Как делать игры в Unity. Попытка в серию обучающих постов #1
Пост №1. Азы программирования.
Всем привет! Попытаюсь поработать над серией обучающих постов по Unity.
Сегодня хочу поговорить об азах правильной работы с языком C# в Unity. Об азах программирования, но не о том, как выучить C#. И о частых ошибках.
Подразумевается, что вы, читатели, уже имеете некое представление о синтаксисе ЯП (языка программирования) и можете написать "Hello, World".
Если нет - то настоятельно рекомендую сначала ознакомиться с C# и только потом уже приступать к работе в Unity. По роду своей работы и по тому, что происходит в ру-сегменте StackOverflow по тегу "Unity3D", очевидно, что большинство проблем/вопросов у новичков возникает по причине незнания ЯП.
Программирование в Unity на C# немного отличается от "классического" использования C#. Самое главное отличие - в классах-компонентах (наследниках от MonoBehaviour) не принято использовать конструкторы и деструкторы. И с этим связана одна из частых "ошибок новичков" - попытка создания компонентов ч/з оператор new. Так делать нельзя!
Классы-компоненты не могут существовать без "носителя"-GameObject'а. Поэтому если вам необходимо добавить новый компонент из кода, необходимо использовать метод AddComponent().
Если же необходимо создать экземпляр "обычного класса", то в этом случае, разумеется, используется оператор new и конструктор класса.
Еще очень важное отличие - в одном .cs-файле в Unity может быть только один класс-компонент (но это не значит, что в этом же файле нельзя будет определять структуры, другие "обычные классы", перечисления и т.д.)
И файл должен называться точно так же, как класс-компонент (наследник от MonoBehaviour)!
В классах-компонентах могут быть использованы "предусмотренные движком" методы (Awake(), Start(), Update() и т.д.) Эти методы должны быть определены в классе и должны быть названы точно так же (с учетом регистра), как указано в документации. Иначе они не будут вызываться движком в предусмотренное время в предусмотренном порядке. Это связано с тем, что Unity работает с такими методами через механизм рефлексии.
И самая, на мой взгляд, распространенная "ошибка новичка" при работе с "предусмотренными методами" - работа с Update(), FixedUpdate(), LateUpdate().
Update() - вызывается раз за кадр. И часто новички в этот метод вставляют много бессмысленного кода (а временами и "вредного", негативно сказывающегося на производительности). Не стоит каждый кадр искать компоненты и объекты (н-р, GameObject.FindObjectOfType()) и не стоит каждый кадр обновлять UI (н-р, каждый раз присваивать тексту здоровья текущее значение HP игрока - это стоит делать только при изменении значения). Так же не забывайте использовать Time.deltaTime - время, прошедшее с прошлого вызова Update() (не путать с Time.fixedDeltaTime) если необходимо что-то делать равномерно каждый кадр (н-р, перемещая объект каждый кадр - можно указанную скорость умножать на величину Time.deltaTime).
FixedUpdate() - вызывается фиксированное кол-во раз в секунду. Настраивается в Unity. Как правило этот метод используют для работы с физикой. И тут для "равномерности" необходимо использовать Time.fixedDeltaTime (не Time.deltaTime).
LateUpdate() - вызывается раз за кадр после Update(). Поэтому в момент вызова LateUpdate() уже известны все изменения из Update(). Как правило в этом методе работают с перемещением камеры. Для "равномерности" следует использовать Time.deltaTime.
На этом буду заканчивать с первым постом. Очень надеюсь, что продолжу серию.
А вам всем желаю успеха в геймдеве!