/ue4-style-guide-rus

Попытка сделать проекты на Unreal Engine 4 более стабильными

GNU General Public License v3.0GPL-3.0

Руководство по стилю проекта UE4 от Gamemakin, перевод КоМиГо {

Наиболее разумный подход к Unreal Engine 4

Создание этого руководства было вдохновлено, по большей части, стайл-гайдом Javascript от Airbnb (En).

Analytics #

Английские термины и их русификация (Levels/Maps)

(От переводчика) Многие вещи будут называться в английском языке, но спокойно мешаться с русскими вариантами. Так, стайл-гайд — это руководство по стилю, ассет — материал для разработки.

Плагин для автопроверки Unreal Engine 4

Автоматизированный способ проверки соответствия вашего проекта этому руководству можно найти на маркете Unreal Engine. Код плагина станет бесплатен, но чтобы использовать этот плагин без сборки UE4 по его исходникам, понадобится использовать версию с маркета.

Как ссылаться на этот документ

Все разделы этого руководства пронумерованы для быстрой адресации. К английской (и самой актуальной) версии руководства можно сослаться, просто добавив хеш-тег ко ссылке http://ue4.style Например, если вы хотите отправить своему другу ссылку на первый принцип руководства, добавьте #0.1 в конец ссылки — получится http://ue4.style#0.1.

Форки и переводы

Если вы создали примечательный форк, который не получится организовать в pull-request, отправьте pull request на его добавление сюда. Так же делаем и с переводами.

Основные термины

Карты/Уровни (Levels/Maps)

Слово 'карта' в основном используется в обозначении слова 'уровень' — эти слова считаем взаимозаменяемыми. То же и с английскими Level и Map. О терминологии уровня смотрите здесь (En) и здесь (RU).

Использование верхнего и нижнего регистра

Есть несколько разных способов, как называть вещи. Вот самые популярные методики:

ДельфиСтиль

Каждое слово начинается с большой буквы, а всё слово пишется без пробелов, нижних пробелов, дефисов и т.п. Например: DesertEagle, StyleGuide, ASeriesOfWords.

верблюжийСтиль

Похож на ДельфиСтиль, но первая буква пишется в нижнем регистре. Например: desertEagle, styleGuide, aSeriesOfWords.

Змеиный_стиль (а.к.а. snake_case)

Использование регистра в начале слов не определено, но слова разделяются нижним пробелом. Например: desert_Eagle, Style_Guide, a_Series_of_Words.

0. Принципы

Эти принципы были адаптированы под UE из руководства по стилю idomatic.js (En).

0.1 Если в вашем проекте UE4 уже используется руководство стиля, вы должны следовать ему

Если вы работаете над существующим проектом, или в команде, которая уже использует руководство стиля, вы должны ему (руководству) следовать. Во всех различиях между имеющимся и новым руководством стиля приоритет отдаётся имеющемуся.

Руководство по стилю, при этом, постоянно меняющийся документ, и рекомендуется предлагать вносить правки в ваше имеющееся руководство по стилю (и в этот документ), если это принесёт реальную пользу сообществу UE.

"Споры по поводу стиля не имеют смысла. Должно быть руководство по стилю, а вы должны следовать ему".

Rebecca Murphey

0.2 Вся структура проекта, материалы для разработки, код в любом Unreal Engine 4 проекте должны выглядеть так, будто всё это создано одним человеком — не важно, как много людей на самом деле участвует

Смена проекта не должна требовать от вас переучиваться под новый стиль и структуру. Использование руководства по стилю избавит вас от гадания на кофейной гуще и неопределённости.

Также, руководство по стилю улучшает продуктивность создателей контента и управляемость проектом, т.к. каждому не требуется думать о стиле — достаточно просто воспользоваться руководством. Это руководство по стилю разрабатывается с учётом лучших практик, и его использование снизит частоту появления трудно отслеживаемых проблем.

0.3 Мы помогаем друзьям следовать хорошему стилю

Если вы видите, что кто-то работает не по вашему руководству стиля, или вовсе без какого-либо — объясните это тому человеку.

При работе в комаде и во время обсуждений в духе Unreal Slackers (EN) постоянство стиля также помогает быстро найти отклик на свою проблему. Никому не хочется рыться в макаронах блюпринтов и изучать непонятные названия материалов для разработки.

Если вы помогаете тому, кто следует другому, но постоянному и понятному руководству стиля, вы сможете к нему адаптироваться. Если вы увидили, что этот кто-то не следует какому-либо руководству стиля, отправьте ему ссылку на этот документ.

0.4 Команда без руководства стиля — не моя команда

Одним из первых ваших вопросах при вступлении в команду разработчиков на UE4 должен быть "У вас есть руководство стиля?" Если его нет, то следует с подозрением относиться ко способности этих людей работать в команде.

Содержание

  1. Соглашение о наименованиях
  2. Структура папок проекта
  3. Блупринты

1. Соглашение о наименованиях #

Соглашение о наименованиях должно восприниматься как закон. В проекте, следующем соглашению о наименованиях, легко управлять ассетами, искать и обрабатывать их.

В большинстве случаев, ассетам присваивается префикс-аббревиатура на основе названия типа этого ассета + нижний пробел _.

1.0 Русский и иные языки (от переводчика)

Использование русских и иных языков в названиях ассетов строго запрещается. Нет ничего хуже, чем пытаться понять проект с французскими названиями, когда вы не владеете таким языком. Точно так же будет плохо зарубежным друзьям при разборе вашего проекта.

Такие проекты нельзя будет передавать лицам из других стран, когда вам потребуется помощь. Также, не-латинские символы могут вызвать ошибки при компиляции, преобразовании и в ходе других внутренних процессов UE4 и сторонних плагинов — такие ошибки будет трудно отловить и исправить, так что лучше не делайте их вообще.

Не бойтесь пользоваться переводчиком. Лучше чудаковатое название на английском, нежели написанное транслитом слово Pchela, или, того хуже, так и оставленное на русском Пчела.

1.1 Базовое название - Префик_БазовоеНазвание_Вариант_Суффикс #

У каждого ассета должно быть своё базовое название. Оно используется как средство логической группировки материалов разработки. Любой ассет, являющийся частью определённой логической группы, должен следовать стандарту Префик_БазовоеНазвание_Вариация_Суффикс.

Использование схемы Префик_БазовоеНазвание_Вариация_Суффикс с её осознанием уже гарантирует создание "хороших" имён. Вот подробные правила по использованию этой схемы:

  • Префикс и Суффикс определяется типом ассета, исходя из таблиц Модификаторов имён ассетов.
  • Базовое название определяется коротким и легко отличимым названием касательно предметной области вашей группы ассетов. Например, если у вас есть персонаж Вася, то все ассеты Васи должны содержать БазовоеНазвание = Vasya.
  • Для особенных или уникальных вариантов ассета используйте Вариант — короткое и легко различимое имя, отражающее логическую группировку ассетов, образующих подмножество на основе базового имя ассета. Например, если у Васи есть несколько скинов, то у этих скинов должно быть всё то же базовое имя Vasya, но также и Вариант. "Злой" скин можно назвать Vasya_Evil, а скин "Ретро"— Vasya_Retro.
  • Для уникальных но схожих ассетов, относящихся к одной группе, добавляется нумерующий Вариант — двузначное число, нумерация которого начинается с 01. Например, если ваш художник окружения генерирует валуны, которые нельзя просто так взять и назвать, то их можно назвать как Rock_01, Rock_02, Rock_03, и т.д. За исключением редких случаев, не используйте трёхзначное число. Если у вас более 100 ассетов в одной группе, вам следует разбить её на несколько других, используя другие базовые названия или варианты.
  • В зависимости от того, как у вас создаются ассеты, вы можете использовать несколько имён-вариантов, друг за другом. Например, если вы создаёте ассеты для пола, вам будет нужно использовать базовое имя Flooring с вариантами вроде Flooring_Marble_01, Flooring_Maple_01, Flooring_Tile_Squares_01.

1.1 Примеры

1.1e1 Вася
Тип ассета (RU) Тип ассета (EN) Название ассета
Скелетный меш Skeletal Mesh SK_Bob
Материал Material M_Bob
Текстура (Diffuse/Albedo) Texture (Diffuse/Albedo) T_Bob_D
Текстура (Normal) Texture (Normal) T_Bob_N
Текстура (Злой Diffuse) Texture (Злой Diffuse) T_Bob_Evil_D
1.1e2 Валуны
Тип ассета (RU) Тип ассета (EN) Название ассета
Статичный меш (01) Static Mesh (01) S_Rock_01
Статичный меш (02) Static Mesh (02) S_Rock_02
Статичный меш (03) Static Mesh (03) S_Rock_03
Материал Material M_Rock
Экземпляр материала (Снег) Material Instance (Snow) MI_Rock_Snow

1.2 Модификаторы имён ассетов #

Используйте эти таблицы наряду с базовым названием, когда именуете ассеты.

Подразделы

1.2.1 Часто используемые

1.2.2 Анимация

1.2.3 Искусственный интеллект

1.2.4 Блупринты

1.2.5 Материалы

1.2.6 Текстуры

1.2.7 Разное

1.2.8 Paper 2D

1.2.9 Физика

1.2.10 Звуки

1.2.11 Графический интерфейс пользователя

1.2.12 Эффекты

1.2.1 Часто используемые #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Карта / уровень Level / Map Должны быть в папке Maps.
Уровень (постоянный) Level (Persistent) _P
Уровень (аудио) Level (Audio) _Audio
Уровень (освещение) Level (Lighting) _Lighting
Уровень (геометрия) Level (Geometry) _Geo
Уровень (геймплей) Level (Gameplay) _Gameplay
Блупринт Blueprint BP_
Материал Material M_
Статичный меш Static Mesh S_ или SM_ Выберите одно. Лучше S_.
Скелетный меш Skeletal Mesh SK_
Текстура Texture T_ _? См. Текстуры
Система частиц Particle System PS_
Виджет-блупринт Widget Blueprint WBP_ или WB_ Выберите одно. Лучше WBP_.

1.2.2 Анимация #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Сдвиг прицела Aim Offset AO_
Сдвиг прицела 1D Aim Offset 1D AO_
Блюпринт анимации Animation Blueprint ABP_
Композиция анимации Animation Composite AC_
Монтаж анимации Animation Montage AM_
Последовательность анимаций Animation Sequence A_ or AS_ Выберите одно. Лучше A_.
Пространство смешивания Blend Space BS_
Пространство смешивания 1D Blend Space 1D BS_
Последовательность уровня Level Sequence LS_
Точка смешивания Morph Target MT_
Paper Flipbook Paper Flipbook PFB_
Риг Rig Rig_
Скелетный меш Skeletal Mesh SK_
Скелет Skeleton SKEL_

1.2.3 Искусственный интеллект #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
ИИ контроллер AI Controller AIC_
Дерево поведений Behavior Tree BT_
Доска состояний Blackboard BB_
Декторатор Decorator BTDecorator_
Сервис Service BTService_
Задание Task BTTask_

1.2.4 Блупринты #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Блупринт Blueprint BP_
Библиотека блупринт-функций Blueprint Function Library BPFL_
Блупринт-интерфейс Blueprint Interface BPI_
Библиотека бупринт-макросов Blueprint Macro Library BPML_ По возможности не используйте библиотеки макросов вообще
Перечисление Enumeration E Без нижнего пробела
Структура Structure F или S Без нижнего пробела
Блупринт-виджет Widget Blueprint WBP_ или WB_ Выберите одно. Лучше WBP_

1.2.5 Материалы #

Тип ассета (RU) Тип ассета (En) Префикс Суффикс Примечания
Материал Material M_
Материал пост-обработки Material (Post Process) PP_
Функция материалов Material Function MF_
Экземпляр материала Material Instance MI_
Материал Parameter Collection Material Parameter Collection MPC_
Профиль подповерхности Subsurface Profile SP_ или SSP_ Выберите одно. Лучше SP_
Физический материал Physical Materials PM_

1.2.6 Текстуры #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Текстура Texture T_
Текстура (Diffuse/Альбедо/Основной цвет) Texture (Diffuse/Albedo/Base Color) T_ _D
Текстура (Нормаль) Texture (Normal) T_ _N
Текстура (Грубость) Texture (Roughness) T_ _R
Текстура (Alpha/Прозрачность) Texture (Alpha/Opacity) T_ _A
Текстура (Нейтральный свет) Texture (Ambient Occlusion) T_ _O или _AO Выберите одно. Лучше _O
Текстура (Неровность) Texture (Bump) T_ _B
Текстура (Излучение) Texture (Emissive) T_ _E
Текстура (Маска) Texture (Mask) T_ _M
Текстура (Блеск) Texture (Specular) T_ _S
Текстура (упакованная) Texture (Packed) T_ _* См. примечание об упаковке текстур.
Текстура-куб Texture Cube TC_
Текстура-медиа Media Texture MT_
Область прорисовки Render Target RT_ или RTT_ Выберите одно. Лучше RT_
Область прорисовки текстуры-куба Cube Render Target RTC_
Профиль освещения Texture Light Profile TLP

<a name="anc-textures-packing"

1.2.6.1 Упаковка текстур #

Упаковка сразу нескольких слоёв информации в одну текстуру — стандартная практика. Примером служит упаковка текстур Emissive, Roughness, Ambient Occlusion как красный, зелёный и синий каналы одной текстуры. Чтобы построить суффикс для таких текстур, просто последовательно запишите суффиксы отдельных масок из таблицы выше, напр. _ERO.

Часто альфа-канал включают в карту Diffuse/Альбедо. Так как это стандартная практика, добавлять суффикс A в суффикс _D необязательно.

Упаковывать сразу 4 канала информации в одну текстуру (в RGBA) не рекомендуется, за исключением использования канала A как Alpha вместе с картой Diffuse/Альбедо.

1.2.7 Разное #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Анимированное векторное поле Animated Vector Field VFA_
Анимация камеры Camera Anim CA_
Цветовая кривая Color Curve Curve_ _Color
Табличная кривая Curve Table Curve_ _Table
Набор данных Data Asset *_ Префикс основывается на классе
Таблица данных Data Table DT_
Вещественная кривая Float Curve Curve_ _Float
Тип растительности Foliage Type FT_
Эффект физического отклика Force Feedback Effect FFE_
Тип растительности Landscape Grass Type LG_
Слой ландшафта Landscape Layer LL_
Данные Matinee Matinee Data Matinee_
Медиапроигрыватель Media Player MP_
Библиотека объектов Object Library OL_
Перенаправление Redirector Перенаправление должно быть исправлено при первой возможности
Атлас спрайтов Sprite Sheet SS_
Статичное векторное поле Static Vector Field VF_
Настройка тач-интерфейса Touch Interface Setup TI_
Векторная кривая Vector Curve Curve_ _Vector

1.2.8 Paper 2D #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Набор кадров Paper Flipbook PFB_
Спрайт Sprite SPR_
Группа атласов спрайтов Sprite Atlas Group SPRG_
Карта тайлов Tile Map TM_
Тайлсет Tile Set TS_

1.2.9 Физика #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Физический материал Physical Material PM_
Физический ассет Physical Asset PHYS_
Разрушаемый меш Destructible Mesh DM_

1.2.10 Звуки #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Голос диалога Dialogue Voice DV_
Запись диалога Dialogue Wave DW_
Звукозапись медиа Media Sound Wave MSW_
Эффект ревербации Reverb Effect Reverb_
Затухание звука Sound Attenuation ATT_
Класс звука Sound Class Без префиксов/суффиксов. Должен быть в отдельной папке SoundClasses
Очерёдность звуков Sound Concurrency _SC Должен быть назван на основе SoundClass
Композиция звуков Sound Cue A_ _Cue
Микс звуков Sound Mix Mix_
Звукозапись Sound Wave A_

1.2.11 Графический интерфейс пользователя #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Шрифт Font Font_
Кисть Slate Slate Brush Brush_
Стиль виджета Slate Slate Widget Style Style_
Виджет-блупринт Widget Blueprint WBP_ или WB_ Выберите одно. Лучше WBP_

1.2.12 Эффекты #

Тип ассета (RU) Тип ассета (EN) Префикс Суффикс Примечания
Система частиц Particle System PS_
Материал постобработки Material (Post Process) PP_

2. Структура папок проекта #

Структура папок также должна восприниматься как закон. Она проекта так же важна, как и соглашение о наименованиях. Они тесно связаны, и нарушение правил любого из них приводит к ненужному хаосу в проекте.

Есть несколько способов организации контента UE4 проекта, но в этом гайде мы будем использовать структуру, которая основывается больше на возможности поиска и фильтрации в Content Browser — вместо того, чтобы под каждый тип материалов проекта создавать отдельную папку, будет использоваться фильтр/поиск в UE.

Если вы используете соглашение о наименованиях выше, то использование папок вроде Meshes, Textures, и Materials будет избыточным действием, т.к. все ассеты уже отсортированы по префиксу и могут быть отфильтрованы в content browser.

2e1 Пример организации папок проекта

|-- Content
    |-- GenericShooter
        |-- Art
        |   |-- Industrial
        |   |   |-- Ambient
        |   |   |-- Machinery
        |   |   |-- Pipes
        |   |-- Nature
        |   |   |-- Ambient
        |   |   |-- Foliage
        |   |   |-- Rocks
        |   |   |-- Trees
        |   |-- Office
        |-- Characters
        |   |-- Bob
        |   |-- Common
        |   |   |-- Animations
        |   |   |-- Audio
        |   |-- Jack
        |   |-- Steve
        |   |-- Zoe
        |-- Core
        |   |-- Characters
        |   |-- Engine
        |   |-- GameModes
        |   |-- Interactables
        |   |-- Pickups
        |   |-- Weapons
        |-- Effects
        |   |-- Electrical
        |   |-- Fire
        |   |-- Weather
        |-- Maps
        |   |-- Campaign1
        |   |-- Campaign2
        |-- MaterialLibrary
        |   |-- Debug
        |   |-- Metal
        |   |-- Paint
        |   |-- Utility
        |   |-- Weathering
        |-- Placeables
        |   |-- Pickups
        |-- Weapons
            |-- Common
            |-- Pistols
            |   |-- DesertEagle
            |   |-- RocketPistol
            |-- Rifles

Предпосылки формирования именно такой структуры проекта описаны ниже.

Подразделы

2.1 Названия папок

2.2 Папки верхнего уровня

2.3 Папки разработчиков

2.4 Карты

2.5 Ядро игры

2.6 Assets и AssetTypes

2.7 Большие наборы

2.8 Библиотека материалов

2.1 Названия папок #

Все названия папок подчиняются единому набору правил.

2.1.1 Всегда используйте ДельфиСтиль* #

ДельфиСтиль означает написание каждого слова строки с большой буквы, без пробелов и нижних пробелов. Например, DesertEagle, RocketPistol, и ASeriesOfWords.

См. Использование верхнего и нижнего регистра.

2.1.2 Никогда не ставьте пробелы #

В дополнение к 2.1.1, не используйте пробелы. Пробелы могут вызвать падения различных средств компиляции и пакетной обработки. В идеале, путь к самому проекту тоже не должен содержать пробелы и быть расположен в папке вроде D:\Project, а не C:\Пользователи\Моё имя\Мои документы\Unreal Projects.

2.1.3 Никогда не используйте символы юникода #

(Прим. пер.) Это также касается использования русского языка.

Если одного из ваших персонажей зовут 'Zoë', его папка должна называться Zoe. Символы юникода могут быть хуже пробелов для инженерных инструментов, а некоторые инструменты UE не поддерживают символы юникода и в путях к файлам.

Если ваш проект страдает по необъяснимым причинам от непонятных ошибок, а имя пользователя вашего компьютера содержит символы юникода (в т.ч. и русские буквы), то любой проект в папке Мои документы будет страдать аналогичным образом. Чаще всего достаточно переместить папку проекта в, скажем, D:\Project, и эти загадочные ошибки исчезнут.

Использование символов, отличных от a-z, A-Z, и 0-9, напр. @, -, _, ,, *, и # тоже может привести к неожиданным и трудно отслеживаемым последствиям на других платформах, в системах контроля версиями и неотшлифованных средствах разработки.

2.2 Используйте папку верхнего уровня для всех ассетов вашего проекта #

Все материалы разработки вашего проекта должны располагаться в папке, названной согласно самому проекту. Например, если проект называется 'Generic Shooter', то всё его содержимое должно лежать в папке Content/GenericShooter.

Папка Developers не для материалов разработки вашего проекта, и потому не относится к папке проекта. См. 2.2 для подробного обоснования.

Есть несколько причин использования такого подхода.

2.2.1 Отсутсвие глобальных ассетов

В стайл-гайдах по кодингу часто пишут о том, что вы не должны засорять глобальное пространство имён. Этот пункт следует этому же принципу. Если ассет существует вне проекта, велик риск роста несоблюдения структуры проекта, т.к. такой ассет становится дурным примером для других.

У каждого материала разработки должна быть своя цель, иначе он не принадлежит вашему проекту. Если ассет экспериментальный и не должен использоваться в проекте, его лучше положить в папку Developer.

2.2.2 Уменьшение риска конфликтов при миграции

При работе над несколькими проектами команда нередко копирует ассеты из проекта в проект, если эти ассеты подходят и полезны сразу двум проектам. В таких случаях лучше произвести копию ресурсов через инструмент Migrate в Content Browser, т.к. он не только копирует сам ассет, но и все его зависимые ресурсы.

Эти зависимости легко генерируют проблемы при слиянии. Если у ваших двух проектов нет одноимённых с названием проекта папок в верхнем уровне контента, то ассеты с аналогичным названием (а то и уже адаптированные из другого проекта) могут быть уничтожены инструментом миграции.

К слову, это главная причина, по которой Epic требует такой же схемы в товарах Магазина.

После миграции, безопасное слияние ассетов может быть сделано через инструмент 'Replace References' content browser-а. После завершения миграции и слияния, лишняя папка на верхнем уровне проекта должна быть удалена. Это гарантирует 100% безопасность ваших миграций.

2.2.2e1 Пример: главный материал

Скажем, вы сделали главный материал-шаблон в своём проекте и хотели бы использовать его в другом. Для этого вы мигрировали его. Если этот ассет не в верхней папке проекта, у него может быть название вроде Content/MaterialLibrary/M_Master, и, если в целевом проекте ещё нет такого главного материала, то ошибки не возникнет.

В ходе разработки проекта каждый такой главный материал дорабатывается под нужды конечного проекта.

Проблема возникает, когда, скажем, художник из одного проекта сделал симпатичный модульный набор статичных мешей, и кто-нибудь захотел включить этот набор в другой проект. Если художник — создатель набора — использовал экземпляры материала на основе главного Content/MaterialLibrary/M_Master, то при миграции возможна ошибка слияния с ранее мигрировавшим ассетом Content/MaterialLibrary/M_Master.

Эту ошибку трудно предупредить и объяснить. Человек, мигрирующий набор мешей, может быть не наслышан о разработке обоих главных материалов, и потому вовсе не осведомлён о том, что меши зависят от экземпляров материалов, которые, в свою очередь, зависят от главного материала. Но инструмент Migrate должен собрать всю сеть зависимостей с целью последующей работоспособности мигрированных ассетов, и поэтому захватит Content/MaterialLibrary/M_Master с исходного проекта, чем перезапишет аналогичный файл в конечном проекте.

Если эти материалы не совместимы в принципе, то велик риск обрушить всю библиотеку материалов вашего проекта. А ведь всё по причине отсутствия папки для проекта на верхнем уровне! Так простое перемещение мешей может наделать массу лишней работы.

2.2.3 Примеры, шаблоны и товары с Магазина безопасны (почти)

В дополнение к 2.2.2: если член команды решит добавить пример, файлы шаблона или товар с Магазина, эти ассеты гарантированно не будут пересекаться с файлами вашего проекта, т.к. у них всех есть своя папка верхнего уровня (в том случае, если имена между всеми ними и вашим проектом уникальны).

Тем не менее, нельзя на 100% доверять товарам с Магазина — не все из них следуют правилу папки верхнего уровня. Существует множество ассетов, где большая часть контента которых расположена в папке верхнего уровня, но при этом также используется контент из примеров движка (напр., шаблоны вроде FirstPersonShooter или Starter Content Pack). Эти ассеты из примеров могут быть изменены под нужды товара. Также, карты из этих примеров засоряют корневую папку Content и тоже могут пересекаться.

Если придерживаться правилу 2.2, худшим сценарием будет использование нескольких товаров с магазина, которые зависят от одного и того же проекта-шаблона. Они могут повредить друг друга, но если именно ваши ассеты располагаются в отдельной папке ресурсов проекта, такой конфликт не затронет ваши наработки.

2.2.4 DLC, подпроектами, патчами проще управлять

Если вы планируете выпустить DLC для своего проекта, или же в нём есть несколько связанных подпроектов, все ассеты этих DLC и подпроектов должны находиться в своих папках верхнего уровня. Такие подпроекты затем могут быть мигрированы из проекта или просто не участвовать в сборке. Техника создания индивидуальных папок верхнего уровня помогает с лёгкостью исключить DLC из выпечки основного проекта. Подпроекты также мигрируются с наименьшими усилиями. А если вам нужно в патче, например, заменить один материал или ввести специфичный ассет, меняющий поведение игры, но при этом вы не хотите ломать главный проект, все эти изменения тоже можно вывести в отдельную папку.

2.3 Используйте папку Developers для локального тестирования #

Очень часто во время разработки проекта участники команды создают, в некотором роде, "песочницу", где они проводят свои эксперименты без влияния на главный проект. Так как такая практика осуществляется на постоянной основе, члены команды могут пожелать загрузить их ассеты в систему контроля версий. Не все команды требуют использования папки Developers, но те, что её используют, часто испытывают одни и те же проблемы с загруженными в систему контроля версиями ассетами.

Участники команды могут по случайности начать использовать те ассеты, которые ещё не готовы к этому, а затем, при их удалении, вызывают ошибки. Например, художник может дорабатывать набор модульных статичных мешей и всё ещё корректирует их размерность и соответствие сетке. Если левел-дизайнер обнаружит такой набор в главной папке проекта, он может использовать набор во всём уровне, не зная, что этот набор позднее будет претерпевать серьёзные изменения (не исключая удаление набора). Следствием этой проблемы будет масса переделок для всей команды.

Если эти модульные меши располагаются в папке разработчиков, у левел-дизайнера не было бы причин использовать этот набор, и проблемы бы не возникло. У Content Browser есть специальная настройка в View Options, которая прячет папки разработчиков (и по умолчанию она включена), что делает случайное использование экспериментальных ресурсов невозможным.

Как только ассеты готовы, художнику достаточно переместить эти материалы разработки в соответствующую папку проекта и подфиксить редиректоры. По сути, это "продвижение" ассетов из экспериментальной зоны в продакшн.

2.4 Все уровни* располагаются в отдельной папке под названием Maps #

Файлы уровней отличаются от других, и нормальной практикой считается использование своей системы наименований, особенно, если команда работает с подуровнями или стримингом карт. Не важно, как организуются эти карты в вашем проекте — все они должны быть расположены в папке /Content/Project/Maps.

Возможность открыть определённую карту без необходимости объяснять, где она находится, серьёзно экономит время. Часто карты группируются в папки вроде Maps/Campaign1/ или Maps/Arenas, но главное, что все они находятся в папке /Content/Project/Maps.

Такой подход также облегчает работу инженеров по сборке. Когда все карты в одной папке, не нужно перерывать весь проект в поиске предмета сборки/исключения из сборки. Становится труднее случайно не подготовить карту к сборке. Польза проявляется и при запуске скриптов для запекания освещения, а также в ходе процессов контроля качеством.

2.5 Используйте папку Core ("Ядро") для особо важных блупринтов и других ассетов #

Используйте папку /Content/Project/Core для тех ассетов, которые являются основой разработки вашего проекта. Например, основные GameMode, Character, PlayerController, GameState, PlayerState и связанные блупринты должны находиться именно здесь.

Это как знак "не трогай" для других участников команды. У не-инженеров обычно нет особых причин заглядывать в эту папку. При соблюдении хорошего стиля кодинга дизайнеры смогут выполнять все изменения, касающиеся геймплея, в дочерних классах. Левел-дизайнеры должны использовать заранее приготовленные блупринты в специально отведенных папках, вместо того, чтобы всё время использовать и модифицировать базовые классы.

Например, если в вашем проекте есть пикапы, которые могут быть расположены в уровне, для них должен быть базовый класс в папке Core/Pickups. Такой класс будет описывать базовое поведение пикапа. Конкретные пикапы, вроде аптечки или патронов уже будут располагаться в папке /Content/Project/Placeables/Pickups/. Гейм-дизайнеры могут спокойно редактировать эти пикапы по своему желанию, но они не должны трогать папку Core/Pickups, т.к. это косвенно может повредить работоспособность всех пикапов вообще.

2.6 Не создавайте папки Assets или AssetTypes #

2.6.1 Создание папки Assets является избыточным действием #

Все ассеты и так являются ассетами.

2.6.2 Создание папок Meshes, Textures, или Materials — лишнее #

Все ассеты именуются с учётом их типа, и их названия уже включают указание типа в префиксе. Такие папки только добавляют избыточности в проект и легко заменяются фильтрами в Content Browser.

Для того, чтобы вывести только статичные меши в папке Environment/Rocks/, достаточно включить фильтр Static Mesh. Если все ассеты названы правильно, то они также будут отсортированы в алфавитном порядке, независимо от префиксов. Чтобы вывести и статичные, и скелетные меши, включите сразу два фильтра. Так вам не понадобится зажимать Ctrl и выделять несколько папок в проводнике Content Browser-а.

Есть и небольшое преимущество в длине строки: префикс S_ (статичный меш) — всего 2 символа, а папка Meshes/ — семь.

Отсутствие таких папок устраняет ошибки с помещением статичных мешей в папку материалов.

2.7 Очень большие наборы ассетов получают свою собственную иерархию #

Это псевдо-исключение к правилу 2.6.

Есть определённые виды ассетов, которые образуют большой объём связанных по смыслу файлов, но каждый такой файл обладает своей уникальной целью. Чаще всего это папки с анимациями и аудио. Мы можем добавить новый уровень иерархии в папке тогда, когда эти подуровни образуют группы в 15+ семантически связанных файлов. Не забывайте делать этим подуровням чёткие и наполненные смыслом названия.

Например, есть анимации, которые используются несколькими персонажами — они должны находиться в папке Characters/Common/Animations , где могут быть поддиректории Locomotion или Cinematic.

Это правило неприменимо к ассетам вроде текстур или материалов. Это норма, когда у папки Rocks огромное количество текстур, соответствующее аналогичному количеству камней; при этом каждая из этих текстур относится к небольшому количеству мешей и должна быть названа соответствующим образом. Не являются исключением и текстуры в библиотеке материалов.

2.8 MaterialLibrary (библиотека материалов) #

Если ваш проект использует главные материалы (материалы-шаблоны), слоистые материалы, или любую другую форму многократно используемых материалов и текстур, которые не принадлежат какому-нибудь подмножеству ассетов, они должны быть расположены в папке Content/Project/MaterialLibrary.

Так все "глобальные" материалы будут находиться в одном легкодоступном месте.

Это также способствует политике "только экземпляры материалов" ('material instances only') в вашем проекте. Если все художники и рабочие материалы используют экземпляры материалы, то обычные материалы будут существовать только в пределах папки. Проверить соблюдение этой политики можно просто поиском основных материалов в папках, отличных от MaterialLibrary.

Папка MaterialLibrary необязательно должна состоять только из материалов. Общие текстуры-помощники, функции материалов и другие аналогичные ассеты могут храниться в этой же папке. Мы также можем объединять их в семантические группы папками. Например, общие текстуры с шумом можно объединить в папке MaterialLibrary/Utility.

Все материалы, предназначенные для тестирования и/или отладки должны располагаться в папке MaterialLibrary/Debug. Это позволяет убрать такие материалы при сборке релизной версии, а если они используются в версии для сборки, сообщение об ошибке укажет на эти связи.

3. Блупринты #

Этот раздел направлен на блупринты и их внутреннее обустройство. Где возможно, эти правила подчиняются стандарту кодинга Epic.

Подразделы

3.1 Компиляция

3.2 Переменные

3.1 Компиляция #

Все блупринты должны компилиться без предупреждений и ошибок. Вы должны исправить все предупреждения и ошибки при первой возможности, т.к. они сразу могут превратиться в снежный ком проблем и вызвать непредвиденное поведение.

Никогда не отправляйте (submit) сломанные блупринты в систему контроля версиями. Если вам нужно хранить их в системе контроля версий, отложите их (shelve).

Сломанные блупринты могут вызвать массу проблем — таких, как поломанные связи, некорректное поведение, падения при сборке, частые ненужные перекомпиляции. Один сломанный блупринт способен порушить всю вашу игру.

3.2 Переменные #

Подразделы

3.2.1 Именование

3.2.2 Editable

3.2.3 Категории

3.2.4 Уровни доступа

3.2.5 Advanced

3.2.6 Transient

3.2.7 SaveGame

3.2.8 Переменные Config

3.2.1 Именование #

3.2.1.1 Существительные #

Все не-булевые переменные должны быть чёткими, недвусмысленными, описательными существительными.

3.2.1.2 ДельфиСтиль #

Все не-булевые переменные должны быть написаны в ДельфиСтиле.

3.2.1.2e Примеры:
  • Score
  • Kills
  • TargetPlayer
  • Range
  • CrosshairColor
  • AbilityID

3.2.1.3 Префикс b для булевых переменных #

Все булевы значения должны следовать ДельфиСтилю, но иметь префикс в виде малой b.

Например: bDead и bEvil, но не Dead и Evil.

Редактор блупринтов в UE4 распознаёт эту b и не выводит её при выводе удобочитаемого текста.

3.2.1.4 Имена булевых значений #

3.2.1.4.1 Общая информация и независимые состояния #

Все булевые переменные должны быть качественными прилагательными. Не включайте вопросительные слова, например, Is. Такие слова зарезервированы для функций.

Например: используйте bDead и bHostile, но не bIsDead и bIsHostile.

Старайтесь также не использовать в названиях глаголы (напр. bRunning). Глаголы, как правило, ведут к сложным состояниям.

3.2.1.4.2 Сложные состояния #

Не используйте булевы переменные для описания сложных и/или зависимых состояний. Это приводит к затруднённому управлению этих состояний и нечитабельности. Вместо этого используйте перечисление (Enum).

Например: описывая пушку, не используйте bReloading и bEquipping, если пушка не может одновременно заряжаться и быть в процессе экипировки. Обозначьте перечисление EWeaponState и используйте вместо булевых переменных одну переменную WeaponState соответствующего типа. Так добавлять новые состояния пушке будет проще.

Пример: не используйте bRunning ("Бежит"), если вам также нужны bWalking ("Ходит") и bSprinting ("Спринтует", кратковременное ускорение). Вам нужно перечисление с чёткими названиями вариантов.

3.2.1.5 Предметная область переменной определяется самим блупринтом, но не названием #

Все названия переменных не должны быть избыточны и упоминать свой контекст, так как все переменные из блупринта уже обладают своим контекстом.

3.2.1.5e Пример:

Пусть у нас есть блупринт BP_PlayerCharacter.

Нельзя

  • PlayerScore
  • PlayerKills
  • MyTargetPlayer
  • MyCharacterName
  • CharacterSkills
  • ChosenCharacterSkin

Названия этих переменных избыточны. Если переменные описаны в BP_PlayerCharacter, то это значит, что они характеризуют именно BP_PlayerCharacter.

Надо

  • Score
  • Kills
  • TargetPlayer
  • Name
  • Skills
  • Skin

3.2.1.6 Не включайте названия атомарных типов #

Атомарные, или примитивные, переменные — это такие переменные, что описывают своё значение в простейшей форме — напимер, в виде булевого значения, целочисленного, вещественного, перечисления (Enum).

Строки (именно String, не Text!), Rotator и векторы тоже считаются атомарными в блупринтах и тоже не должны включать названия типа в своих именах. Тем не менее, с технической точки зрения они не являются атомарными.

Хоть вектора и состоят каждый из трёх вещественных значений, с векторами часто работают как с единым целым. То же и с Rotator.

Нельзя считать Text атомарным типом, т.к. они включают в себе скрытый функционал по локализации. Атомарным типом является String, но не Text.

Атомарные переменные не должны включать название типа переменной в своём названии.

Например: используйте Score, Kills и Description, но не ScoreFloat, FloatKills, DescriptionString.

Единственное исключение этого правила — когда имеется ввиду "количество того-то" и когда использование имени без типа переменной приводит к затруднению чтения.

Например: генератор забора создаёт X досок. Это X нужно сохранить в переменной NumBoards или BoardsCount, но не Boards, т.к. Boards может уже относиться к массиву переменных типа Board.

3.2.1.7 Нужно включать имена неатомарных типов в названиях переменных #

Неатомартные, или сложные, переменные — это такие, что отражают свою информацию как набор атомарных переменных. Структуры, классы, интерфейсы, примитивы со скрытым поведением (вроде Text и Name) попадают под это правило.

В то время, как массив атомарных значений — это список атомарных переменных, массивы не меняют "атомарность" типа переменных.

Эти переменные должны включать названия их типов, но также и подразумевать контекст использования.

Если класс владеет экземпляром сложной переменной, напр. если у BP_PlayerCharacter есть BP_Hat, то она должна называться как тип переменной, без каких-либо изменений.

Например: используйте Hat, Flag, и Ability, но не MyHat, MyFlag, или PlayerAbility.

Если класс не владеет значением сложной переменной, то нужно использовать существительное вместе с названием типа переменной.

Например: если у BP_Turret есть способность нацеливаться на BP_PlayerCharacter, она (туррель) должна хранить переменную TargetPlayer — так в контексте BP_Turret будет понятно, что это ссылка на другую переменную сложного типа, которой туррель не владеет.

3.2.1.8 Массивы #

Массивы подчиняются правилам выше, но описываются во множественном числе.

Например: используйте Targets, Hats и EnemyPlayers, но не TargetList, HatArray, EnemyPlayerArray.

3.2.2 Редактируемые (Editable) переменные #

Все переменные, которые спокойно можно менять с целью настройки поведения блупринта, должны быть отмечены как Editable.

Аналогично, все те переменные, которые небезопасно редактировать и которые не должны быть раскрыты дизайнерам, не должны быть отмечены как Editable, за исключением тех случаев, когда переменная требует флага Expose On Spawn.

Не помечайте переменные флагом Editable произвольным образом.

3.2.2.1 Подсказки #

Все переменные типа Editable, включая те, что были помечены так только из-за флага Expose On Spawn, должны иметь своё описание в поле Tooltip, которое должно показывать, как изменение этого значения меняет поведение блупринта.

3.2.2.2 Слайдеры и пределы допустимых значений #

Все переменные с флагом Editable должны использовать слайдеры (Slider) и пределы допустимых значений (Value Range), если есть хоть какое-нибудь значение, которое не должно использоваться.

Пример: блупринт, генерирующий забор, может иметь редактируемую переменную BoardsCount, и значение -1 не будет являться для него рабочим. Используйте пределы допустимых значений, чтобы обозначить 0 как минимальное значение.

Если редактируемая переменная используется в Construction Script, у неё должен быть настроенный слайдер (Slider Range), который препятствует назначению таких значений, что могут обрушить редактор.

Пределы допустимых значений нужно устанавливать только тогда, когда известны границы этих значений. Если слайдер предотвращает случайный ввод слишком больших значений, то неустановленное значение пределов всё же позволяет указать значения вне диапазона слайдера — "опасные", но всё ещё валидные.

3.2.3 Категории #

Если у класса совсем немного переменных, то использование категорий не требуется.

Если у класса есть некоторое количество переменных (5-10), все переменные с флагом Editable должны обладать своей нестандартной категорией. Для общих переменных создаётся категория Config.

Если у класса большое количество переменных, то все переменные с флагом Editable должны быть помещены в подкатегории внутри Config. Нередактируемые переменные (без флага Editable) должны быть помещены в отдельные категории с понятными названиями.

Вы можете создавать подкатегории, используя символ вертикальной черты |, напр. Config | Animations.

Пример: набор переменных оружия может быть расположен в следующей иерархии:

|-- Config
|   |-- Animations
|   |-- Effects
|   |-- Audio
|   |-- Recoil
|   |-- Timings
|-- Animations
|-- State
|-- Visuals

3.2.4 Уровень доступа переменных #

В C++ есть реализация уровня доступа переменных. Уровень доступа Public означает, что все экземпляры любых классов могут получить доступ к этой переменной. Переменные Protected могут использованы только самим классом и дочерними классами. Private значит, что только сам класс может видеть эти переменные (дочерние не видят).

В блупринтах, по крайней мере — на данный момент —, нет реализации уровня доступа переменных.

Считайте переменные с флагом Editable как публичные. Переменные без этого флага считайте как Protected.

3.2.4.1 Закрытые (Private) переменные #

В том случае, если не известно, должна ли быть переменная доступна только в самом классе, но не в дочерних, не отмечайте переменную как Private. Используйте Protected и закрывайте переменную только тогда, когда вы абсолютно уверены, что хотите ограничить использование переменных в дочерних классах.

3.2.5 Advanced Display #

Если переменная должна быть редактируема, но, в большинстве случаев, нетронута, отметьте её флагом Advanced Display. Переменная будет скрыта, но может быть отображена по клику стрелки в конце категории.

Сам флаг Advanced Display тоже является скрытым за этой стрелкой на панеле Details.

3.2.6 Transient #

Все переменные без флага Editable и которые должны обладать нулевым начальным значением, должны быть помечены как Transient.

Такие переменные не требуют сохранения и загрузки их значения и изначально равны нулю (zero или null). Они полезны для тех случаев, когда требуется ссылка на других объектов и актёров, не известная до запуска игры.

Этот флаг предотвращает сохранение ссылки на эту переменную внутри редактора и ускоряет процесс сохранения и загрузки класса.

3.2.7 Переменные с флагом SaveGame #

Используйте флаг SaveGame только для переменных класса, унаследованного от класса SaveGame. Отмечайте этот флаг, только если SaveGame должен сохранить значение. Временные переменные, не хранимые в слоте сохранения, не должны отмечаться этим флагом.

Не смешивайте SaveGame и Transient — это бесполезно.

3.2.8 Флаг Config Variable #

Не используйте флаг Config Variable. Дизайнерам будет труднее из-за этого контроллировать поведение блупринта. Этот флаг используется только в C++ для редко меняющихся значений, как если бы они были под двойным флагом Advanced Display.

Вклад сообщества

Лицензия

Copyright (c) 2016 Gamemakin LLC

См. файл LICENSE

Наверх

Правки

Мы поощряем клонирование этого репозитория с целью адаптации под правила вашей команды. Ниже, вы можете указать свои правки, чтобы периодически обновлять стайл-гайд без ошибок слияния.

};