Основы C# для Unity: Переменные, методы и классы

Глубокое погружение в логику программирования на C# в контексте Unity. Вы научитесь превращать статические GameObject в живые игровые сущности, управляя их свойствами через код.

1. Скрипт как компонент: Связь текстового файла и GameObject

Скрипт как компонент: Связь текстового файла и GameObject

В предыдущем курсе мы собрали сцену: расставили платформы и поместили на них красный квадрат, который будет нашим игроком. Но если сейчас нажать кнопку Play, ничего не произойдет. Квадрат просто висит в воздухе. В нем нет жизни, нет гравитации и нет реакции на нажатия клавиш. Чтобы превратить статичную картинку в игру, объектам нужно дать «мозг». В Unity эту роль выполняют скрипты.

Компонентный подход: от формы к логике

Мы уже знаем, что любой объект на сцене — это пустой контейнер GameObject. Его свойства полностью зависят от того, какие компоненты лежат внутри.

Добавили Transform — объект получил координаты. Добавили Sprite Renderer — объект стал видимым красным квадратом.

Программирование в Unity строится на точно таком же принципе. Скрипт — это просто еще один компонент. Разница лишь в том, что Transform написали разработчики Unity, а скрипт для управления вашим персонажем напишете вы сами. Когда вы пишете код, вы фактически создаете новый, уникальный строительный блок (кастомный компонент), который затем можно положить в любой GameObject.

Создание скрипта: текстовый файл в проекте

Все скрипты хранятся в окне Project, точно так же, как картинки, звуки или префабы. Это обычные текстовые файлы с расширением .cs (C Sharp).

Чтобы создать скрипт:

  • Кликните правой кнопкой мыши в пустом месте окна Project (лучше заранее создать папку Scripts для порядка).
  • Выберите Create → C# Script.
  • В проекте появится новый файл.
  • Здесь наступает самый критичный момент для новичков, на котором ломаются первые проекты. Как только файл появился, его имя выделено синим цветом — Unity ждет, что вы введете название.

    Назовем его PlayerController и нажмем Enter.

    Почему это так важно сделать сразу? Когда вы создаете скрипт, Unity автоматически генерирует внутри него стартовый шаблон кода. В этом коде есть имя так называемого класса (шаблона поведения). Имя файла должно символ в символ совпадать с именем класса внутри него.

    Если вы создали скрипт, случайно кликнули мышкой мимо, он назвался NewBehaviourScript. Если вы потом переименуете файл в PlayerController, внутри текстового документа имя останется старым. Unity запутается и выдаст ошибку, отказавшись работать с этим файлом.

    !Что произойдет при нарушении правила имен

    Правило хорошего тона: названия скриптов всегда пишутся слитно, каждое новое слово начинается с заглавной буквы (стиль PascalCase). Например: EnemyHealth, GameManager, WeaponShoot. Никаких пробелов.

    Связываем код и объект

    Сам по себе файл PlayerController.cs, лежащий в окне Project, ничего не делает. Это просто чертеж. Чтобы чертеж заработал, его нужно применить к конкретному объекту на сцене.

    Сделать это можно двумя способами:

  • Drag & Drop: Схватить скрипт левой кнопкой мыши в окне Project и перетащить его прямо на красного квадрата в окне Scene (или на его имя в окне Hierarchy).
  • Через Inspector: Выделить красного квадрата, в окне Inspector нажать кнопку Add Component, начать вводить PlayerController и выбрать наш скрипт из списка.
  • Как только вы это сделаете, в окне Inspector под компонентами Transform и Sprite Renderer появится новый блок — ваш скрипт.

    !Анатомия Инспектора со скриптом

    Теперь текстовый файл и игровой объект неразрывно связаны. GameObject знает, что при запуске игры он должен заглянуть в файл PlayerController.cs и начать выполнять написанные там инструкции.

    Один и тот же скрипт можно повесить на десять разных объектов. Например, написав скрипт EnemyPatrol (Патрулирование врага) один раз, вы можете добавить его на всех гоблинов на уровне. Каждый гоблин получит свой собственный экземпляр этого компонента и будет патрулировать свою зону независимо от других.

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

    2. Анатомия класса: Структура скрипта и пространство имен UnityEngine

    Анатомия класса: Структура скрипта и пространство имен UnityEngine

    Двойной клик по созданному C#-файлу открывает редактор кода. Вы ожидаете увидеть чистый лист, но вместо этого на экране уже написано 10–15 строк текста. Unity генерирует этот шаблон автоматически. Почему? Потому что любой скрипт, который вы планируете добавить на игровой объект, обязан следовать строгим правилам оформления.

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

    !Иллюстрация основных компонентов структуры C#-скрипта Unity: пространства имен, класса и методов.

    Что такое класс простыми словами?

    Прежде чем читать код, давайте ответим на главный вопрос: что именно мы сейчас создаем? В программировании постоянно звучит слово «класс».

    > Класс — это чертеж или шаблон, описывающий, какими свойствами будет обладать объект и что он сможет делать.

    Вспомните прошлые уроки: вы добавляли на объекты готовые компоненты, такие как Transform (для позиции) или SpriteRenderer (для отрисовки 2D-графики). Так вот, SpriteRenderer — это класс, который когда-то написали программисты движка Unity.

    Когда вы создаете свой скрипт, например PlayerController, вы создаете чертеж своего собственного, уникального компонента. Пока скрипт просто лежит в папке проекта (в окне Project) — это лишь бумажный чертеж. Но как только вы перетаскиваете его на объект в окне Hierarchy, Unity берет ваш чертеж-класс и по нему «собирает» реальный работающий Компонент, прикрепленный к персонажу.

    Заголовок чертежа: Объявление и наследование

    Суть любого скрипта в Unity заложена в одной строке, которая объявляет наш новый класс:

    Разберем эту конструкцию по словам:

  • public (публичный) — модификатор доступа. Он означает, что этот класс открыт и виден движку Unity. Если класс не будет публичным, окно Inspector просто не сможет его найти и показать вам.
  • class — ключевое слово языка C#. Оно сообщает компьютеру: «Внимание, дальше идет описание нового шаблона».
  • PlayerController — имя вашего класса. Оно обязано буква в букву совпадать с названием файла .cs. Если файл называется Hero.cs, а внутри написано class PlayerController, Unity выдаст ошибку.
  • : MonoBehaviour — самая критичная деталь, обозначающая наследование.
  • Двоеточие читается как «является наследником» или «расширяет». MonoBehaviour — это базовый класс-фундамент, зашитый глубоко в Unity. Он содержит всю скрытую механику, которая позволяет обычному текстовому файлу стать полноценным Компонентом.

    Наследуя MonoBehaviour, ваш PlayerController мгновенно получает суперспособности: он учится прикрепляться к GameObject, понимать, где он находится в пространстве, и реагировать на течение времени в игре.

    !Вы написали сложную логику передвижения, но случайно удалили часть строки, и теперь она выглядит так: public class PlayerController. Что произойдет, когда вы вернетесь в редактор Unity?

    Словари терминов: Директивы using

    Если посмотреть в самое начало скрипта, над объявлением класса вы увидите такие строки:

    Это директивы подключения пространств имен (namespaces).

    Язык C# огромен. Если бы ваш скрипт по умолчанию загружал в память абсолютно все существующие в мире команды, игры бы неимоверно тормозили. Поэтому код разбит на тематические словари — пространства имен. Слово using переводится как «используя» и работает как пропуск: оно говорит компилятору, какие именно словари мы собираемся применять в этом файле.

    Самая важная строка здесь — using UnityEngine;. Именно этот «словарь» содержит термины, специфичные для движка: тот самый MonoBehaviour, физику, управление камерой и нажатиями клавиш. Если вы удалите эту строку, C# забудет, что такое Unity, и ваш код перестанет понимать игровые термины. Строки с System подключают стандартные библиотеки C# для работы с данными — их мы пока просто оставляем как есть.

    Границы дозволенного: Тело класса

    После строки объявления класса идут фигурные скобки { }.

    Фигурные скобки в C# определяют область видимости (scope). Открывающая скобка { означает начало вашего чертежа, закрывающая } — его конец.

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

    Внутри этих скобок Unity заботливо разместила два пустых блока — Start() и Update(). Это изолированные «комнаты» внутри вашего класса, которые называются методами.

  • То, что вы напишете внутри скобок метода Start(), выполнится ровно один раз в момент появления объекта на уровне.
  • То, что вы напишете внутри Update(), будет выполняться постоянно, каждый нарисованный кадр игры.
  • Первая инструкция: Оживляем код

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

    Измените метод Start внутри вашего класса так, чтобы он выглядел следующим образом:

    Здесь мы обращаемся к классу Debug (инструменты отладки) и через точку вызываем его команду Log (записать в журнал). В круглых скобках, обязательно в кавычках, передается текст вашего сообщения.

    Обратите внимание на точку с запятой ; в конце строки. В языке C# это аналог точки в конце обычного предложения. Она сообщает компилятору, что мысль (инструкция) завершена. Забытая точка с запятой — самая частая причина ошибок у начинающих программистов.

    Если теперь сохранить скрипт, вернуться в Unity, убедиться, что скрипт висит на объекте на сцене (например, на вашем персонаже), и нажать кнопку Play, то в окне Console появится ваше сообщение.

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

    3. Переменные и типы данных: Создание «памяти» для игровых объектов

    Переменные и типы данных: Создание «памяти» для игровых объектов

    Меч ударяет гоблина. Удар наносит 15 единиц урона. Как движок поймет, должен ли гоблин упасть замертво или может продолжить атаку? Для этого скрипт гоблина должен «помнить», сколько у него было здоровья до удара. Без памяти любой скрипт — это просто набор инструкций, который каждый кадр начинается с чистого листа. Чтобы игровые объекты могли накапливать опыт, получать урон, менять имена и собирать монеты, коду нужна память.

    В программировании ячейки памяти, в которых хранятся данные, называются переменными.

    Что такое переменная

    В прошлой главе мы создали класс — чертеж будущего компонента, ограниченный фигурными скобками { }. Внутри этих скобок мы можем создавать переменные.

    Переменную удобнее всего представить как коробку на складе. У этой коробки есть три обязательных атрибута:

  • Тип — форма коробки. Определяет, что именно в нее можно положить (число, текст или что-то другое).
  • Имя — уникальная этикетка на коробке. По этому имени мы будем обращаться к содержимому.
  • Значение — то, что фактически лежит внутри коробки в данный момент.
  • Синтаксис создания (объявления) переменной в C# выглядит так: Тип Имя = Значение;

    Знак = здесь означает не математическое равенство, а команду присваивания: «возьми то, что справа, и положи в коробку слева». Не забывайте про точку с запятой в конце — это знак завершения инструкции.

    Базовые типы данных: Форма коробок

    Компьютер не умеет хранить абстрактную информацию. Ему нужно точно знать, сколько места выделить в памяти компьютера. Поэтому язык C# является строго типизированным — вы обязаны указать тип переменной при ее создании, и потом этот тип изменить нельзя. В коробку для чисел нельзя положить текст.

    В Unity для создания 90% игровой логики используются четыре базовых типа данных.

    | Тип данных | Что хранит | Пример значения | Игровое применение | | :--- | :--- | :--- | :--- | | int | Целые числа (от англ. integer) | 100, -5, 0 | Количество монет, уровень персонажа, инвентарь. | | float | Дробные числа (числа с плавающей точкой) | 4.5f, -1.2f | Скорость движения, сила прыжка, точные координаты. | | bool | Логическое значение (только true или false) | true, false | Состояние: жив ли игрок, есть ли ключ, на земле ли персонаж. | | string | Текстовые строки (пишутся строго в двойных кавычках) | "Player", "Game Over" | Имя персонажа, диалоги, названия предметов. |

    !Базовые типы данных

    Особенность типа float: правило суффикса «f»

    Обратите внимание на букву f в конце дробного числа (4.5f). Это не опечатка, а жесткое правило языка C#.

    Дело в том, что в C# есть два типа для дробных чисел: обычный и двойной точности. По умолчанию язык воспринимает любую дробь как число двойной точности, которое занимает в два раза больше памяти. Но движок Unity ради высокой производительности (чтобы игра выдавала 60 кадров в секунду) использует более легкий тип float.

    Добавляя f в конце числа, вы явно говорите компилятору: «Отрежь лишнюю точность, мне нужен именно легкий float». Если вы напишете float speed = 4.5; без буквы f, код выдаст ошибку и игра не запустится.

    !Выбор правильного типа данных

    Именование переменных: Правило camelCase

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

    Правила camelCase:

  • Имя всегда начинается с маленькой буквы.
  • Если имя состоит из нескольких слов, пробелы ставить нельзя.
  • Каждое следующее слово начинается с заглавной буквы (образуя «горбы» верблюда).
  • Примеры хороших имен: health, maxSpeed, isPlayerDead, collectedCoinsCount. Ошибочные имена: MaxSpeed (с большой буквы называют классы), max speed (пробелы запрещены), 1speed (имя не может начинаться с цифры).

    Переменные внутри класса

    Давайте посмотрим, как выглядит создание памяти на практике. Откроем скрипт PlayerController, который мы создали ранее, и добавим в него характеристики нашего персонажа.

    Теперь, когда этот скрипт будет добавлен на GameObject в Unity, у этого конкретного объекта появится своя собственная память. Если мы повесим этот же скрипт на трех разных персонажей, у каждого из них будет свой независимый набор этих переменных. Урон, полученный одним, никак не повлияет на playerHealth другого.

    Однако, если вы сейчас сохраните этот код и выделите персонажа в окне Hierarchy, вы не увидите этих переменных в окне Inspector. Движок знает о них, но они скрыты от глаз геймдизайнера. Чтобы настраивать скорость и здоровье прямо в редакторе Unity, не открывая код каждый раз, нам нужно научиться управлять видимостью этих переменных.