Траектория «Геймдев» · линия A · конспект 7 из 13

Основы C# и жизненный цикл скрипта

О чём эта тема
Минимум языка C#, нужный для скриптов Unity: переменные, методы, условия — и главное: как устроен скрипт-наследник MonoBehaviour и в каком порядке движок вызывает его методы.
Аннотация
Конспект начинается с простейшей программы на C# и базовых конструкций языка: переменные и типы, неявные преобразования, методы с модификаторами доступа, перегрузка методов, условные операторы и логические операции. Затем пишется первый скрипт Unity: класс-наследник MonoBehaviour добавляется на объект сцены и выводит сообщение в консоль; код разбирается построчно. Завершающая часть — жизненный цикл скрипта: порядок вызова методов от Awake до OnDestroy, различие Update и FixedUpdate, пары OnEnable/OnDisable и OnCollision/OnTrigger; порядок закрепляется интерактивным симулятором.
Пререквизиты
Конспект A05: сцена, объекты, компоненты, добавление компонента через Add Component, вкладка «Консоль». Опыт программирования на любом языке полезен, но изложение его не предполагает.
Мотивация
Машина состояний противника из A02 уже была записана на C#: перечисление, метод Update, условия переходов. Тогда мы приняли на веру, что «Update вызывается каждый кадр». Пришло время разобраться, кто, когда и в каком порядке вызывает методы скрипта — без этого невозможно ответить даже на простой вопрос, почему счётчик в Update у одних игроков растёт быстрее, чем у других, а физика при этом ведёт себя одинаково.

1. Первая программа на C#

Прежде чем писать скрипты для движка, посмотрим на C# в чистом виде. Минимальная программа:

using System;

public class MainClass
{
    public static void Main()
    {
        Console.WriteLine("Unity это круто!");
    }
}

2. Переменные

Переменные хранят данные. Основные типы, с которых мы начнём:

Тип переменной должен соответствовать содержимому, но с оговоркой о преобразованиях. Целое число можно присвоить переменной типа float: 100 превратится в 100.0 без потери точности — это неявное преобразование. Обратное неявно не работает: у числа с плавающей точкой есть дробная часть, и при переводе в целое она была бы потеряна, поэтому компилятор требует явного указания.

using System;

public class MainClass
{
    public static void Main()
    {
        int year = 2025;
        float pi = 3.14f;
        Console.WriteLine(year);
        Console.WriteLine(pi);
    }
}

3. Методы и модификаторы доступа

Метод — упрощённо — список действий, которые надо выполнить. В программировании не принято копировать один и тот же код, раздувая программу: повторяющиеся действия оформляются в метод, которому передаются разные данные.

public int Add(int a, int b)
{
    return a + b;
}

Разберём сигнатуру. public — модификатор доступа: метод доступен всем; парный ему private открывает доступ только внутри класса, где метод объявлен. int — тип возвращаемого значения. Add — имя метода: любые буквы, цифры и подчёркивание, первый символ — буква или подчёркивание, без пробелов и знаков пунктуации, не ключевое слово языка; хорошим тоном считается имя с большой буквы. В круглых скобках — аргументы; фигурные скобки — зона ответственности метода. return возвращает результат и завершает метод: команды после него не выполнятся.

Метод может ничего не возвращать — тогда вместо типа пишется void («пустота»), и переменную со значением такого метода объявить нельзя:

public void PrintMsg()
{
    Console.WriteLine("Hello!");
}

3.1. Перегрузка методов

Перегрузка — использование одного имени метода с разными аргументами: другим их количеством или типом. Нужно сложить не два, а три числа — пишем метод с тем же именем и тремя аргументами; нужно сложить числа с плавающей точкой — с аргументами float:

public int Sum(int a, int b)          { return a + b; }
public int Sum(int a, int b, int c)   { return a + b + c; }
public float Sum(float a, float b)    { return a + b; }

В классах Unity перегрузка используется постоянно. Убедиться легко: в редакторе кода щёлкните по интересующему методу с зажатой Ctrl — увидите все варианты перегрузки, например у методов класса GameObject.

4. Условия и логические операции

int a = 5;
int b = 5;

if (a > b)
{
    Console.WriteLine("YES");      // a больше b
}
else if (a == b)
{
    Console.WriteLine("EQUALS");   // a равно b
}
else
{
    Console.WriteLine("NO");       // остаётся: a меньше b
}

Условие в if — выражение типа bool: «правда» (true) или «ложь» (false). Если условие ложно, управление переходит к else if со своей проверкой, а затем к else — ветке «во всех остальных случаях». Три состояния сравнения двух чисел (больше, равно, меньше) покрываются ровно этой конструкцией.

Типичная ошибка Один знак равно в условии: if (a = b). Один знак — присваивание, два знака ==сравнение. Компилятор C# такое условие не пропустит, но привычку различать = и == стоит закрепить сразу.

Логические операции соединяют условия: && — «логическое И», истинно, только когда верны оба условия; || — «логическое ИЛИ», истинно, когда верно хотя бы одно.

5. Первый скрипт Unity

Подготовка окружения делается один раз: в Package Manager (Window → Package Manager, фильтр In Project) должен стоять пакет поддержки вашего редактора кода — если его нет, найдите его в Unity Registry и нажмите Install; затем в Edit → Preferences → External Tools выберите редактор в пункте External Script Editor.

Скрипт создаётся в панели «Проект» так же, как материал: Create → C# Script; назовём его HelloWorld. Двойной щелчок открывает редактор кода:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HelloWorld : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Hello World!");
    }

    // Update is called once per frame
    void Update()
    {
    }
}

Сохраняем (Ctrl+S) и добавляем скрипт на любой объект сцены — например, на шар из A05: выделить объект в иерархии → Add Component в инспекторе → в поиске набрать имя скрипта. Запускаем проект, открываем вкладку Console — там наше приветствие.

5.1. Разбор кода построчно

Небольшое упражнение из материалов: перенесите Debug.Log из Start в Update, запустите игру и объясните, что изменилось. Ответ проверьте в симуляторе следующего раздела.

6. Жизненный цикл скрипта

В каждом скрипте-наследнике MonoBehaviour есть базовые методы, и Unity вызывает их в строго определённой последовательности. Самые востребованные — в порядке вызова:

Типичная ошибка Считать Update и FixedUpdate взаимозаменяемыми. Update привязан к кадрам: на быстром компьютере вызовется чаще, на медленном — реже, поэтому «скорость += 1 в Update» даёт разным игрокам разную физику. Расчёты движения и сил — в FixedUpdate с его стабильными 50 вызовами в секунду; ввод с клавиатуры — в Update.
Тренажёр · симулятор жизненного цикла

Слева — методы скрипта, справа — журнал вызовов. Управляйте «приложением»: запустите его, прокрутите кадры, выключите и включите объект, уничтожьте его — и проследите, какие методы вызывает Unity. Проверьте особенность Awake: поставьте галочку «объект выключен при старте» и посмотрите, что вызовется всё равно.

Приложение не запущено.

Полная схема порядка выполнения (включая методы отрисовки и корутины) — в документации Unity:

Блок-схема порядка выполнения событийных методов Unity: инициализация (Awake, OnEnable, Start), физика (FixedUpdate, OnTrigger, OnCollision), логика игры (Update, LateUpdate), отрисовка, отключение и уничтожение
Порядок выполнения событийных методов. Источник: Unity Documentation, Order of execution for event functions

Контрольные вопросы

Источники

  1. Order of execution for event functions // Unity Documentation : [сайт]. — URL: https://docs.unity3d.com/Manual/ExecutionOrder.html (дата обращения: 08.07.2026).
  2. MonoBehaviour // Unity Scripting API : [сайт]. — URL: https://docs.unity3d.com/ScriptReference/MonoBehaviour.html (дата обращения: 08.07.2026).
  3. Руководство по языку C# // Microsoft Learn : [сайт]. — URL: https://learn.microsoft.com/ru-ru/dotnet/csharp/ (дата обращения: 08.07.2026).