Геймдев — занятие по настоящему увлекательное, особенно когда в команде есть как опытные программисты, так и новички. В отличии от таких движков как Unreal и CryEngine, в Unity достаточно низкий порог вхождения, и зачастую ветераны .NET и новички начинают выяснять отношения, которые заканчиваются дракой с применением офисной мебели.
В этой статье я попытался собрать советы которые помогут вам и вашей команде договориться наконец о том, как надо писать код, и, надеюсь, хорошо посмеяться. И так, поехали!
1. Пиши на UnityScript
Один язык в проекте — это скучно. Разнообразь жизнь своих коллег, пусть учаться быть полиглотами. C# — это майкрософт, и вообще строгая типизация это не твое.2. Не используй var
Сами Unity запрещают* это делать, да и вообще непонятно, какого типа переменная. Когда тебе скажут про подсказки IntelliSense — закатывай глаза, майкрософт головного мозга! Твой Notepad++ этого не умеет.3. Смешивай стили
Ну а что? Сами Unity нарушают C# Style Guide и фигачат camelCase в пропертях, чем ты хуже? Если используешь MonoDevelop, не забывай периодически менять табы на пробелы и обратно. При этом говори всем, что в MonoDevelop «настройки слетели» — про этот баг все знают!4. Не пиши XML Doc комментарии
Они засоряют файл, а твой код должен быть понятен без дополнительных комментариев. И вообще, твой Notepad++ не поддреживает это всё. Если меняешь сигнатуру чужого метода, не обновляй XML Doc — так чтение автодокументации будет веселее.5. Не используй namespace
Писать using — слишком муторно, и вообще зачем это делать, если можно обойтись без этого. Все скрипты должны лежать в папке Script — так их проще находить по алфавиту.6. Связывай компоненты
Чем больше связей — тем лучше! Каждый компонент должен ссылаться на каждый другой компонент — зато так проще! У твоего персонажа должна быть ссылка на противника, дверь, гейм менеджер, ХП бар на канвасе, на любые другие объекты на сцене. А иначе как с этим работать?7. Создавая референсы, прячь их через [SerializeField] private GameObject myGameObject;
Так твой референс можно будет отредактировать только через редактор, а в коде они мешаться не будут. Когда окажется, что что-то надо все-таки поменять через код, просто переделай private на public.8. Не используй паттерны проектирования, кроме singleton
Когда тебе говорят про Dependency Injection или другие паттерны, закатывай глаза. Какие нафиг паттерны, тут тебе не энтерпрайз!9. GameObject.SendMessage — потрясающе удобный инструмент, используй его как можно чаще
По возможности собирай название метода из нескольких строк — так твоим коллегам будет веселее искать, откуда вызвался метод!10. Используй UnityEvent везде, где это возможно
Стандартные event'ы — это для лохов, тем более они не отображаются в инспекторе. Unity не зря придумали свои ивенты.Выставляй все через инспектор. Раздели свой код на части и выстави 5 разных методов при нажатии на кнопку — так будет веселее искать, по нажатию какой кнопки этот метод вызывается!
11. Подписываясь на событие через AddListener, забывай прописать RemoveListener
Нет ничего веселее, чем дебажить и искать, почему код срабатывает несколько раз одновременно. Особенно когда это происходит не постоянно.12. Кэшируй все компоненты на GameObject'ах
Даже если вы их не используете или используете один раз при нажатии на кнопку. Оптимизировать надо начинать как можно раньше! Не забывайте закэшировать transform; те, кто говорят, что transform уже закэширован — лжецы.13. Не используй свойства
Свойства — это медленно, как вызов метода, а доступ к полю гораздо быстрее. Все преимущества свойств — выдуманы. Когда тебе кто-то начнет говорить про private set, обратную совместимость и необходимость рекомпиляции assembly в случае изменения поля на свойство, смотри на них как на дураков — какая еще компиляция, у нас геймдев а не энтерпрайз, мы тут dll не используем! И вообще, когда ты последний раз менял поле на свойство?14. Не используй foreach
Ну, про это уже не раз говорили. Сами Unity запрещают использование foreach. Найдя foreach в коде коллеги, замени его на for и прочитай 10 минутную лекцию о том, что foreach создает мусор, для убедительности покажи свой бенчмарк, где ты обходишь список каждый кадр.15. Не используй Linq
Linq — это медленно, сложно, и вообще это майкрософт. For на 10 строк — это гораздо красивее (foreach мы же не используем — забыл?). Если кто-то посмеет написать Query Expressions, то смотри на него как на идиота — майэскюЭль с Юнити перепутал!16. Не используй строки
Строка — это выделение памяти, которую потом будет собирать GC. Используй char[] — не зря же ты в универе сишку проходил. Никакой юникод тебе не нужен — нечего лишние байты гонять, все равно у тебя bitmap шрифты.17. Не используй Generics
Дженерики — это медленно и сложно, а Generic Constraints — еще сложнее. Какая нафиг ковариантность и контравариантность? У нас Юнити, тут этого нет! Когда нужны классы с разным типом, храните имя класса в переменной и находите его с помощью Type.GetType().18. Не используй Coroutines без надобности
Они не работают на неактивных объектах, и вообще, создают дополнительную нагрузку. Храни состояние в булевых переменных, и проверяй их в Update — так гораздо удобнее, ведь все собрано в одном месте.19. Как только выходит новая версия движка, ставь ее и закоммить папку ProjectSettings
Пусть твои коллеги учаться держать обновленный инструментарий. Ну и что, что проект сдавать через 2 дня, а новая версия с багами? Не твоя это проблема, что Unity не могут зарелизить нормально! Зато там есть новая система частиц, с которой тебе хочется поиграться.20. Не используй текстовую сериализацию ассетов
Она тормозит редактор. Бинарная сериализация — это гораздо быстрее. Когда кто-то скажет про merge, закати глаза — он что, дурак, сцену мержить? Когда смержить нужно будет тебе, просто откати чужие изменения. Надо было говорить, над каким ассетом работаешь, что бы другие не трогали!Про var и foreach
1. В своем Bitbucket репозитории Unity действительно указывают на то, что в pull-request'ах нельзя использовать var или foreach. Интересно, что там же они пишут не использовать префиксы m_ k_ итд, хотя сами делают это в огромном количестве мест, в нарушение стандарта C# Style Guide.
Статья была частично навеяна вот этой статьей по оптимизации и периодическими перлами, которые выдают знакомые программисты.
Что бы не устраивать холивар, я предлагаю условиться, что foreach действительно создает мусор, который потом приходится собирать GC. Но во-первых, это правило работает не всегда (иногда foreach разворачивается компилятором в обычный for), а во-вторых, если не обходить большие списки в каждом кадре, в 99% случаев проблемой это не является.
Статья была частично навеяна вот этой статьей по оптимизации и периодическими перлами, которые выдают знакомые программисты.
Что бы не устраивать холивар, я предлагаю условиться, что foreach действительно создает мусор, который потом приходится собирать GC. Но во-первых, это правило работает не всегда (иногда foreach разворачивается компилятором в обычный for), а во-вторых, если не обходить большие списки в каждом кадре, в 99% случаев проблемой это не является.
P.S. Всем хороших выходных, и с Наступающим!