Из хаоса в порядок, или «создаем структуру проекта в Unity и не только...»

  • Tutorial
При создании нового проекта он такой чистый, понятный, нет лишнего хлама… он пуст. Чем дольше идет разработка, тем больше в нем появляется лишнего мусора, непонятных папок, файлов, иногда туда могут попасть префабы для других проектов и вся организация летит в Тартар.

Выясняется что организации никогда не было, проекту три года, порядок наводить уже поздно, работать не удобно и вообще…

Добро пожаловать в хаос, вы оказались именно тут потому что:

  • никогда не задумывались зачем нужна структура проекта в Unity
  • в ваших проектах вечный бардак и вы хотите от этого избавиться
  • в поисках новых способов организации
  • потеряли надежду навести порядок в своем проекте

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



Добро пожаловать под кат.

Спасибо всем кто прочитал мой предыдущий материал . Именно комментарии под ним побудили меня написать эту статью. Более содержательную и полезную, с романтичным вступлением но практичным наполнением. Сегодня будем говорить о довольно очевидных вещах, если есть что добавить, смело пишите и предлагайте свои варианты.
К сути.
Зачем нужна структура? — время. Мы экономим кучу времени на отладке, добавлению новых фич, файлов, чистке при условии что наша организация нам понятна и удобна, при условии что она есть. Правильные названия файлов, порядок, таги прочие маленькие хитрости позволяют экономить время.
В сети достаточно подобных материалов с примерами, но не очень много объяснений «почему это так». Опишу решения которые использую сам и чем они удобны конкретно мне. Не думаю что внесу что-то новое, но правильная организация — это начало начал любого проекта.

«Как это сделано»


Взять к примеру коллайдеры для окружения. Какие объекты и плоскости у нас есть?

  • пол
  • стены
  • препятствия(ящики, бочки, камни и прочее)
  • потолок

В иерархии сцены мы можем положить это все в один game object, но искать будет неудобно.

Поэтому мы сделаем отдельный game object для коллайдеров пола, стен, потолка и препятствий.

Как пример уровень из игры



Если у нас больше 10 дочерних объектов то рекомендую писать таг, это упрощает поиск. Опять же коллайдеры, если мы говорим о 2D то используется edge,polygon,box,circle и каждый может быть коллайдером плоскости или препятствия. Можно именовать в виде «coll_edge_N» или «coll_e_N» т.к коллайдеры стен имеют материнский обьект Wall(который в свою очередь имеет материнский обьект Colliders) встает вопрос писать ли таг плоскости «coll_wall_edge_N», стоит для упрощенного поиска, когда количество объектов большое вы сэкономите очень много времени.

Мы получаем нечто подобное.





Организация папок в Unity

Внутри проекта тоже есть достаточно понятные правила.

А именно:

  • должно быть понятно что где лежит
  • понятно куда добавлять новые файлы и исходники
  • структура адаптивная и удобная
  • структура не слишком сложная и не дробленая

Можно конечно кидать что угодно и куда угодно, не задумываясь о организации.

Например так



Можно сделать нечто более организованное с понятной структурой.

Как-то так



А теперь давайте разберем что нужно, что нет.

Очень удобно делить проект на internal assets и external assets, это плюс.
В external assets у нас лежат все сторонние асеты и ничего больше.
Есть отдельная папка Scene в которой лежат все сцены.
Папка scripts тоже отдельно, это удобнее.
Самая интересная папка для нас internal assets
Все что касается видимой части нашей игры лежит именно там.



Какие папки там нужны?

  • Prefabs главная папка для всех префабов
  • Textures/Sprites кому как удобнее и в зависимости от того 2д или 3д проект
  • Materials тут материалы и тут все понятно
  • Shaders аналогично, вопросов немного
  • Animations
  • VFX
  • Sound тут простая организация в самой папке и разделение звуков на BGM, Impact FX и пр.

Как VFX Artist и 2D/3D художник по анимации остановлюсь подробнее на организации именно этих папок.

Для анимации юнита нам нужно сделать animator controller и animation clip, анимационных клипов бывает несколько, поэтому их удобнее уложить в папку. Плюс нужна папка для самого юнита.

Выглядеть это будет так.


Это удобно
Теперь про VFX

В папке с vfx нужна папка textures, materials и по желанию prefabs. VFX артисту удобнее работать в своих папках и не наводить бардак во всем проекте, а следить за порядком в своем огороде. Текстуры для эффектов, это всегда текстуры. Материалы для эффектов имеют разные настройки от additive до alpha blend и иногда одна текстура идет на несколько материалов, если папка текстур рядом то поиск проще. Если вы пишете шейдеры, то тянуть текстуры из папки VFX удобнее, точно так же удобнее и логичнее материалы готового шейдера положить в VFX.
Зачем нужна папка Trash?

Часто нужно что-то удалить, не факт что вы сможете сделать это и все пройдет гладко, часто нечто теряется и если вы не лид программист на проекте, то можете накосячить. Также бывает потребность протестировать фичу/идею и не факт что она приживется и вообще нужна. Именно для этого нужна папка trash, все тесты, все что нужно удалить или все что вы не хотите отправлять с текущим коммитом лучше положить сюда и прописать игнор для гита.

Организация иерархии в Unity

Чуть выше был пример про коллайдеры. Именно этому правилу подчиняется все. В нашем проекте мы применили такое решение.



Мы просто добавили "---chapter name ---" это пустой объект несущий в себе только название. Вроде бесполезная и лишняя штука, но упрощает поиск и понимание иерархии на сцене в разы. Такое просто решение позволяет ускорить визуальный поиск в несколько раз. Например у нас есть объект противники, мы можем усложнить и сделать несколько дочерних объектов под каждый вид противника и отдельный для боссов плюс сделать таг для каждого врага. А можем сделать один материнский объект для противников, летающих обозначить символом ^, сильных $, а босса обозначить как %. Для коллайдеров такое решение не очень удобное, но для противников и их визуального разделения в иерархии — просто отлично.

Организация на примере Spine

Когда мы говорим о 2Д или 3Д анимации то важность организации и имен выходит на иной уровень. Можно прибегнуть к мокап анимации и не переживать за организацию, а просто сделать нужные движения в студии и сделать финал тут же на месте, к сожалению не всегда так получается. Есть множество вещей которые необходимо дорабатывать вручную даже при захвате движения, но мы не об этом. Как править все движения, определить нужную точку, кость, когда их более 20? Простой человечек с 5 костями не будет сложным в организации и понимании связей, а теперь добавьте ему 10 пальцев, сложнее, не так ли?

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

А вот пример выделения цветом, помогает в работе (на примере Dragon Bones)



Главные правила


  • понятность названий
  • удобство
  • разумный подход

Вывод


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


Комментарии



Leopotam
«ExternalAssets» — это путь в никуда, если нужно не только подкладывать ассеты, но и обновлять их. Самое правильное и простое решение — это изолировать локальные ассеты проекта (в статье это «InternalAssets»), а внешние ассеты хранить так как их подготовили авторы — в идеале, отдельными папками на уровне папки «InternalAssets». В этом случае обновление становится легким и простым, не нужно сортировать по кастомным папкам то, что может приехать в обновлении и чего не было ранее. К тому же есть специальные папки, которые нельзя двигать и которые могут быть только в корне (Gizmos, Plugins/Android, Plugins/iOS и т.п.).

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

А на чьей ты стороне?

Поделиться публикацией

Комментарии 14

    +2

    а можно вариант аля "50 на 50" в голосовании.
    Когда аккуратно все складываешь и называешь, а потом неделя аврала, срочно нужна демка, или пару фитч через костыли, но срочно.
    И это выливается в кривые некрасивые места в общей красивой организации проекта/сцены/скриптов.

      0
      Типо того, готово) Вот для костылей и срочно мы обычно используем папку Trash. Когда лежит не на месте что-то рабочее, то начинает жутко раздражать. В итоге нужное мигрирует из корзины по своим местам. Именно на такие случаи папка незаменима и по сути панацея, сразу видно где лежат горячие таски.
        0
        Что-то я вспомнил несколько случаев из жизни, когда оказывалось, что в корзине лежали очень нужные файлы, на диске было мало места, а пользователь потом очень злился на поддержку, которая почистила корзину, не спросив на то пользователя разрешения. Никогда не думал, что встречу такое в реальной жизни.
      +1

      "ExternalAssets" — это путь в никуда, если нужно не только подкладывать ассеты, но и обновлять их. Самое правильное и простое решение — это изолировать локальные ассеты проекта (в статье это "InternalAssets"), а внешние ассеты хранить так как их подготовили авторы — в идеале, отдельными папками на уровне папки "InternalAssets". В этом случае обновление становится легким и простым, не нужно сортировать по кастомным папкам то, что может приехать в обновлении и чего не было ранее. К тому же есть специальные папки, которые нельзя двигать и которые могут быть только в корне (Gizmos, Plugins/Android, Plugins/iOS и т.п.). С остальным согласен, писал когда-то аналогичный пост.

        0
        Спасибо, про некоторые вещи забываешь потому что не возникает вопросов и думаешь что все в курсе. Не против если добавлю комментарий в статью?
          0
          Не против если добавлю комментарий в статью?

          Почему бы и нет.
            0
            кстати, емнип, Plugins/Android, Plugins/iOS — уже неактуальны, не помню с какой версии. Поправь если ошибаюсь )
            Вроде после появления docs.unity3d.com/Manual/PluginInspector.html стало можно класть куда хочешь.
              0
              Чому это? Манифест берется только из корневой папки вроде как. Но на самом деле не проверял.
                0
                docs.unity3d.com/Manual/PluginInspector.html

                Так там про импорт внешних сборок в виде dll файлов, я же говорил про нейтивные части россыпью под разные мобильные платформы.
          0
          Ещё как вариант, можно папки разделять не по типу ассета, а по назначению. Например:
          Tank
          └ Tank.cs
          └ TankShootSound.mp3
          └ TankModel
            0
            Мы пробовали, но так не очень удобно когда много файлов. На скрине из проекта для каждого противника свой звук, анимация, спрайт и эффект + логика. Думаем о том чтобы делать папку под противника и хранить в ней все что к нему относится, это сделает работу с локальными вещами более удобной, но префабы хранить придется отдельно для удобства.
              0

              А как хранить в случае общего ресурса для 3-5-10 объектов? Копировать? Иметь ещё одну специальную папку?

                +1
                Планировали общие ресурсы выносить при наличии, но такое у нас не часто. Единственное что может повторится это VFX и то его вариация. Ну это у нас, в противном случае лучше не создавать миллион дублей а просто не использовать повторяющиеся файлы в каждой папке а сделать отдельную папку для группы.
              –1
              Спасибо за статью. Plugins/Android и Plugins/iOS можно пихать куда угодно.

              Реализация папки Trash — Сделал папку Prototype и написал расширение, которое трекает всё в этой папке. Если файлы попадают в эту папку получают тег «prototype_» в начале. Если убрать из папки, тег удаляется.
              В эту папку попадают файлы, которые нужно первый раз добавить в проект. Так можно контролировать ресурсы (валидны или нет).

              А на весь проект расширение написал, по расширению файла создаёт теги типа:
              «mat_» — .material;
              «sprite_» или «texture» — .png, .jpg. Имя зависит от названия папки.
              и.т.д.

              На папки и скрипты исключения. Но при желании и им можно теги давать (но это будет сатана).

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

              Самое читаемое