КулЛиб - Классная библиотека! Скачать книги бесплатно 

Изучаем C# через разработку игр на Unity [Ферроне Харрисон] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]
Харрисон Ферроне

Изучаем C#
через разработку
игр на Unity

Пятое издание

2022

ББК 32.973.2-018.1
УДК 004.43
Ф43

Ферроне Харрисон
Ф43 Изучаем C# через разработку игр на Unity. 5-е издание. — СПб.: Питер,
2022. — 400 с.: ил. — (Серия «Библиотека программиста»).
ISBN 978-5-4461-2932-4
Изучение C# через разработку игр на Unity — популярный способ ускоренного освоения мощного и универсального языка программирования, используемого для решения прикладных задач
в широком спектре предметных областей. Эта книга дает вам возможность с нуля изучить программирование на C# без зубодробительных терминов и непонятной логики программирования,
причем процесс изучения сопровождается созданием простой игры на Unity.
В пятом издании изложены последние версии всех современных функций C# на примерах из
игрового движка Unity, а также добавлена новая глава о промежуточных типах коллекций. Вы
начнете с основ программирования и языка C#, узнаете основные концепции программирования
на С#, включая переменные, классы и объектно-ориентированное программирование. Освоив
программирование на C#, переключитесь непосредственно на разработку игр на Unity и узнаете,
как написать сценарий простой игры на C#. На протяжении всей книги описываются лучшие
практики программирования, которые помогут вам вывести свои навыки Unity и C# на новый
уровень. В результате вы сможете использовать язык C# для создания собственных реальных
проектов игр на Unity.

16+ (В соответствии с Федеральным законом от 29 декабря 2010 г. № 436-ФЗ.)

ББК 32.973.2-018.1
УДК 004.43
Права на издание получены по соглашению с Packt Publishing. Все права защищены. Никакая часть данной
книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Информация, содержащаяся в данной книге, получена из источников, рассматриваемых издательством
как надежные. Тем не менее, имея в виду возможные человеческие или технические ошибки, издательство
не может гарантировать абсолютную точность и полноту приводимых сведений и не несет ответственности
за возможные ошибки, связанные с использованием книги.
Издательство не несет ответственности за доступность материалов, ссылки на которые вы можете найти
в этой книге. На момент подготовки книги к изданию все ссылки на интернет-ресурсы были действующими.

ISBN 978-1800207806 англ.

© Packt Publishing, 2020.
F
 irst published in the English language
under the title ‘Learning C# by Developing Games
with Unity 2020 - 5th Edition – (9781800207806)’

ISBN 978-5-4461-2932-4

© Перевод на русский язык ООО Издательство «Питер», 2022
© Издание на русском языке, оформление ООО Издательство
«Питер», 2022
© Серия «Библиотека программиста», 2022

Краткое содержание
Об авторе..........................................................................................................................16
О научных редакторах.................................................................................................17
Предисловие...................................................................................................................18
Глава 1. Знакомство со средой.................................................................................24
Глава 2. Основные элементы программирования.............................................47
Глава 3. Погружение в переменные, типы и методы........................................66
Глава 4. Поток управления и типы коллекций............................................... 101
Глава 5. Работа с классами, структурами и ООП........................................... 138
Глава 6. Погружение в Unity................................................................................. 173
Глава 7. Движение, управление камерой и столкновения.......................... 215
Глава 8. Программируем механику игры.......................................................... 251
Глава 9. Основы ИИ и поведение врагов.......................................................... 292
Глава 10. Снова о типах, методах и классах..................................................... 320
Глава 11. Знакомство со стеками, очередями и HashSet............................. 343
Глава 12. Обобщения, делегаты и многое другое ......................................... 357
Глава 13. Путешествие продолжается................................................................ 385
Ответы на контрольные вопросы......................................................................... 393

Оглавление
Об авторе..........................................................................................................................16
О научных редакторах.................................................................................................17
Предисловие...................................................................................................................18
Для кого эта книга..................................................................................................18
Структура книги......................................................................................................19
Как получить от книги максимум.....................................................................21
Скачивание файлов с примерами кода............................................................22
Скачивание цветных изображений...................................................................22
Условные обозначения..........................................................................................22
От издательства.......................................................................................................23
Глава 1. Знакомство со средой.................................................................................24
Технические требования.......................................................................................25
Начинаем работу в Unity 2020...........................................................................25
Если у вас macOS..............................................................................................31
Создание нового проекта................................................................................32
Интерфейс программы....................................................................................34
Использование C# с Unity..................................................................................35
Работа со сценариями C#...............................................................................36
Редактор Visual Studio....................................................................................38
Синхронизация файлов C#...........................................................................40

Оглавление  7

Изучение документации.......................................................................................41
Доступ к документации Unity......................................................................41
Поиск ресурсов C#...........................................................................................44
Подведем итоги........................................................................................................45
Контрольные вопросы. Работа со сценариями.............................................46
Глава 2. Основные элементы программирования.............................................47
Определение переменных....................................................................................48
Имена важны......................................................................................................49
Переменные — это «коробки».......................................................................49
Понятие метода........................................................................................................53
Методы — это движущая сила......................................................................53
Методы — это тоже «коробки».....................................................................54
Знакомство с классами..........................................................................................56
Стандартный класс Unity...............................................................................57
Классы — это шаблоны....................................................................................57
Работа с комментариями......................................................................................58
Практичные косые............................................................................................59
Многострочные комментарии......................................................................59
Собираем все вместе..............................................................................................61
Сценарии превращаются… в элегантные компоненты.........................61
Рука помощи от MonoBehavior....................................................................63
Связь между классами..........................................................................................64
Подведем итоги........................................................................................................64
Контрольные вопросы. Основные элементы C#.........................................65
Глава 3. Погружение в переменные, типы и методы........................................66
Пишем на C# правильно......................................................................................67
Отладка кода.............................................................................................................68
Объявление переменных......................................................................................69
Объявление типа и значения........................................................................70
Объявление типа без значения.....................................................................71

8  Оглавление

Использование модификаторов доступа........................................................71
Выбор уровня безопасности..........................................................................72
Работа с типами.......................................................................................................74
Простые встроенные типы.............................................................................74
Преобразование типов.....................................................................................78
Предполагаемые объявления........................................................................79
Пользовательские типы..................................................................................79
Итого про типы .................................................................................................79
Именование переменных......................................................................................80
Практические рекомендации........................................................................80
Понятие области видимости переменных......................................................81
Знакомство с операторами...................................................................................83
Арифметика и присваивание........................................................................84
Определение методов............................................................................................86
Базовый синтаксис...........................................................................................87
Определение параметров.....................................................................................91
Определение возвращаемых значений............................................................93
Время действовать. Добавляем возвращаемый тип..............................94
Использование возвращаемых значений..................................................95
Анализ распространенных методов Unity......................................................97
Метод Start()......................................................................................................97
Метод Update()..................................................................................................98
Подведем итоги........................................................................................................99
Контрольные вопросы. Переменные и методы.......................................... 100
Глава 4. Поток управления и типы коллекций............................................... 101
Операторы выбора............................................................................................... 102
Оператор if-else............................................................................................... 102
Оператор switch.............................................................................................. 112
Контрольные вопросы 1. Операторы if, and и or................................. 117

Оглавление  9

Знакомство с коллекциями.............................................................................. 117
Массивы............................................................................................................ 117
Списки............................................................................................................... 121
Словари............................................................................................................. 124
Контрольные вопросы 2. Все о коллекциях.......................................... 127
Операторы итерации........................................................................................... 128
Цикл for............................................................................................................. 128
Цикл foreach..................................................................................................... 131
Цикл while........................................................................................................ 134
Бесконечность не предел!............................................................................ 136
Подведем итоги..................................................................................................... 137
Глава 5. Работа с классами, структурами и ООП........................................... 138
Определение класса............................................................................................ 139
Базовый синтаксис........................................................................................ 139
Создание экземпляра объекта класса..................................................... 140
Добавление полей класса............................................................................ 142
Использование конструкторов.................................................................. 143
Объявление методов класса....................................................................... 146
Объявление структур......................................................................................... 148
Базовый синтаксис........................................................................................ 148
Общие сведения о ссылочных типах и типах значений......................... 150
Ссылочные типы............................................................................................ 151
Типы-значения................................................................................................ 153
Подключаем объектно-ориентированное мышление.............................. 154
Инкапсуляция................................................................................................. 155
Наследование................................................................................................... 157
Композиция...................................................................................................... 160
Полиморфизм.................................................................................................. 160
Итого про ООП............................................................................................... 162

10  Оглавление

Применение ООП в Unity................................................................................ 163
Объекты — это творение класса................................................................ 163
Доступ к компонентам................................................................................. 165
Подведем итоги..................................................................................................... 172
Контрольные вопросы. Все об ООП............................................................. 172
Глава 6. Погружение в Unity................................................................................. 173
Основы игрового дизайна................................................................................. 174
Документация игрового дизайна.............................................................. 174
Брошюра о Hero Born................................................................................... 175
Создание уровня................................................................................................... 176
Создание примитивов.................................................................................. 177
Трехмерное мышление................................................................................. 180
Материалы........................................................................................................ 182
White-boxing.................................................................................................... 186
Основы работы со светом.................................................................................. 198
Создание источников света........................................................................ 198
Свойства источников света........................................................................ 200
Анимация в Unity................................................................................................ 201
Создание клипов............................................................................................ 202
Запись ключевых кадров............................................................................. 205
Кривые и касательные.................................................................................. 207
Система частиц..................................................................................................... 211
Подведем итоги..................................................................................................... 214
Контрольные вопросы. Основные функции Unity.................................. 214
Глава 7. Движение, управление камерой и столкновения.......................... 215
Перемещение игрока........................................................................................... 216
Создание игрока............................................................................................. 217
Введение в векторы....................................................................................... 219
Обработка ввода от игрока......................................................................... 221

Оглавление  11

Следование камеры за игроком....................................................................... 226
Время действовать. Программируем поведение камеры................. 226
Работа с физикой Unity..................................................................................... 229
Rigidbody в движении................................................................................... 232
Коллайдеры и столкновения...................................................................... 237
Использование триггеров коллайдера.................................................... 243
Итоги по физике............................................................................................. 249
Подведем итоги..................................................................................................... 250
Контрольные вопросы. Управление игроком и физика......................... 250
Глава 8. Программируем механику игры.......................................................... 251
Добавление прыжков.......................................................................................... 252
Перечисления.................................................................................................. 252
Работа со слоями-масками.......................................................................... 256
Реализация стрельбы.......................................................................................... 262
Создание экземпляров объектов.............................................................. 263
Следим за размножением GameObject................................................... 268
Создание игрового менеджера......................................................................... 270
Отслеживание свойств игрока................................................................... 270
Свойства для чтения и для записи........................................................... 273
Улучшаем игрока.................................................................................................. 278
Графический интерфейс.............................................................................. 279
Условия победы и поражения.................................................................... 283
Использование директив и пространств имен..................................... 288
Подведем итоги..................................................................................................... 290
Контрольные вопросы. Работа с механикой............................................... 291
Глава 9. Основы ИИ и поведение врагов.......................................................... 292
Навигация с помощью Unity........................................................................... 293
Компоненты навигации............................................................................... 293
Перемещение вражеских агентов................................................................... 300
Процедурное программирование............................................................. 300

12  Оглавление

Механика врага..................................................................................................... 308
Найти и уничтожить..................................................................................... 308
Рефакторинг — держим код в чистоте.......................................................... 317
Время действовать. Создаем метод перезапуска................................. 317
Подведем итоги..................................................................................................... 319
Контрольные вопросы. ИИ и навигация..................................................... 319
Глава 10. Снова о типах, методах и классах..................................................... 320
Подробнее о модификаторах доступа........................................................... 321
Свойства constant и readonly...................................................................... 321
Использование ключевого слова static................................................... 322
Вернемся к методам............................................................................................ 324
Перегрузка методов....................................................................................... 325
Параметр ref..................................................................................................... 327
Параметр out.................................................................................................... 329
Подробнее об ООП.............................................................................................. 330
Интерфейсы..................................................................................................... 331
Абстрактные классы...................................................................................... 334
Расширения класса........................................................................................ 336
И снова о пространствах имен......................................................................... 340
Псевдонимы типов......................................................................................... 340
Подведем итоги..................................................................................................... 341
Контрольные вопросы. Новый уровень!...................................................... 342
Глава 11. Знакомство со стеками, очередями и HashSet............................. 343
Введение в стеки................................................................................................... 344
Базовый синтаксис........................................................................................ 344
Просмотр и извлечение................................................................................ 347
Общие методы................................................................................................. 348
Работа с очередями.............................................................................................. 350
Базовый синтаксис........................................................................................ 350

Оглавление  13

Добавление, удаление и просмотр........................................................... 351
Общие методы................................................................................................. 351
Использование HashSet..................................................................................... 352
Базовый синтаксис........................................................................................ 352
Выполнение операций.................................................................................. 353
Подведем итоги..................................................................................................... 355
Контрольные вопросы. Сложные коллекции............................................ 356
Глава 12. Обобщения, делегаты и многое другое .......................................... 357
Обобщения............................................................................................................. 357
Обобщенные объекты................................................................................... 358
Обобщенные методы..................................................................................... 360
Ограничения типов параметров................................................................ 363
Делегирование действий................................................................................... 365
Базовый синтаксис........................................................................................ 365
Делегаты как типы параметров................................................................. 367
Запуск событий..................................................................................................... 369
Базовый синтаксис........................................................................................ 370
Обработка подписок на события.............................................................. 372
Обработка исключений...................................................................................... 374
Выбрасывание исключений........................................................................ 375
Использование оператора try-catch......................................................... 378
Экскурс по паттернам проектирования....................................................... 381
Часто используемые игровые паттерны................................................. 382
Подведем итоги..................................................................................................... 383
Контрольные вопросы. Продвинутый C# . ................................................ 384
Глава 13. Путешествие продолжается................................................................ 385
Верхушка айсберга.............................................................................................. 385
Повторим принципы ООП............................................................................... 386
Приближение к проектам Unity..................................................................... 387

14  Оглавление

Возможности Unity, которые мы не рассмотрели.............................. 388
Следующие шаги.................................................................................................. 389
Ресурсы по языку C#.................................................................................... 389
Ресурсы по Unity............................................................................................ 389
Сертификаты Unity....................................................................................... 390
Подведем итоги..................................................................................................... 391
Ответы на контрольные вопросы......................................................................... 393
Глава 1. Знакомство со средой......................................................................... 393
Глава 2. Основные элементы программирования..................................... 393
Глава 3. Погружение в переменные, типы и методы................................ 394
Глава 4. Поток управления и типы коллекций.......................................... 394
Глава 5. Работа с классами, структурами и ООП..................................... 395
Глава 6. Погружение в Unity............................................................................ 395
Глава 7. Движение, управление камерой и столкновения..................... 395
Глава 8. Программируем механику игры..................................................... 396
Глава 9. Основы ИИ и поведение врагов..................................................... 396
Глава 10. Снова о типах, методах и классах................................................ 396
Глава 11. Знакомство со стеками, очередями и HashSet........................ 397
Глава 12. Обобщения, делегаты и многое другое...................................... 397

Достигнув совершенства, люди исчезают.
Теренс Хэнбери Уайт.
Король былого и грядущего

Об авторе
Харрисон Ферроне родился в Чикаго, штат Иллинойс. Пишет техническую документацию в Microsoft, создает учебные материалы для
LinkedIn Learning и Pluralsight или занимается сайтом Рэя Вендерлиха.
Харрисон — обладатель нескольких дипломов Университета Колорадо в Боулдере и Колумбийского колледжа в Чикаго. Проработав несколько лет iOS-разработчиком в небольших стартапах и даже в одной
компании из списка Fortune 500, он сделал карьеру преподавателя
и ни секунды не жалел об этом. За все это время он купил много книг,
обзавелся несколькими кошками, поработал за границей и постоянно
задавался вопросом, почему в школах не проходят «Нейроманта»
Уильяма Гибсона.
Книга так и не была бы дописана без поддержки Келси, моего ком­
паньона в этом путешествии. Благодарю также Уилбура, Мерлина,
Уолтера и Иви за их добрые сердца и готовность поддержать в труд­
ную минуту.

О научных редакторах
Эндрю Эдмондс — опытный программист, разработчик игр и преподаватель. Получил степень бакалавра компьютерных наук Уошбернского университета и является сертифицированным программистом
и преподавателем по Unity. После колледжа Эндрю три года трудился
разработчиком в государственном аппарате штата Канзас, а затем еще
пять лет учил старшеклассников писать код и создавать видеоигры.
В то время он помог многим молодым амбициозным разработчикам
игр достичь больших высот, в том числе выиграть национальный чемпионат Skills USA по разработке видеоигр в 2019 году, создав в Unity
игру в виртуальной реальности. Эндрю живет в Вашингтоне с женой
Джессикой и дочерьми Алисой и Адой.
Адам Бжозовски — опытный разработчик игр и клиентских приложений. Разбирается в Unity, Unreal Engine, C++, Swift и Java, что помогает
ему находить правильное решение для каждого проекта.

Предисловие
Unity — один из самых популярных игровых движков в мире, которым пользуются и геймдизайнеры-любители, и профессиональные
разработчики AAA-проектов, и киностудии. Обычно Unity считают
3D-движком, но у него есть немало специальных функций, реализующих поддержку всего на свете, от 2D-игр и виртуальной реальности
до инструментов постпродакшена и кросс-платформенной адаптации.
Что разработчикам нравится в Unity? Например, позволяющий перетаскивать панели интерфейс, встроенные функции и, конечно, самое
великолепное — возможность писать собственные сценарии C# для
программирования поведения и игровой механики. Опытного программиста, владеющего другими языками, нисколько не смутит необходимость выучить язык C#, а вот тех, у кого нет опыта программирования,
это может отпугнуть. И тут-то вам и пригодится данная книга, в которой мы с нуля рассмотрим основы программирования и языка C#,
создав попутно полноценную и веселую игру в Unity.

Для кого эта книга
Книга создана в первую очередь для тех, кто не знаком с азами программирования и языком C#. Если же вы уже что-то понимающий новичок
или даже опытный программист, знающий другой язык либо тот же C#,
но теперь хотите заняться разработкой игр на Unity, то также пришли
по адресу.

Структура книги  19

Структура книги
В главе 1 «Знакомство со средой» мы рассмотрим процесс установки
Unity, познакомимся с основными функциями редактора и посмотрим
документацию по различным вопросам C# и Unity. Затем поговорим
о создании сценариев C# прямо изнутри Unity и через приложение
Visual Studio, в котором и будем работать с кодом далее.
В главе 2 «Основные элементы программирования» мы начнем с разбора основных понятий программирования и посмотрим, как переменные,
методы и классы соотносятся с ситуациями из нашей повседневной
жизни. Затем перейдем к простым методам отладки, правилам форматирования и комментирования кода, а также посмотрим, как Unity
превращает сценарии C# в компоненты.
В главе 3 «Погружение в переменные, типы и методы» мы более
подробно поговорим о переменных, рассмотрим типы данных C#,
соглашения об именовании, модификаторы доступа и все прочее,
что необходимо для создания программы. Мы также рассмотрим,
как писать методы, включать параметры и эффективно использовать
возвращаемые типы. В конце рассмотрим стандартные методы класса
MonoBehavior из Unity.
В главе 4 «Поток управления и типы коллекций» мы познакомимся
с реализацией принятия решений в коде с помощью операторов if ...
else и switch. Далее перейдем к работе с массивами, списками и словарями, а затем рассмотрим операторы итерации, которые позволяют
циклически перебирать коллекции. В конце главы мы рассмотрим
операторы цикла с условием и специальным типом данных C# — перечислением.
В главе 5 «Работа с классами, структурами и ООП» мы впервые попробуем создавать свои классы и их экземпляры, а также структуры.
Рассмотрим порядок создания конструкторов, добавление переменных и методов, основы создания подклассов и наследования. В конце
обсудим концепцию объектно-ориентированного программирования
в целом, а также ее применение в C#.
В главе 6 «Погружение в Unity» мы переключимся с синтаксиса C# на
разработку игр, создание уровней и применение инструментов Unity.

20  Предисловие

Для начала ознакомимся с основами документации игрового дизайна,
научимся фиксировать геометрию уровня, добавим освещение и простую систему частиц.
В главе 7 «Движение, управление камерой и столкновения» мы обсудим
различные подходы к перемещению объекта-игрока и настройке камеры
с видом от третьего лица. Для создания более реалистичного передвижения задействуем элементы физики Unity, посмотрим, как работать
с коллайдерами и «ловить» взаимодействия на сцене.
В главе 8 «Программируем механику игры» мы узнаем само понятие
игровой механики и то, как эффективно применять эту концепцию.
Начнем с добавления простого действия — прыжка, затем реализуем
механику стрельбы и, взяв уже готовый код из предыдущих глав, добавим логику для обработки сбора предметов.
В главе 9 «Основы ИИ и поведение врагов» мы начнем с краткого
обсуждения реализации искусственного интеллекта в играх и тех концепций, которые понадобятся нам в игре Hero Born. Мы рассмотрим
вопросы навигации в Unity, научимся пользоваться геометрией уровня
и навигационной сеткой, умными агентами, а также реализуем автоматическое движение противника.
В главе 10 «Снова о типах, методах и классах» мы более подробно
поговорим о типах данных, углубимся в изучение методов и дополнительных поведений, которые можно использовать для реализации более
сложных классов. Вы еще больше узнаете об универсальности и широте
применения языка C#.
В главе 11 «Знакомство со стеками, очередями и HashSet» мы рассмотрим более сложные типы коллекций и их особенности, поговорим
об использовании стеков, очередей и типа HashSet, а также рассмотрим ситуации, для которых каждый из этих типов подходит просто
идеально.
В главе 12 «Обобщения, делегаты и многое другое» подробно описаны
более сложные функции языка C# и их применение в реальных практических задачах. Начнем с концепции обобщенного программирования,
затем рассмотрим понятия делегирования, событий и обработку исклю-

Как получить от книги максимум  21

чений. В конце главы вкратце изучим общие паттерны проектирования
и подготовим фундамент для вашего дальнейшего путешествия в мир
разработки.
В главе 13 «Путешествие продолжается» мы вспомним все то, что
изучили в данной книге, и рассмотрим примеры ресурсов для дальнейшего изучения C# и Unity. Это будут и материалы в Интернете,
и информация о сертификации, и множество моих любимых каналов
с видеоуроками.

Как получить от книги максимум
Чтобы получить максимум пользы из данного путешествия в страну C# и Unity, вам понадобится всего ничего: любопытство и желание
учиться. Это значит, вам стоит выполнить все задания рубрик «Время
действовать», «Испытание героя» и «Контрольные вопросы», поскольку вам потребуется закрепить вновь обретенные знания. Наконец, прежде, чем двигаться дальше, всегда полезно возвращаться к пройденным
темам и главам, чтобы освежить или закрепить понимание материала.
На неустойчивом фундаменте дом не построить.
Кроме того, вам нужно будет установить на компьютер актуальную
версию Unity. Рекомендуется версия 2020 или более поздняя. Все примеры кода были протестированы на Unity 2020.1 и должны без проблем
работать и в более новых версиях.
Программное обеспечение, используемое в книге:
zzUnity 2020.1 или новее;
zzVisual Studio 2019 или новее;
zzC# 8.0 или новее.

Прежде чем начать, убедитесь, что ваш компьютер соответствует системным требованиям Unity: docs.unity3d.com/ru/current/Manual/systemrequirements.html. Это требования для Unity 2019, но они актуальны и для
более новых версий.

22  Предисловие

Скачивание файлов
с примерами кода
Файлы с примерами кода для этой книги можно скачать на сайте
github.com.
Чтобы скачать файлы кода, выполните следующие действия.
1. Перейдите по ссылке github.com/PacktPublishing/Learning-C-8-by-DevelopingGames-with-Unity-2020.
2. Нажмите кнопку ↓ Code и выберите пункт Download ZIP.
3. Скачайте ZIP-архив с примерами кода.
После загрузки файла вам нужно будет распаковать его с помощью последней версии следующего ПО:
zzWinRAR/7-Zip для Windows;
zzZipeg/iZip/UnRarX для macOS;
zz7-Zip/PeaZip для Linux.

Скачивание цветных изображений
Вы также можете скачать PDF-файл с цветными снимками экрана
и графиками, приведенными в оригинальной книге, по ссылке: static.packtcdn.com/downloads/9781800207806_ColorImages.pdf.

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

таблиц баз данных, имена файлов и путей, расширения файлов, вводимые пользователем данные и имена пользователей Twitter. Например,
«Рассмотрим сценарий LearningCurve».

От издательства  23

Блок кода форматируется следующим образом:
public string firstName = "Harrison";

Если необходимо заострить внимание на определенной части кода, то
эти строки или элементы выделяются полужирным моноширинным шрифтом:
accessModifier returnType UniqueName(parameterType parameterName) {
method body
}

Курсивом оформляются новые термины.
оформляются URL, имена папок, важное слово
или слова, которые вы видите на экране. Например, это могут быть
пунк­ты меню, фразы в диалоговых окнах: «Выберите команду Crea­
te3D ObjectCap­sule на панели Hierarchy».
Шрифтом без засечек

Предупреждения или важные примечания оформлены так.

Подсказки и полезные «фишки» оформлены так.

От издательства
Ваши замечания, предложения, вопросы отправляйте по адресу
comp@piter.com (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На сайте издательства www.piter.com вы найдете подробную информацию
о наших книгах.

1

Знакомство
со средой

В массовой культуре программисты часто представляются эдакими
аутсайдерами, одиночками, хакерами до мозга костей, которые имеют
фантастические способности к алгоритмическому мышлению, странные
анархические наклонности и притом совершенно не адаптированы к социальной жизни. Конечно, это не так, но стоит отметить, что изучение
программирования коренным образом меняет ваш взгляд на мир. Хорошо
здесь то, что ваш любознательный ум быстро адаптируется к этому новому образу мышления и даже начинает получать от него удовольствие.
Даже в повседневной жизни мы используем аналитические навыки,
которые можно перенести в программирование, и зачастую вам просто не хватает подходящего языка и синтаксиса, который позволил бы
показать эти навыки в коде. Ну, к примеру, вы знаете свой возраст?
Это переменная. Когда вы переходите улицу, вы, скорее всего, как и все,
смотрите на дорогу в обоих направлениях, а затем начинаете движение.
В жизни это оценка различных условий, а в программировании —
управление потоком выполнения. Глядя на банку с консервами, вы
подсознательно определяете, что у нее есть какие-то свойства: форма,
вес, содержимое. Это объект класса! Ну вы поняли.
Имея опыт реальной жизни, вы можете перенести его в мир программирования. Вам необходимо знать, как настроить среду разработки,
работать с приложениями и где искать помощи, когда она потребуется.
Поэтому в начале нашего приключения в страну C# мы рассмотрим
следующие вопросы:
zzначало работы в Unity;
zzработу в Visual Studio;
zzиспользование C# в Unity;
zzизучение документации.

Начинаем работу в Unity 2020  25

Технические требования
Когда необходимо нечто описать, иногда проще начать с того, чем
оно не является. Так вот, в этой книге мы не ставим цель охватить все
тонкости игрового движка Unity и разработки игр. Мы начнем с постепенного рассмотрения необходимых тем на базовом уровне, а затем
более подробно продолжим в главе 6. При этом все это делается лишь
для того, чтобы начать изучать язык программирования C# с нуля
в увлекательной и доступной манере.
Данная книга предназначена для начинающих программистов, поэтому
если у вас нет опыта работы с C# или Unity, то вы по адресу! Если же
немного работали с редактором Unity, но не занимались программированием, то… все равно пришли куда надо. И даже если вы немного
знакомы и с C#, и с Unity, но хотите изучить их глубже и рассмотреть
более продвинутые темы, в более поздних главах книги вы найдете искомое.
Если у вас уже есть серьезный опыт программирования на
других языках, то можете смело пропустить теорию для начинающих и сразу переходить к тому, что вас интересует.
А можете никуда не спешить и освежить в памяти основы.

Начинаем работу в Unity 2020
Если у вас еще не установлена среда Unity или ваша версия устарела,
то вам придется немного поработать. Выполните следующие действия.
1. Зайдите на сайт https://www.unity.com (вид сайта показан на рис. 1.1).
2. Нажмите кнопку Get Started, чтобы перейти на страницу магазина
Unity.
Вид главной страницы может отличаться от приведенного на
снимке экрана. В этом случае вы можете перейти по прямой
ссылке store.unity.com.

Не переживайте — вы можете получить Unity совершенно бесплатно!

26  Глава 1



Знакомство со средой

Рис. 1.1

3. Перейдите на вкладку Individual и выберите слева параметр Personal.
В других, платных конфигурациях есть более продвинутые функции
и подписки на сервисы (рис. 1.2). При желании можете почитать
о них самостоятельно.

Рис. 1.2

Начинаем работу в Unity 2020  27

После того как вы выберете тариф, вас спросят, впервые ли вы скачиваете Unity или уже занимались им ранее.
4. Нажмите кнопку Start here в разделе First-time Users (рис. 1.3).

Рис. 1.3

5. Нажмите кнопку Agree and download, чтобы скачать Unity Hub, как показано на рис. 1.4.

Рис. 1.4

28  Глава 1



Знакомство со средой

После того как загрузка будет завершена, выполните следующие действия.
1. Откройте загруженный файл (двойным щелчком кнопкой мыши).
2. Примите пользовательское соглашение.
3. Следуйте инструкциям по установке. Когда все получится, запустите приложение Unity Hub, и вы увидите следующий экран
(рис. 1.5).

Рис. 1.5

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

4. Запустите Unity Hub, перейдите на вкладку Installs в меню слева и нажмите кнопку ADD (рис. 1.6).

Начинаем работу в Unity 2020  29

Рис. 1.6

На момент написания книги новейшая версия Unity 2020 еще находится в стадии альфа-тестирования, но вы можете выбрать эту версию из
списка Latest Official Releases (рис. 1.7).

Рис. 1.7

30  Глава 1



Знакомство со средой

Для работы с примерами из книги вам не понадобятся какие-либо модули для конкретных платформ, поэтому данный шаг можно пропустить.
Если вы захотите загрузить их позже, то всегда можете нажать кнопку
More (значок с тремя точками) в правом верхнем углу любой версии
в окне Installs (рис. 1.8).

Рис. 1.8

Когда установка будет завершена, вы увидите новую версию программы
на панели Installs (рис. 1.9).

Рис. 1.9

Начинаем работу в Unity 2020  31

Дополнительную информацию и ресурсы приложения Unity
Hub можно найти по адресу docs.unity3d.com/ru/current/
Manual/GettingStartedInstallingHub.html.

Всегда что-то может пойти не так, поэтому обязательно ознакомьтесь
со следующим подразделом, если вы работаете в macOS Catalina или
более новой версии.

Если у вас macOS
Если вы работаете на Mac под управлением операционной системы
Catalina или более поздней версии, то в этой ОС есть известная проблема
использования Unity Hub 2.2.2 (и более ранних версий) для установки
Unity по описанному выше алгоритму. При наличии данной проблемы
сделайте глубокий вдох, зайдите в архив загрузок Unity и скачайте нужную вам версию (https://unity3d.com/get-unity/download/archive). Не забудьте
выбрать опцию Downloads (Mac) вместо Unity Hub (рис. 1.10).

Рис. 1.10

Если вы сталкиваетесь с подобными проблемами и в операционной системе Windows, то этот алгоритм подойдет и вам.

32  Глава 1



Знакомство со средой

Мы скачали установщик приложения в виде файла .dmg . Откройте
его, следуйте инструкциям, и все будет готово в считаные мгновения
(рис. 1.11)!

Рис. 1.11

Все примеры и снимки экрана для данной книги были созданы в Unity 2020.1.0a20. Если вы используете более новую
версию, то редактор Unity может выглядеть немного иначе,
но проблем от этого быть не должно.

Теперь, когда мы установили Unity Hub и Unity 2020, пора создать
новый проект!

Создание нового проекта
Чтобы создать новый проект, запустите приложение Unity Hub. Если
у вас есть учетная запись Unity, то войдите в систему. Если нет, то можете создать ее или нажать кнопку Skip в нижней части экрана.
Теперь настроим новый проект, щелкнув на треугольнике рядом с вкладкой NEW в правом верхнем углу (рис. 1.12).

Начинаем работу в Unity 2020  33

Рис. 1.12

Выберите вашу версию Unity и заполните следующие поля.
zzProject name: я назову проект Hero Born.
zzLocation: здесь мы укажем, где хотим сохранить проект.
zzTemplate:

по умолчанию создается 3D-проект, поэтому можно сразу
нажимать кнопку CREATE (рис. 1.13).

Рис. 1.13

34  Глава 1



Знакомство со средой

Когда проект создан, можно переходить к изучению интерфейса
Unity.

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

Рис. 1.14

Рассмотрим каждую из панелей более подробно.
1. Панель Toolbar — самая верхняя часть редактора Unity. На этой панели можно управлять объектами (кнопки слева), а также запускать
и приостанавливать игру (центральные кнопки). Справа расположены кнопки сервисов Unity, слои-маски и опции макетов, которые мы
не будем использовать в этой книге.
2. На панели Hierarchy отображаются все элементы, находящиеся в данный момент на игровой сцене. Во вновь созданном проекте есть
камера и направленный источник света, но по мере создания игры
эта панель начнет наполняться объектами.

Использование C# с Unity  35

3. Панели Game и Scene — самые визуально наглядные части редактора.
Панель Scene — ваша рабочая поверхность, на которой вы можете размещать и перемещать 2D- и 3D-объекты. Когда вы нажимаете кнопку
Play, появляется окно Game, в котором будет показана та же сцена, но
уже с рабочими запрограммированными взаимодействиями.
4. Панель Inspector — обобщенный инструмент для просмотра и редактирования свойств ваших объектов. Выбрав компонент Main Camera, вы
увидите, что у него есть несколько частей (в Unity они называются
компонентами) и все они находятся именно здесь.
5. В окне Project представлены все ресурсы, которые в настоящее время
находятся в вашем проекте. Если проще, то это все файлы и папки
вашего проекта.
6. На панели Console станут появляться выходные данные, которые
будут выводить наши сценарии. С этого момента, если мы станем говорить о выводе консоли или отладки, то будем иметь в виду именно
это место.
Более подробное описание функциональности каждой панели
можно найти в документации Unity по адресу docs.unity3d.com/
ru/current/Manual/UsingTheEditor.html.

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

Использование C# с Unity
Забегая вперед, отмечу, что нужно рассматривать Unity и C# как симбиотические сущности. Unity — это движок, в котором вы будете создавать сценарии и в дальнейшем запускать их, но фактическое программирование происходит в другой программе под названием Visual
Studio. Однако прямо сейчас об этом задумываться не нужно, ведь мы
вернемся к данному вопросу через мгновение.

36  Глава 1



Знакомство со средой

Работа со сценариями C#
Хоть мы еще и не рассмотрели основныеконцепции программирования, нам негде будет их применять, пока мы не узнаем, как создать
сценарий C# в Unity.
Есть несколько способов создания сценариев C# из редактора.
zzВыберите команду AssetsCreateС# Script.
zzНа панели Project выберите команду CreateС# Script.
zzЩелкните

правой кнопкой мыши на панели Project (справа) и выберите команду CreateC# Script из всплывающего меню.

zzВыберите объект GameObject на панели Hierarchy и нажмите Add Compo­
nentNew Script.

В дальнейшем, когда нужно будет создать сценарий C#, вы можете
использовать любой из этих способов, который вам больше нравится.
Эти же способы позволяют создавать и другие ресурсы и объекты, а не только сценарии C#. Я не буду перечислять все их
каждый раз, когда создаем что-то новое, поэтому запомните
их сразу и надолго.

Из соображений сохранения порядка мы будем хранить наши ресурсы
и сценарии в специально отведенных для них папках. Это нужно делать
не только при работе с Unity, и ваши коллеги будут вам благодарны
(обещаю).
1. Выберите команду CreateFolder (или любой другой способ, который вам больше нравится) на панели Project и назовите папку Scripts
(рис. 1.15).
2. Дважды щелкните на папке Scripts и создайте новый сценарий C#.
По умолчанию сценарий будет называться NewBehaviourScript, но
имя файла будет выделено, поэтому вы тут же сможете переименовать его. Введите название LearningCurve и нажмите клавишу Enter
(рис. 1.16).

Использование C# с Unity  37

Рис. 1.15

Рис. 1.16

Мы только что создали подпапку с именем Scripts , и она показана
на рис. 1.16. Внутри этой папки мы создали сценарий C# с именем
LearningCurve.cs (тип файла .cs означает C-Sharp, если вдруг интересно), и он стал одним из активов проекта Hero Born. Нам осталось лишь
открыть файл в Visual Studio!

38  Глава 1



Знакомство со средой

Редактор Visual Studio
В самом Unity можно создавать и хранить сценарии C#, но редактировать их придется с помощью Visual Studio. Дистрибутив Visual Studio
идет в комплекте с Unity и откроется автоматически, если вы дважды
щелкнете на любом сценарии C# из редактора.

Время действовать. Открываем файл C#
Unity синхронизируется с Visual Studio при первом открытии файла. Самый простой способ сделать это — выбрать сценарий на панели Project.
Дважды щелкните на файле LearningCurve.cs (рис. 1.17).

Рис. 1.17

В результате файл C# откроется в Visual Studio (рис. 1.18).
Если файл по умолчанию открывается в другом приложении, то выполните следующие действия.
1. Выберите команду UnityPreferences в верхнем меню, а затем на левой
панели выберите External Tools.
2. Измените параметр External Script Editor на Visual Studio, как показано на
рис. 1.19.

Использование C# с Unity  39

Рис. 1.18

Рис. 1.19

В левой части интерфейса Visual Studio вы увидите структуру папок,
отражающую структуру в Unity, и работать с ней можно будет аналогичным образом. Справа находится сам редактор кода, в котором
и творится волшебство. В приложении Visual Studio гораздо больше
возможностей, но для начала нам будет достаточно и этого.
Интерфейс Visual Studio в Windows и macOS отличается, но
код, который мы будем использовать в данной книге, будет
одинаково правильно работать в обеих ОС. Все снимки экрана для книги были сделаны в среде Mac, поэтому, если на
вашем компьютере все выглядит по-другому, волноваться
не надо.

40  Глава 1



Знакомство со средой

Остерегайтесь несоответствий в именах
Одна из распространенных ошибок, которая сбивает с толку начинающих программистов, — имена файлов, а точнее, несоответствие этих
имен. Проиллюстрируем проблему с помощью строки 5 из скриншота
файла C# в Visual Studio, показанного выше, на рис. 1.18:
public class LearningCurve : MonoBehaviour

Имя класса LearningCurve совпадает с именем файла LearningCurve.cs.
Это обязательное требование. Пусть даже вы еще и не знаете, что такое
класс, важно помнить: в Unity имя файла и имя класса должны совпадать. Но если вы используете C# вне Unity, то это правило соблюдать
не обязательно.
Когда вы создаете файл сценария C# в Unity, имя файла на панели
Project сразу находится в режиме редактирования и готово к изменению. Лучше взять за привычку сразу переименовывать файл. Если вы
переименуете сценарий позже, то имя файла и имя класса не будут совпадать. Тогда имя файла изменится, но пятая строка будет выглядеть
следующим образом:
public class NewBehaviourScript : MonoBehaviour

Если вы случайно сделаете так, то это не вызовет катастрофу. Чтобы
все починить, достаточно будет войти в Visual Studio и заменить имя
класса NewBehaviourScript на имя вашего сценария C#.

Синхронизация файлов C#
В рамках симбиотических отношений Unity и Visual Studio поддерживают связь друг с другом, чтобы синхронизировать контент. Это значит, что если вы добавляете, удаляете или изменяете файл сценария
в одном приложении, то другое приложение автоматически увидит эти
изменения.
А что произойдет, если сработает закон Мёрфи и синхронизация попросту не выполнится? Столкнувшись с такой ситуацией, сделайте глубокий вдох, найдите проблемный сценарий, щелкните правой кнопкой
мыши и выберите команду Refresh.

Изучение документации  41

Теперь вы знаете основы создания сценариев, поэтому пришло время
поговорить о поиске и эффективном использовании полезных ресурсов.

Изучение документации
Последняя тема, которую мы осветим в нашем первом контакте с Unity
и C#, — документация. Это скучно, знаю, но важно как можно раньше
сформировать правильные навыки работы с новыми языками программирования или средами разработки.

Доступ к документации Unity
Как только вы начнете писать серьезные сценарии, вам придется довольно часто работать с документацией Unity, поэтому будет полезно
как можно раньше узнать, где ее найти. В руководстве по программированию (Reference Manual) можно почитать о конкретном компоненте
или теме, а примеры кода можно найти в Scripting Reference (справочнике по сценариям).

Время действовать. Читаем руководство
по программированию
У каждого объекта GameObject (элемент на панели Hierarchy) на сцене
есть компонент Transform, который определяет его положение, поворот
и масштаб. Для простоты найдем в руководстве по программированию
компонент Transform у камеры.
1. На панели Hierarchy выберите объект Main Camera.
2. Перейдите на вкладку Inspector и щелкните на значке информации (знак вопроса) в правом верхнем углу компонента Transform
(рис. 1.20).
После этого откроется браузер, а в нем появится руководство по программированию на странице Transform. Все компоненты Unity снабжены
справкой, поэтому, если вам потребуется узнать больше об их работе,
вы знаете, что делать (рис. 1.21).

42  Глава 1



Знакомство со средой

Рис. 1.20

Рис. 1.21

Время действовать. Читаем Scripting Reference
Итак, у нас открыто руководство по программированию, но что, если
нам нужны конкретные примеры кода, связанные с компонентом
Transform? Тут тоже все просто — нам поможет Scripting Reference.
Выберите Scripting API или ссылку Switch to Scripting под именем компонента
или класса (в данном случае компонента Transform).

Изучение документации  43

После этого руководство по программированию автоматически переключится на Scripting Reference для компонента Transform (рис. 1.22).

Рис. 1.22

Scripting Reference — большой документ, но таким он и должен быть. Однако это не означает, что вам нужно выучить
его целиком или даже прочитать всю приведенную в нем
информацию, чтобы начать писать сценарии. Это справочник, а не тест.

Если вы запутались в документации или просто не знаете, где что искать, за решением многих проблем можно обратиться к огромному
сообществу разработчиков Unity:
zzforum.unity.com/;
zzanswers.unity.com/index.html;
zzdiscord.com/invite/unity.

Кроме того, вам нужно знать, где найти ресурсы по любому вопросу,
связанному с языком C#, о чем мы и поговорим далее.

44  Глава 1



Знакомство со средой

Поиск ресурсов C#
Теперь, когда у нас есть нужные ресурсы по Unity, почитаем документацию по Microsoft C# на docs.microsoft.com/ru-ru/dotnet/csharp/programmingguide/.
Существует и множество других ресурсов по языку C#, начиная от справочников и руководств по быстрому запуску
и заканчивая спецификациями версий (если вам такое нравится). Все это можно найти по адресу docs.microsoft.com/
ru-ru/dotnet/csharp/.

Время действовать. Находим класс C#
Откроем руководство по программированию и найдем класс String
языка C#. Выполните одно из следующих действий.
zzВведите Strings в строку поиска в верхнем левом углу веб-страницы.
zzПрокрутите

вниз до раздела Language Sections и щелкните на ссылке
Strings (рис. 1.23).

Рис. 1.23

На странице описания класса вы увидите нечто наподобие этого
(рис. 1.24). В отличие от документации по Unity справка по C# и ин-

Подведем итоги  45

формация о сценариях объединены в одно целое, для простоты справа
вынесен список подтем. Пользуйтесь на здоровье.

Рис. 1.24

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

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

46  Глава 1



Знакомство со средой

понятийного характера, мы все же напишем первые строки сценария
LearningCurve. Пристегните ремни!

Контрольные вопросы. Работа
со сценариями
1. Как взаимосвязаны Unity и Visual Studio?
2. В Scripting Reference приведен пример кода, в котором показано
применение определенного компонента или функции Unity. А где
можно найти более подробную (не связанную с кодом) информацию
о компонентах Unity?
3. Scripting Reference — большой документ. Какую его часть вам придется запомнить, прежде чем вы сможете написать сценарий?
4. В какой момент лучше всего давать имя сценарию C#?

2

Основные элементы
программирования

Любой язык программирования несведущему человеку кажется китайской грамотой, и C# в этом смысле не исключение. Но не все так
плохо — за непонятными словами у всех языков программирования
скрываются одни и те же основные элеметы. Переменные, методы
и классы (или объекты) — вот в чем заключается суть традиционного
программирования. Усвоение этих простых понятий откроет перед
вами целый мир разнообразных и сложных приложений. Тут все как
у людей: в ДНК каждого человека на Земле есть всего четыре различных нуклеооснования, но все равно все мы разные, уникальные.
Если вы еще не знакомы с программированием, то в этой главе будет
много новой для вас информации, и здесь вы напишете первые в своей жизни строки кода. Я не пытаюсь перегрузить ваш мозг фактами
и цифрами, а лишь хочу максимально полно и ясно рассказать об
основных элементах программирования, опираясь на примеры из повседневной жизни.
В этой главе я приведу высокоуровневый разбор элементов, из которых
состоит программа. Познакомившись с принципами работы до того, как
переходить непосредственно к написанию кода, вы как начинающий
программист будете крепче стоять на ногах, лучше поймете материал,
а хорошо запоминающиеся примеры лишь укрепят это понимание.
Среди прочего в данной главе мы обсудим следующие вопросы:
zzпонятие переменных и способы их использования;
zzназначение методов;
zzклассы и как они «превращаются» в объекты;
zzкак превратить сценарии C# в компоненты Unity;
zzсвязь между компонентами и точечную нотацию.

48  Глава 2



Основные элементы программирования

Определение переменных
Начнем с простого вопроса: что такое переменная? В зависимости от точки зрения ответить на этот вопрос можно несколькими способами.
zzКонцептуально переменная — это мельчайшая базовая единица про-

граммирования, как атом для физического мира (умолчу о теории
струн). Все начинается с переменных, и без них программы попросту
не могут существовать.
zzТехнически переменная — небольшой фрагмент памяти вашего ком-

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

сути переменная — контейнер. При необходимости вы можете
самостоятельно создавать их, заполнять чем-то, перемещать, изменять содержимое и ссылаться на них. Иногда полезны даже пустые
переменные.

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

Рис. 2.1

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

Определение переменных  49

Имена важны
Еще раз посмотрим на рис. 2.1. Если я попрошу вас пойти и открыть
почтовый ящик, вы, скорее всего, захотите уточнить: «Какой именно?» Если бы я сказал более точно, например: «ящик Ивановых», «коричневый почтовый ящик» или «круглый почтовый ящик», то у вас
было бы достаточно информации (или контекста) для выполнения
моего поручения. Аналогично, создавая переменную, вы должны дать
ей уникальное имя, по которому можно было бы обратиться к ней позже. Об особенностях правильного форматирования и описательного
именования мы подробнее поговорим в главе 3.

Переменные — это «коробки»
Объявляя переменную и давая ей имя, вы словно создаете пустую коробку для значения, которое хотите сохранить. Для примера возьмем
следующее простое математическое равенство:
2 + 9 = 11

Здесь все просто, но что, если бы мы хотели, чтобы число 9 было взято
из переменной? Рассмотрим следующий блок кода:
myVariable = 9

Теперь вместо числа 9 мы можем использовать имя переменной myVa­
riable везде, где требуется:
2 + myVariable = 11

Если вам интересно, есть ли у переменных другие правила
или ограничения, то да. О них поговорим в следующей главе,
поэтому пока не торопитесь.

Приведенный выше пример не является реальным кодом C#, но зато
иллюстрирует возможности переменных и их применение в качестве
ссылок на «коробку со значением». Далее мы начнем создавать собственные переменные, так что вперед!

50  Глава 2



Основные элементы программирования

Время действовать. Создаем переменную
Пожалуй, хватит теории. Создадим настоящую переменную в нашем
сценарии LearningCurve.
1. Дважды щелкните на сценарии LearningCurve, чтобы открыть его
в Visual Studio, затем добавьте в него строки 7, 12 и 14 (пока не думайте о синтаксисе, а просто перепишите указанные строки с этого
снимка экрана (рис. 2.2)).

Рис. 2.2

2. Сохраните файл, используя сочетание клавиш +S на клавиатуре
Mac или Ctrl+S на клавиатуре Windows.
Чтобы скрипты запускались в Unity, их нужно прикрепить к объекту
GameObject на сцене. По умолчанию в проекте HeroBorn появились камера и направленный свет, который создает освещение сцены. Упростим
задачу, прикрепив LearningCurve к камере.
1. Перетащите сценарий LearningCurve.cs на объект Main Camera.
2. Выберите объект Main Camera, чтобы он появился на панели Inspector,
и убедитесь, что компонент LearningCurve.cs (Script) прикреплен правильно.

Определение переменных  51

3. Нажмите кнопку Play и посмотрите, что появится на панели Console
(рис. 2.3).

Рис. 2.3

Операторы Debug.Log() вывели в консоли результат вычисления простых математических выражений, которые мы заключили в круглые
скобки. Как видно на снимке панели Console (рис. 2.4), выражение,
в котором использовалась наша переменная, сработало так же, как и выражение с числами.

Рис. 2.4

В конце этой главы мы рассмотрим, как Unity преобразует сценарии C#
в компоненты, но сначала попробуем изменить значение одной из наших переменных.

52  Глава 2



Основные элементы программирования

Время действовать. Меняем значение переменной
Поскольку в строке 7 мы объявили переменную currentAge, значение,
которое в ней хранится, можно изменить. После этого уже новое значение будет подставляться туда, где переменная используется в коде.
Посмотрим, как это работает.
1. Остановите игру, нажав кнопку Play, если сцена все еще запущена.
2. На панели Inspector измените значение параметра Current Age на 18,
снова запустите сцену и посмотрите на результат на панели Console
(рис. 2.5).

Рис. 2.5

Первый оператор по-прежнему вывел 31, а второй — уже 19, поскольку
мы изменили значение нашей переменной.
Цель здесь заключалась не в прохождении синтаксиса переменных, а в демонстрации того, что переменные работают
как контейнеры, которые мы один раз создаем, а затем
ссылаемся на них в другом месте. Подробнее об этом поговорим в главе 3.

Понятие метода  53

Теперь, зная, как создавать переменные в C# и присваивать им значения, мы готовы рассмотреть следующий важный элемент программирования: методы!

Понятие метода
Переменные могут лишь хранить присвоенные им значения. Эта функция невероятно важна, но сама по себе не слишком полезна с точки
зрения создания серьезных приложений. Итак, как нам создать в коде
какие-либо действия и управлять поведением? Ответ прост: с помощью
методов.
Прежде чем я расскажу, что такое методы и как их применять, нужно
немного прояснить один момент из терминологии. В мире программирования термины «метод» и «функция» часто используются как
синонимы, особенно в Unity. Поскольку C# — объектно-ориентированный язык (в главе 5 мы рассмотрим, что означает это понятие), на
протяжении всей книги я буду употреблять термин «метод», чтобы
соответствовать стандартным рекомендациям C#.
Когда в Scripting Reference или в любой другой документации
вы встретите слово «функция», это будет то же самое, что
я здесь называю методом.

Методы — это движущая сила
Как и в случае с переменными, определение методов в программировании может быть или утомительно длинным, или опасно кратким. Снова
подойдем к термину с трех сторон.
zzКонцептуально

методы — это то, как в приложении выполняется

работа.
zzТехнически

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

54  Глава 2



Основные элементы программирования

принимать аргументы (также называемые параметрами), которые
можно использовать внутри области действия метода.
zzПо сути метод — контейнер для набора инструкций, выполняющих-

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

Методы — это тоже «коробки»
Возьмем тривиальный пример сложения двух чисел, чтобы понять
концепцию. При написании сценария вы, по сути, пишете строки кода,
которые компьютер должен выполнить по порядку. Когда вам впервые
нужно сплюсовать два числа, вы можете просто взять и сложить их, как
показано ниже:
someNumber + anotherNumber

Но затем оказывается, что эти числа нужно сложить где-то еще. Вместо
того чтобы копировать и вставлять один и тот же код, что приводит
к появлению неаккуратного кода (или так называемого спагетти-кода)
и чего следует избегать любой ценой, вы можете создать именованный
метод, который будет выполнять сложение:
AddNumbers
{
someNumber + anotherNumber
}

Теперь метод AddNumbers хранится в памяти как переменная, но вместо
значений содержит набор инструкций. Использование имени метода
(или его вызов) в любом месте сценария позволяет выполнить сохраненные в нем инструкции, не прибегая к необходимости повторно
писать что-либо.

Понятие метода  55

Если вы в какой-то момент обнаружите, что пишете одни
и те же строки кода снова и снова, то наверняка этот код
можно упростить или объединить повторяющиеся действия
в методы.
Повторное написание одного и того же кода приводит к явлению, которое программисты в шутку называют спагетти-кодом, поскольку он получается беспорядочным. В связи с этим
часто можно услышать о принципе Don’t Repeat Yourself (DRY),
то есть «Не повторяйся», и о нем следует помнить.

Как и раньше, рассмотрев новую концепцию в псевдокоде, лучше всего
реализовать ее самостоятельно и довести до ума, что мы и сделаем ниже.

Время действовать. Создаем простой метод
Снова откроем файл LearningCurve и посмотрим на работу методов
в C#. Как и в примере с переменными, перепишите код в свой сценарий,
чтобы получить то же, что и на рис. 2.6. Я удалил предыдущий пример
кода, чтобы не было беспорядка, но вы можете и сохранить его в своем
сценарии для справки.

Рис. 2.6

56  Глава 2



Основные элементы программирования

1. Откройте сценарий LearningCurve в Visual Studio и добавьте строки 8, 13 и 16–19.
2. Сохраните файл, а затем вернитесь в Unity и нажмите кнопку Play,
чтобы посмотреть, что появилось в консоли.
Мы определили первый метод в строках с 16-й по 19-ю и вызвали его
в строке 13. Теперь везде, где мы будем вызывать метод AddNumbers(),
программа станет суммировать две переменные и выводить их в консоль, даже если их значения изменятся (рис. 2.7).

Рис. 2.7

Самостоятельно попробуйте задавать разные значения переменных на
панели Inspector, чтобы проверить, как это работает. Подробнее о самом
синтаксисе кода, который вы только что написали, поговорим в следующей главе.
Теперь, получив базовое понимание работы методов, мы готовы перейти
к самой серьезной теме в области программирования — классам!

Знакомство с классами
Мы уже знаем, что переменные хранят информацию и методы выполняют действия, но пока наш инструментарий программирования все еще
несколько ограничен. Нам нужна возможность создать суперконтейнер
со своими переменными и методами, на которые можно ссылаться из
самого контейнера. Это и будут классы.
zzКонцептуально класс хранит некую информацию, действия и пове-

дение внутри одного контейнера. Эти элементы могут даже общаться
друг с другом.

Знакомство с классами  57
zzТехнически

классы — структуры данных. Они могут содержать
переменные, методы и другую программную информацию, и на все
эти элементы можно ссылаться при создании объекта класса.

zzПо сути класс — некий шаблон. Он устанавливает правила для лю-

бого объекта (называемого экземпляром), созданного с помощью
этого шаблона.
Вы наверняка поняли, что классы есть не только в Unity, но и в реальном мире. Далее мы рассмотрим наиболее распространенный класс
Unity и то, как классы работают в реальных условиях.

Стандартный класс Unity
Прежде чем задаться вопросом, как выглядит класс в C#, отметим, что
всю эту главу вы уже работали с классом. По умолчанию каждый сценарий, созданный в Unity, является классом, и на это намекает ключевое
слово class в строке 5:
public class LearningCurve: MonoBehavior

Имя MonoBehavior просто означает, что этот класс может быть присоединен к GameObject в сцене Unity. В C# классы могут существовать
сами по себе, что мы увидим, когда будем писать автономные классы
в главе 5.
Термины «сценарий» и «класс» иногда используются в ресурсах Unity как синонимы. Для единообразия я буду называть
файлы C# сценариями, если они прикреплены к объектам
GameObject, и классами, если они автономны.

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

58  Глава 2



Основные элементы программирования

Класс PostOffice — это отличный пример потенциального класса, который мы можем описать в следующем псевдокоде:
PostOffice
{
// Переменные
Address = "1234 Letter Opener Dr."

}

// Методы
DeliverMail()
SendMail()

Основная польза здесь заключается в том, что, когда информация и поведение следуют заранее определенному шаблону, становится возможным организовать сложные действия и межклассовое общение.
Например, если у нас есть другой класс, который хочет отправить
письмо через наш класс, то ему не придется гадать, куда идти, чтобы это
сделать. Можно просто вызвать функцию SendMail из класса PostOffice
следующим образом:
PostOffice.SendMail()

Кроме того, мы можем получить адрес почтового отделения, чтобы
знать, куда отправлять письма:
PostOffice.Address

Если вас интересует, откуда взялись точки между словами
(точечная нотация), то мы рассмотрим это в конце главы —
держитесь крепче.

Теперь базовый инструментарий программирования в нашем распоряжении (ну, по крайней мере, его теоретическая часть). Далее мы
углубимся в синтаксис и практическое использование переменных,
методов и классов.

Работа с комментариями
Вы могли заметить, что в сценарии LearningCurve есть две строки серого
текста (строка 10 на рис. 2.6), начинающиеся с двух косых черт, которые

Работа с комментариями  59

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

Практичные косые
В сценарии LearningCurve есть однострочные комментарии:
// это однострочный комментарий

Visual Studio не видит в коде строк, начинающихся с двух косых черт
(без пробелов между ними), поэтому вы можете использовать их сколько угодно раз.

Многострочные комментарии
Из названия понятно, что однострочные комментарии охватывают
лишь одну строку кода. Если вам нужны многострочные комментарии,
то нужно использовать косую черту и звездочку в качестве открыва­
ющих и закрывающих символов вокруг текста комментария:
/* это
многострочный комментарий * /

Вы также можете комментировать и раскомментировать блоки кода, выделяя их и используя сочетание клавиш +?
в macOS и Ctrl+K+C в Windows.

Видеть примеры комментариев — это хорошо, а использовать их в своем
коде еще лучше. Начать комментировать никогда не рано!

60  Глава 2



Основные элементы программирования

Время действовать. Добавляем комментарии
В Visual Studio также есть удобная функция автоматического создания
комментариев. Введите три косые черты в строке, предшествующей
любой строке кода (переменные, методы, классы и т. д.), и в результате
появится блок комментариев summary. Откройте LearningCurve и добавьте три косые черты над методом ComputeAge() (рис. 2.8).

Рис. 2.8

Появится трехстрочный комментарий с описанием метода, созданный
Visual Studio для данного имени метода. Само описание находится
между двумя тегами . Разумеется, вы можете изменить текст
или добавить новые строки, нажав клавишу Enter, как и в текстовом документе, но теги при этом удалять нельзя.
Польза подробных комментариев очевидна, если вы хотите описать
созданный вами метод. Если вы использовали комментарий с тройной
косой чертой, то в дальнейшем можете навести указатель мыши на имя
метода в любом месте кода, и Visual Studio покажет ваш комментарий
(рис. 2.9).

Рис. 2.9

Осталось понять, как все, что мы узнали в этой главе, применяется в игровом движке Unity. И именно об этом поговорим в следующем разделе!

Собираем все вместе  61

Собираем все вместе
Когда мы разобрались со всеми нужными элементами по отдельности,
пришло время немного поработать с Unity, прежде чем завершать эту
главу. В частности, нам нужно узнать о том, как Unity обрабатывает
сценарии C#, прикрепленные к объектам GameObject. В этом примере
мы продолжим использовать наш сценарий LearningCurve и объект Main Camera.

Сценарии превращаются… в элегантные компоненты
Все компоненты GameObject — это сценарии, написанные вами или
добрыми людьми из команды Unity. Однако нам не нужно редактировать специфичные для Unity компоненты, такие как Transform, и их
сценарии.
Когда созданный вами сценарий помещается в объект GameObject, он
становится еще одним компонентом этого объекта и появляется на
панели Inspector. С точки зрения Unity он работает так же, как и любой
другой компонент, а его публичные переменные, показанные внутри
компонента, можно изменять в любое время. Несмотря на невозможность редактировать встроенные компоненты Unity, мы все равно
можем обращаться к их свойствам и методам, что делает их эффективными инструментами разработки.
Unity также автоматически настраивает удобочитаемость,
когда сценарий становится компонентом. Вы могли заметить,
что, когда мы добавили сценарий LearningCurve к объекту Main
Camera, Unity отобразил его имя как Learning Curve, а переменная currentAge превратилась в параметр Current Age.

В предыдущем пункте «Время действовать» мы уже пробовали менять
значение переменной на панели Inspector, и теперь пора более подробно
остановиться на том, как это работает. Есть две ситуации, в которых вы
можете изменить значение свойства:
zzв режиме воспроизведения игры;
zzв режиме разработки.

62  Глава 2



Основные элементы программирования

Изменения, внесенные в режиме воспроизведения, вступают в силу немедленно в реальном времени, что отлично подходит для тестирования
и настройки игрового процесса. При этом любые изменения, внесенные
в режиме игры, будут утрачены, когда вы остановите игру и вернетесь
в режим разработки.
Когда вы находитесь в режиме разработки, любые изменения, которые
вы вносите в переменные, будут сохранены в Unity. Это значит, что
если вы выйдете из Unity, а затем перезапустите его, то изменения сохранятся.
Изменения, которые вы вносите в значения на панели
Inspector, не влияют на сценарий, но в режиме воспроизведения заменяют собой любые значения, которые вы назначили
в сценарии.

Если вам нужно отменить какие-либо изменения, внесенные на панели
Inspector, вы можете сбросить сценарий до значений по умолчанию (иногда называемых начальными). Щелкните на значке с тремя вертикальными точками справа от любого компонента, а затем выберите команду
Reset, как показано на рис. 2.10.

Рис. 2.10

Собираем все вместе  63

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

Рука помощи от MonoBehavior
Если сценарии C# являются классами, то откуда Unity знает, нужно
делать сценарий компонентом или нет? Ответ прост: LearningCurve
(и любой сценарий, созданный в Unity) наследуется от MonoBehavior
(другого класса). Для Unity это означает, что класс C# можно преобразовать в компонент.
Тема наследования классов на данном этапе будет для вас сложновата.
Выразимся так: есть класс MonoBehaviour, который предоставляет несколько своих переменных и методов классу LearningCurve. В главе 5
мы рассмотрим наследование классов подробно.
Используемые нами методы Start() и Update() принадлежат классу
MonoBehavior, который Unity запускает автоматически для любого сценария, прикрепленного к GameObject. Метод Start() запускается один
раз при запуске сцены, а метод Update() выполняется в каждом кадре
(в зависимости от частоты кадров вашего компьютера).
Теперь, когда вы неплохо познакомились с документацией Unity, предлагаю вам решить небольшую дополнительную задачу, которую я для
вас подготовил!

Испытание героя. Ищем MonoBehavior в Scripting API
Теперь вам пора освоиться с документацией Unity самостоятельно,
и что может быть лучше, чем поискать некоторые из распространенных
методов MonoBehavior:
zzпопробуйте поискать методы Start() и Update() в Scripting API, что-

бы лучше понять, что и когда они делают в Unity;
zzесли не боитесь, то почитайте о классе MonoBehavior еще и в руковод-

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

64  Глава 2



Основные элементы программирования

Связь между классами
До сих пор я описывал классы и, как следствие, компоненты Unity
как отдельные автономные сущности. Однако в действительности они
глубоко переплетены. Сложно создать серьезное приложение, в котором
не было бы никакого взаимодействия или связи между классами.
Если вы еще не забыли предыдущий пример с почтовым отделением,
то в нем использовали точки, чтобы сослаться на классы, переменные
и методы. Если представить классы как каталоги информации, то точечная нотация — это инструмент индексации:
PostOffice.Address

С помощью точечной нотации можно получить доступ к любым переменным, методам или другим типам данных в классе. Это применимо
и к вложенной информации или информации о подклассах, но этими
вопросами мы займемся позже, в главе 5.
Точечная нотация также определяет связь между классами. Когда классу требуется информация о другом классе или он хочет выполнить один
из его методов, используется точечная нотация:
PostOffice.DeliverMail()

Точечная нотация иногда упоминается как «оператор (.)»,
поэтому не расстраивайтесь, если увидите в документации
нечто подобное.

Если точечная нотация вам пока не нравится, то не волнуйтесь, еще
притретесь. Это кровоток программы, передающий информацию и контекст туда, где это необходимо.

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

Контрольные вопросы. Основные элементы C#  65

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

Контрольные вопросы. Основные
элементы C#
1. Каково основное назначение переменных?
2. Какую роль в сценариях играют методы?
3. Как сценарий превратить в компонент?
4. Для чего нужна точечная нотация?

3

Погружение в переменные,
типы и методы

Поначалу в освоении любого языка программирования возникает
фундаментальная проблема — вы понимаете набираемые слова, но
не их назначение. Обычно в таких ситуациях возникает парадокс, но
программирование — особый случай.
C# написан на английском. Несоответствие между словами, которые
вы используете в своей жизни, и кодом в Visual Studio возникает из-за
отсутствия контекста, который всегда разный. Вы знаете, как произносить и записывать слова, используемые в C#, но не знаете, где, когда,
почему и, что наиболее важно, как именно они превращаются в язык
программирования.
В этой главе мы отойдем от теории программирования и сделаем
первые шаги на нашем пути к реальному программированию. Мы поговорим о принятых правилах форматирования, методах отладки
и составлении более сложных примеров переменных и методов. Нам
нужно осветить много вопросов, но к моменту, когда вы дойдете до
контрольных вопросов, мы рассмотрим такие высокоуровневые вопросы, как:
zzпишем на C# правильно;
zzотладка вашего кода;
zzобъявление переменных;
zzиспользование модификаторов доступа;
zzпонятие области видимости переменных;
zzработа с методами;
zzанализ распространенных методов Unity.

Пишем на C# правильно  67

Пишем на C# правильно
Строки кода работают как предложения, то есть в них должен быть
некий разделительный или конечный символ. Каждая строка C#, называемая оператором, обязательно должна заканчиваться точкой с запятой, чтобы компилятор мог понять, где заканчивается одна команда
и начинается другая.
Однако есть одна особенность, о которой вам нужно знать. В отличие
от обычного письменного языка, с которым вы знакомы, оператор C#
не обязательно должен располагаться в одной строке. Пробелы и символы переноса строки компилятором игнорируются. Например, простую
переменную можно объявить так:
public int firstName = "Harrison";

а можно и так:
public
int
firstName
=
"Harrison";

Оба эти фрагмента кода одинаково приемлемы для Visual Studio,
но второй вариант крайне не одобряется сообществом разработчиков
программного обеспечения, поскольку такой код становится чрезвычайно трудным для чтения. Идея состоит в том, что писать программы
нужно как можно эффективнее и понятнее.
Бывают моменты, когда оператор получается слишком длинным и не умещается в одной строке, но это редкость. Но если
так произошло, то отформатируйте данный оператор таким
образом, чтобы и другие люди могли его понять, и не забудьте точку с запятой.

Второе правило форматирования, которое нужно записать у себя на
подкорке, — использование фигурных скобок. У всех методов, классов
и интерфейсов после их объявления должна идти пара фигурных скобок. Мы поговорим о каждом из этих элементов более подробно позже,

68  Глава 3



Погружение в переменные, типы и методы

но продумать стандартное форматирование нужно заблаговременно.
Традиционная практика в C# — писать каждую скобку на новой строке,
как показано ниже:
public void MethodName()
{
}

Однако, когда вы создаете в редакторе Unity новый сценарий или открываете документацию Unity, первая фигурная скобка оказывается
в той же строке, что и объявление:
public void MethodName() {
}

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

Отладка кода
Когда мы будем работать над практическими примерами, нам понадобится способ распечатать информацию и отзывы на панели консоли
в редакторе Unity. В программировании это называется отладкой,
и в C# и в Unity есть вспомогательные методы, упрощающие данный
процесс для разработчиков. Каждый раз, когда я попрошу вас отладить
или вывести что-либо на экран, используйте один из методов, которые
описаны ниже.
zzДля простого текста или отдельных переменных задействуйте стан-

дартный метод Debug.Log(). Текст должен быть заключен в кавычки,

Объявление переменных  69

а переменные можно использовать напрямую, без добавления символов. Например:
Debug.Log("Text goes here.");
Debug.Log(yourVariable);

zzДля

более сложной отладки используйте метод Debug.LogFormat().
Он позволяет размещать переменные внутри выводимого текста
через заполнители. Они отмечены парой фигурных скобок, каждая
из которых содержит индекс. Индекс — это обычное число, начинающееся с 0 и последовательно увеличивающееся на 1.

В следующем примере заполнитель {0} заменяется значением переменной variable1, {1} — значением variable2 и т. д.:
Debug.LogFormat("Text goes here, add {0} and {1} as variable
placeholders", variable1, variable2);

Вы могли заметить, что в наших методах отладки мы используем точечную нотацию, и это не случайность! Debug — класс, а Log() и LogFormat() —
методы из данного класса, которые мы можем задействовать. Подробнее
об этом — в конце главы.
Теперь, зная о возможностях отладки, мы можем смело двигаться дальше и глубже погрузиться в то, как объявляются переменные, а также
в различные способы использования синтаксиса.

Объявление переменных
В предыдущей главе мы посмотрели, как записываются переменные,
и коснулись высокоуровневого функционала, который они предоставляют. Однако нам все еще не хватает синтаксиса, который позволил бы
реализовать этот функционал. Переменные не просто появляются в верхней части сценария C#. Их нужно объявлять в соответствии с определенными правилами и требованиями. На самом базовом уровне оператор
переменной должен удовлетворять следующим требованиям:
zzнеобходимо указать тип данных, которые будет хранить переменная;
zzпеременная должна иметь уникальное имя;

70  Глава 3



Погружение в переменные, типы и методы

zzесли мы присваиваем переменной значение, то оно должно соответ-

ствовать указанному типу;
zzобъявление переменной должно заканчиваться точкой с запятой.

Совокупность этих правил дает следующий синтаксис:
dataType uniqueName = value;

Переменным нужны уникальные имена, чтобы избежать конфликтов со словами, уже используемыми в самом C#, которые
называются ключевыми. Вы можете найти полный список защищенных ключевых слов, пройдя по ссылке docs.microsoft.com/
ru-ru/dotnet/csharp/language-reference/keywords/.

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

Объявление типа и значения
Наиболее распространенный сценарий создания переменных — тот,
в котором вся необходимая информация указывается сразу при объявлении. Например, если бы мы знали возраст игрока, то написали бы
нечто такое:
int currentAge = 32;

В этой строке выполнены все основные требования:
zzуказан тип данных — int (сокращение от integer);
zzиспользуется уникальное имя currentAge;
zz32 — целое число, соответствующее указанному типу данных;
zzоператор заканчивается точкой с запятой.

Однако бывают случаи, в которых нужно объявить переменную, не зная
ее значениязаранее. Об этом мы поговорим в следующем подразделе.

Использование модификаторов доступа  71

Объявление типа без значения
Рассмотрим другой случай: вам известны тип данных, которые вы хотите хранить в переменной, и ее имя, а значение неизвестно. Оно будет
вычислено и присвоено где-нибудь еще, но вам все равно нужно объявить переменную в начале сценария.
Эта ситуация идеально подходит для вот такого объявления:
int currentAge;

Здесь определены только тип (int) и уникальное имя (currentAge),
и такой оператор тоже работает и соответствует правилам. Без присвоенного значения переменная получит значение по умолчанию, соответствующее типу переменной. В данном случае currentAge станет
равно 0, что соответствует типу int. Когда фактическое значение будет
известно, его можно легко установить в отдельном операторе, указав
имя переменной и присвоив ей значение:
currentAge = 32;

Полный список всех типов C# и их значений по умолчанию можно найти по адресу docs.microsoft.com/ru-ru/dotnet/
csharp/language-reference/builtin-types/default-values.

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

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

72  Глава 3



Погружение в переменные, типы и методы

Взгляните на переменные, которые мы использовали в предыдущей главе в сценарии LearningCurve, и вы увидите, что перед их объявлениями
добавлено дополнительное ключевое слово public. Это модификатор
доступа к переменной, то есть некий параметр безопасности, определяющий, кто и что может получить доступ к информации о переменной.
Любая переменная, не имеющая модификатора public, по
умолчанию получает модификатор private и не будет отображаться на панели Inspector в Unity.

Если мы добавим модификатор, то рецепт синтаксиса, который мы собрали в начале этой главы, будет выглядеть следующим образом:
accessModifier dataType uniqueName = value;

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

Выбор уровня безопасности
В C# есть четыре основных модификатора доступа, но вам, как новичкам, чаще всего предстоит работать с двумя из них:
zzpublic

— переменная доступна для любого сценария без ограни-

чений;
— переменная доступна только в классе, в котором создана
(он называется содержащим классом (containing class)).

zzprivate

Любая переменная без модификатора доступа по умолчанию является
частной.
Есть еще два более сложных модификатора:
— доступна из содержащего класса или производных от
него типов;

zzprotected

zzinternal — доступна только в текущей сборке.

Использование модификаторов доступа  73

Каждый из этих модификаторов предполагает свои варианты использования, но пока мы не дошли до более сложных глав, о модификаторах
protected и internal можно временно забыть.
Существует еще два комбинированных модификатора, но
в этой книге мы не будем их использовать. Подробнее о них
можно почитать, пройдя по ссылке docs.microsoft.com/ru-ru/
dotnet/csharp/language-reference/keywords/access-modifiers.

Теперь опробуем эти модификаторы доступа!

Время действовать. Делаем переменную частной
Как и в реальной жизни, одни данные необходимо защищать, а другие
можно передавать конкретным людям. Если в вашем проекте нет необходимости изменять переменную на панели Inspector или обращаться
к ней из других сценариев, то такой переменной можно задать модификатор private.
Подредактируем сценарий LearningCurve, выполнив следующие действия.
1. Измените модификатор доступа переменной currentAge с public на
private и сохраните файл.
2. Вернитесь в Unity, выберите объект Main Camera и посмотрите, что
изменилось в разделе LearningCurve.
Поскольку переменная currentAge теперь является частной, она больше не отображается на панели Inspector и доступна только в сценарии
LearningCurve (рис. 3.1). Если мы нажмем кнопку Play, то сценарий будет
работать точно так же, как и раньше.

Рис. 3.1

74  Глава 3



Погружение в переменные, типы и методы

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

Работа с типами
Присвоение переменной определенного типа — важный выбор, влия­
ющий в дальнейшем на каждое ее взаимодействие на протяжении всего
ее жизненного цикла. Поскольку C# — так называемый строго типизированный или типобезопасный язык, абсолютно каждая переменная
должна иметь определенный тип данных. Это значит, что существуют
четкие правила при выполнении операций с определенными типами,
а также правила преобразования одного типа переменной в другой.

Простые встроенные типы
Все типы данных в C# наследуются (или являются производными,
если говорить как программисты) от общего предка: System.Object.
Эта иерархия, называемая системой общих типов (Common Type
System, CTS), означает, что разные типы имеют много общих функций.
В табл. 3.1 представлены некоторые из наиболее распространенных
вариантов типов данных и хранимые ими значения.
Таблица 3.1

Тип

Содержимое переменной

Int

Целые числа, например 42

Float

Число с плавающей запятой, например 3,14

String

Набор символов в кавычках, например «абыр валг»

Bool

Логическое значение — true или false

Помимо указания на значения, которые может хранить переменная,
типы содержат дополнительную информацию о себе:
zzнеобходимое для хранения пространство;
zzминимальные и максимальные значения;

Работа с типами  75
zzдопустимые операции;
zzрасположение в памяти;
zzдоступные методы;
zzбазовый (производный) тип.

Если этот объем информации кажется вам слишком большим, то сделайте глубокий вдох. Работа со всеми типами, которые есть в C#, — прекрасный пример использования документации вместо запоминания.
Довольно скоро применение даже самых сложных пользовательских
типов станет для вас простым и родным.
Вы можете найти полный список всех встроенных типов C#
и их спецификации по адресу docs.microsoft.com/ru-ru/dotnet/
csharp/programming-guide/types/.

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

Время действовать. Экспериментируем
с типами
Откройте сценарий LearningCurve и добавьте в него новую переменную
каждого типа, которые мы перечислили выше. Имена и значения можете выбрать сами, но не забудьте добавить им модификатор public,
чтобы они появились на панели Inspector. Если вам нужно вдохновение,
то взгляните на мой код, который показан на рис. 3.2.
При работе со строковыми типами присваиваемое текстовое
значение должно находиться внутри пары двойных кавычек,
а значения с плавающей запятой должны заканчиваться
строчной буквой f — в примере это видно.

Теперь мы видим все использованные типы переменных. Обратите внимание на переменную типа bool, которая отображается в Unity в виде
флажка (если галочка есть — переменная получает значение true, если
нет, то false) (рис. 3.3).

76  Глава 3



Погружение в переменные, типы и методы

Рис. 3.2

Рис. 3.3

Работа с типами  77

Прежде чем мы перейдем к преобразованиям, рассмотрим распространенный и эффективный способ применения строкового типа данных —
а именно, создание строк, в которые включаются переменные.

Время действовать. Создаем интерполированные строки
Если числовые типы ведут себя так, как нас учили на уроках математики в начальной школе, то со строками дело обстоит иначе. Мы
можем вставлять переменные и литералы непосредственно в текст,
если начнем его с символа $, что называется строковой интерполяцией.
Интерполированные значения добавляются в фигурные скобки, как
при использовании метода LogFormat(). Создадим простую интерполированную строку в сценарии LearningCurve, чтобы попробовать это
в действии.
Выведите интерполированную строку внутри метода Start() сразу после вызова метода ComputeAge() (рис. 3.4).

Рис. 3.4

Благодаря фигурным скобкам значение переменной firstName выводится внутри интерполированной строки (рис. 3.5).

Рис. 3.5

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

78  Глава 3



Погружение в переменные, типы и методы

Преобразование типов
Мы уже видели, что переменные могут содержать только значения своих объявленных типов, но иногда приходится комбинировать переменные разных типов. В терминологии программирования они называются
преобразованиями и бывают двух основных видов.
zzНеявные преобразования происходят автоматически, обычно когда

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

zzЯвные преобразования необходимы в случаях, когда во время преоб-

разования существует риск потерять некую информацию. Например,
если бы мы хотели преобразовать переменную типа double в int, то
нам пришлось бы явно преобразовать ее, добавив целевой тип в круглых скобках перед значением, которое мы хотим преобразовать.
Так мы сообщаем компилятору, что знаем о предстоящей потере
данных (или точности).
В этом явном преобразовании число 3.14 будет округлено до 3, то есть
дробная часть отбрасывается:
int explicitConversion = (int)3.14;

В C# есть встроенные методы для явного преобразования
значений в простые типы. Например, любой тип можно
преобразовать в строковое значение с помощью метода
ToString(), а метод Convert может обрабатывать более сложные преобразования. Подробнее об этом можно почитать
в разделе Methods, пройдя по ссылке docs.microsoft.com/
ru-ru/dotnet/api/system.convert?view=netframework-4.7.2.

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

Работа с типами  79

Предполагаемые объявления
К счастью, C# может предположить тип переменной по присвоенному
ей значению. Например, ключевое слово var может сообщить программе, что тип переменной currentAge должен быть определен по присвоенному ей значению 32, которое является целым числом:
var currentAge = 32;

Иногда удобно так делать, но не поддавайтесь привычке
ленивого программирования использовать предполагаемые
объявления везде. Из-за этого в коде появится слишком
много неясности там, где он должен быть кристально ясным.

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

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

Итого про типы
Типы — сложная тема, и единственный способ освоить ее — использовать их. Однако следует помнить о некоторых важных вещах:
zzвсе

переменные должны быть определенного типа (будь он задан
явно или через предположение);

zzпеременные могут содержать только значения назначенного им типа

(в int нельзя «положить» текст);
zzу

каждого типа есть набор операций, которые он может и не может
выполнять (bool нельзя вычесть из другого значения);

80  Глава 3



Погружение в переменные, типы и методы

zzесли

переменную объединить с переменной другого типа или присвоить значение другого типа, то необходимо выполнить преобразование (неявное или явное);

zzкомпилятор

C# может определить тип переменной по ее значению
с помощью ключевого слова var, но этот метод следует использовать
только в том случае, если тип заранее не известен.

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

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

Практические рекомендации
Первое правило именования переменных: выбираемое имя должно
иметь смысл. Второе правило — используйте верблюжий регистр
(camel case). Возьмем общий пример из игр и объявим переменную,
в которой будет храниться здоровье игрока:
public int health = 100;

Вскоре после объявления такой переменной вам начнут поступать тревожные звонки от внутреннего голоса. Чье здоровье имеется в виду?
Это максимальное или минимальное значение? На какой код повлияет
изменение этого значения? На все эти вопросы легко ответить, выбрав
осмысленное имя переменной. И нужно так и делать, если вы не хотите,
чтобы ваш код запутал вас через неделю или месяц.

Понятие области видимости переменных  81

С учетом сказанного попробуем улучшить этот код, добавив заодно
верблюжий регистр:
public int maxHealth = 100;

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

Уже лучше. Немного подумав, мы обновили имя переменной с учетом
ее смысла и контекста. Поскольку технических ограничений на длину
имени переменной нет, вы можете переборщить и начать писать длинные описательные имена, но это будет так же плохо, как и короткое,
неописательное имя.
Лучше всего делать имя переменной настолько информативным, насколько оно должно быть, — ни больше, ни меньше. Найдите свой стиль
и придерживайтесь его.

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

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

82  Глава 3



Погружение в переменные, типы и методы

zzОбласть

видимости class или member выбирается для переменных,
доступных в любом месте содержащего класса.

zzОбласть

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

Взгляните на рис. 3.6. Вам не нужно писать данный код в сценарий
LearningCurve, если не хочется. Это всего лишь пример.

Рис. 3.6

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

Более подробно поговорим об областях видимости переменных, показанных на рис. 3.6.
zzПеременная characterClass

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

zzПеременная characterHealth объявляется внутри метода Start(); это

значит, что она видна только внутри данного блока кода. Мы легко

Знакомство с операторами  83

можем получить доступ к characterClass из метода Start(), но если
попытаемся получить доступ к characterHealth из другого места, то
получим ошибку.
zzПеременная characterName

находится в тех же условиях, что и cha­
rac­t erHealth , и доступ к ней можно получить только из метода
CreateCharacter(). Таким образом, я показал, что в одном классе
может быть несколько локальных областей (даже вложенных).

Проведя достаточно времени с программистами, вы наверняка услышите дискуссии (или споры, в зависимости от времени суток) о том, где
лучше всего объявить переменную. Ответ проще, чем вы думаете: переменные следует объявлять с учетом их использования. Если у вас есть
переменная, к которой нужно обращаться во всем классе, то сделайте
ее переменной класса. Если она нужна только в определенном разделе
кода, то объявите ее как локальную.
Обратите внимание: в окне Inspector можно просматривать
только переменные класса, что не подходит для локальных
или глобальных переменных.

Теперь, зная все об именах и областях видимости, вернемся за парту
средней школы и заново узнаем, как работают арифметические операции!

Знакомство с операторами
Символы операторов в языках программирования выполняют арифме­
тические, присваивающие, реляционные и логические функции, которые
могут выполнять разные типы. Арифметические операторы представляют собой основные математические функции, а операторы присваивания одновременно выполняют математические функции и функции присваивания с заданным значением. Реляционные и логические
операторы оценивают некое условие между несколькими значениями,
например, «больше», «меньше» или «равно».
В C# также есть побитовые и прочие операторы, но они вам
не пригодятся, пока вы не начнете создавать более сложные
приложения.

84  Глава 3



Погружение в переменные, типы и методы

На данный момент нам есть смысл рассматривать только арифметические операции и операторы присваивания, но мы перейдем к реляционным и логическим операциям в следующей главе, когда они потребуются.

Арифметика и присваивание
Вы с малых лет знакомы с символами арифметических операторов:
zz+ — сложение;
zz– — вычитание;
zz/ — деление;
zz* — умножение.

Операторы C# выполняются по обычному приоритету операций,
то есть сначала вычисляется то, что в скобках, затем степени, умножение, деление, сложение и, наконец, вычитание1. Например, следующие
равенства дадут разные результаты, несмотря на то что содержат одинаковые значения и операторы2:
5 + 4 - 3 / 2 * 1 = 8
5 + (4 - 3) / 2 * 1 = 5

В случае применения к переменным операторы работают так
же, как и с чистыми значениями.

Операторы присваивания можно задействовать как сокращенную
замену любой математической операции, используя символ арифметической операции и символ равенства вместе. Например, если бы мы
1

Надо отметить, что в C# нет возведения в степень. Кроме того, автор в оригинале
приводит аббревиатуру BEDMAS (Brackets, Exponents, Divide, Multiply, Add,
Subtract), а потом в списке приоритетов приводит умножение раньше деления.
Умножение и деление, как и сложение с вычитанием, являются операторами одного
приоритета и выполняются по порядку слева направо. — Примеч. науч. ред.

2

Тонкий момент: в обычной арифметике приведенные ниже выражения равны 7,5 и 5,5
соот­ветственно, однако из-за того, что все операнды — целые числа, которые нигде
явно не приведены к числам с плавающей точкой, используется целочисленная
арифметика, в которой итоговое значение округляется по правилам коммерческого
округления. — Примеч. науч. ред.

Знакомство с операторами  85

хотели умножить переменную на число, то оба следующих варианта
дали бы один и тот же результат:
int currentAge = 32;
currentAge = currentAge * 2;

И второй вариант:
int currentAge = 32;
currentAge *= 2;

Символ равенства в С# также считается оператором присваивания. Другие символы присваивания следуют тому же
синта­ксическому шаблону, что и в предыдущем примере: +=,
–= и /= выполняют сложение, вычитание, деление, а затем
присваивание.

У строк операторы работают по-своему. Например, символ сложения
у строк выполняет склейку:
string fullName = "Joe" + "Smith";

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

Теперь мы узнали, что у типов есть правила, которые определяют,
какие операции и взаимодействия они могут иметь. Однако мы еще
не попробовали это на практике и потому сделаем это прямо сейчас.

Время действовать. Выполняем операции
на неправильных типах
Проведем небольшой эксперимент: попробуем перемножить строку
и число с плавающей запятой, как делали ранее с числами (рис. 3.7).
Если вы посмотрите в окно консоли, то увидите сообщение об ошибке,
которое гласит, что нельзя перемножать строку и число с плавающей
запятой (рис. 3.8). Каждый раз, когда встречается подобная ошибка,
необходимо проверить типы переменных на совместимость.

86  Глава 3



Погружение в переменные, типы и методы

Рис. 3.7

Рис. 3.8

Обязательно нужно убрать этот пример, поскольку компилятор не позволит нам запустить игру с такой ошибкой. Закомментируйте данную
строку двумя чертами или просто удалите ее.
На данный момент это все, что нам нужно знать о переменных и типах.
Обязательно проверьте себя, ответив на вопросы в конце главы, прежде
чем двигаться дальше!

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

Определение методов  87

Базовый синтаксис
Как и в случае с переменными, к объявлениям методов предъявляются
следующие основные требования:
zzтип данных, возвращаемый методом;
zzуникальное имя (обычно начинается с заглавной буквы);
zzпара скобок после имени метода;
zzпара

фигурных скобок, обозначающая тело метода (где хранятся
инструкции).

Собирая все эти правила воедино, мы получаем простой шаблон
метода:
returnType UniqueName()
{
method body
}

В качестве практического примера разберем метод Start() из сценария
LearningCurve (рис. 3.9).

Рис. 3.9

Что здесь есть:
zzметод начинается с ключевого слова void, которое задает возвраща-

емый тип метода, если он не возвращает никаких данных;
zzу метода уникальное имя;
zzпосле

имени метода есть пара круглых скобок для возможных аргументов;

zzтело метода ограничено набором фигурных скобок.

88  Глава 3



Погружение в переменные, типы и методы

В общем, если у вас есть метод с пустым телом, то рекомендуется удалить его из класса. От неиспользуемого кода
всегда стоит избавляться.

Как и у переменных, у методов есть уровни безопасности. А еще они
могут иметь входные параметры, которые мы обсудим далее.

Модификаторы и параметры
У методов могут быть те же четыре модификатора доступа, что и у переменных, а также входные параметры. Параметры — это переменныезаполнители, которые могут передаваться в методы и быть доступными внутри них. Количество входных параметров, которые вы можете
использовать, не ограничено, но каждый из них должен быть отделен
запятой, для каждого указывается тип данных и уникальное имя.
Аргументы — это заполнители для переменных, значения
которых можно использовать внутри тела метода.

Если мы применим эти параметры, то наш обновленный шаблон будет
выглядеть так:
accessModifier returnType UniqueName(parameterType parameterName)
{
method body
}

Если явного модификатора доступа нет, то по умолчанию используется private. Частный метод, как и частная переменная,
не может быть вызван из других сценариев.

Чтобы вызвать метод (то есть запустить или выполнить его инструкции), мы просто используем его имя, за которым следует пара
круглых скобок, с параметрами или без них и в конце ставим точку
с запятой:
// Без параметров
UniqueName();
// С параметрами
UniqueName(parameterVariable);

Определение методов  89

Как и у переменных, каждый метод располагает информацией о его уровне доступа, типе возвращаемого значения
и аргументах. Это называется сигнатурой метода. По сути,
сигнатура помечает метод как уникальный для компилятора,
поэтому Visual Studio знает, что с ним делать.

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

Время действовать. Определяем простой метод
Ранее, в предыдущей главе, вы слепо переписали метод AddNumbers
в сценарий LearningCurve, не зная, во что ввязываетесь. На этот раз
создадим метод осмысленно.
zzОбъявите метод с возвращаемым типом void и именем GenerateCha­

racter() как public.
zzДобавьте оператор Debug.Log(), который выводит имя персонажа из

вашей любимой игры или фильма.
zzВызовите

метод GenerateCharacter() внутри метода Start() и нажмите кнопку Play (рис. 3.10).

Рис. 3.10

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

90  Глава 3



Погружение в переменные, типы и методы

Правильное именование — неотъемлемая часть программирования, поэтому неудивительно, что нам нужно посмотреть соглашения об именах
для методов, прежде чем двигаться дальше.

Соглашения об именах
Подобно переменным, методам нужны уникальные и осмысленные
имена, которые позволят различать их в коде. Методы определяют
действия, поэтому рекомендуется называть их как действия. Например,
метод GenerateCharacter() назван хорошо и понятно, а имя Summary()
чересчур расплывчатое и не дает очень четкой картины того, что будет
выполнять метод.
Названия методов всегда начинаются с заглавной буквы, и затем с заглавной буквы начинаются все последующие слова. Этот стиль называется Pascal Case (сводный брат формата Camel Case, который мы
используем для переменных).

Методы — что-то вроде объездных дорог
Мы видели, что строки кода выполняются последовательно в том порядке, в котором они написаны, но использование методов сбивает
эту последовательность. Вызов метода заставляет программу сначала
выполнить по порядку его инструкции, а затем возобновить последовательное выполнение с того места, где был вызван метод.
Взгляните на рис. 3.11 и посмотрите, сможете ли понять, в каком порядке в консоль выведутся сообщения.

Рис. 3.11

Определение параметров  91

Порядок выполнения выглядит так.
1. Сообщение Choose a Character выводится первым, поскольку это
первая строка кода.
2. Когда вызывается метод GenerateCharacter(), программа переходит
к строке 23, выводит сообщение Character: Spike, а затем возобновляет выполнение со строки 17.
3. Сообщение A fine choice выводится последним, когда метод Gene­
rateCharacter() завершит работу (рис. 3.12).

Рис. 3.12

Сами по себе методы были бы не очень полезными, кроме таких простых примеров, если бы мы не могли передавать им значения аргументов, что мы и сделаем.

Определение параметров
Вероятно, ваши методы не всегда будут такими же простыми, как
GenerateCharacter(). Чтобы передать методу дополнительную информацию, следует определить список параметров, которые он будет принимать и использовать в работе. При определении параметра нужно
задать две вещи:
zzявный тип;
zzуникальное имя.

92  Глава 3



Погружение в переменные, типы и методы

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

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

передаваемый в метод, должен соответствовать типу параметра, как переменная и ее значение;

zzаргументы могут быть просто значениями (например, числом 2) или

переменными, объявленными в другом месте класса.
Имена аргументов и имена параметров не обязательно должны совпадать.

Теперь продолжим и добавим методу GenerateCharacter() параметры,
чтобы код стал более интересным.

Время действовать. Добавляем параметры методу
Обновим метод GenerateCharacter(), чтобы он мог принимать два параметра.
1. Добавим два параметра: один — это имя персонажа строкового типа,
а другой — уровень персонажа типа int.
2. В метод Debug.Log() добавим новые параметры.
3. Дополните вызов метода GenerateCharacter() в методе Start() своими аргументами, которые могут быть либо буквальными значениями,
либо объявленными переменными (рис. 3.13).

Определение возвращаемых значений  93

Здесь мы определили два параметра, name(string) и level (int), и задействовали их внутри метода GenerateCharacter(), словно это локальные
переменные. Вызывая данный метод внутри Start(), мы указали значения аргументов для каждого параметра с соответствующими типами.
На рис. 3.13 видно, что применение буквального строкового значения
в кавычках дает тот же результат, что и использование переменной
characterLevel (рис. 3.14).

Рис. 3.13

Рис. 3.14

Двигаемся дальше и узнаем, как передавать значения в метод и из
него. Это подводит нас к следующему разделу — о возвращаемых
значениях.

Определение возвращаемых значений
Помимо приема параметров, методы могут возвращать значения любого имеющегося в C# типа. Во всех наших предыдущих примерах
использовался тип void , который ничего не возвращает, но главное

94  Глава 3



Погружение в переменные, типы и методы

преимущество методов — это возможность выполнять вычисления
и возвращать обратно вычисленные результаты.
Согласно шаблону возвращаемые типы методов указываются после модификатора доступа. Помимо типа, метод должен содержать ключевое
слово return, за которым следует возвращаемое значение. Оно может
быть переменной, буквальным значением или даже выражением, если
соответствует объявленному возвращаемому типу.
Методы, у которых тип возвращаемого значения задан как
void, по-прежнему позволяют использовать ключевое слово
return без присвоенного значения или выражения. Как только
будет достигнута строка с ключевым словом return, метод
прекратит выполнение. Это полезно в тех случаях, когда вы
хотите избежать определенного поведения или защититься
от сбоев программы.

Добавим тип возвращаемого значения в GenerateCharacter() и узнаем,
как записать его в переменную.

Время действовать. Добавляем возвращаемый тип
Научим метод GenerateCharacter возвращать целое число.
1. Заменим тип возвращаемого значения в объявлении метода с void
на int.
2. Вернем значение, увеличенное на +5, используя ключевое слово
return (рис. 3.15).

Рис. 3.15

Теперь метод GenerateCharacter() возвращает целое число. Оно вычисляется путем прибавления 5 к аргументу level. Но мы пока не указали,

Определение возвращаемых значений  95

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

Использование возвращаемых значений
В этом вопросе есть два подхода.
zzСоздать

локальную переменную для захвата (хранения) возвращаемого значения.

zzЗадействовать

сам вызывающий метод как замену возвращаемому
значению, используя его как переменную. Вызывающий метод —
это фактическая строка кода, запускающая инструкции, которыми
в нашем примере будет GenerateCharacter("Spike", characterLevel).
При необходимости даже можно передать вызывающий метод другому методу в качестве аргумента.
В большинстве случаев программисты предпочитают первый
вариант из-за его удобочитаемости. Указание вызовов методов в качестве переменных может породить беспорядок
в коде, особенно когда мы используем одни методы в качестве аргументов в других методах.

Попробуем в коде захватить и вывести возвращаемое значение метода
Genera­teCharacter().

Время действовать. Захватываем
возвращаемые значения
Мы собираемся опробовать оба способа захвата и использования возвращаемых переменных.
1. Создадим новую локальную переменную типа int с именем next­
SkillLe­v el и присвоим ей возвращаемое значение вызова метода
GenerateCharacter(), который у нас уже есть.

96  Глава 3



Погружение в переменные, типы и методы

2. Добавим два оператора вывода, первый из которых выводит next­
SkillLevel, а второй — новый вызывающий метод со значениями
аргументов по вашему выбору.
3. Закомментируйте вывод внутри GenerateCharacter() двумя косыми
чертами (//), чтобы в консоли не было нагромождений.
4. Сохраните файл и нажмите кнопку Play в Unity (рис. 3.16).

Рис. 3.16

Для компилятора переменная nextSkillLevel и вызывающий метод Genera­t eCharacter() представляют одну и ту же информацию,
а именно целое число, поэтому в обоих выводах появляется число 37
(рис. 3.17).

Рис. 3.17

Мы обсудили много всего, особенно учитывая огромные возможности
методов при работе с параметрами и возвращаемыми значениями.
Однако здесь мы на минуту притормозим и рассмотрим некото-

Анализ распространенных методов Unity   97

рые из наиболее распространенных методов Unity, чтобы немного
передохнуть.
Испытание героя. Рассматриваем
методы как аргументы
Если не боитесь, то почему бы не попробовать создать новый метод,
который принимает параметр типа int и просто выводит его в консоль? Возвращаемый тип не требуется. Создав этот метод, вызовите
его в Start(), передайте вызов метода GenerateCharacter в качестве
аргумента и посмотрите на результат.

Анализ распространенных
методов Unity
Теперь мы можем обсудить наиболее распространенные встроенные методы, появляющиеся в новых сценариях C# в Unity: Start()
и Update(). В отличие от методов, которые мы определяем сами, методы, принадлежащие классу MonoBehaviour, автоматически вызываются
движком Unity по особым правилам. В большинстве случаев важно
иметь в сценарии хотя бы один метод MonoBehaviour для запуска вашего
кода.
Вы можете найти полный список всех доступных методов Mo­
noBehaviour и их описания, пройдя по ссылке docs.unity3d.com/
ScriptReference/MonoBehaviour.html.

Рассказывая историю, всегда лучше начинать с самого начала. Так
и здесь — начнем с встроенного в Unity метода Start().

Метод Start()
Unity вызывает этот метод в первом кадре, в котором включается
сценарий. Поскольку сценарии MonoBehaviour почти всегда прикреплены к объектам GameObject на сцене, прикрепленные к ним сценарии

98  Глава 3



Погружение в переменные, типы и методы

включаются одновременно с их загрузкой при нажатии кнопки Play.
В нашем проекте сценарий LearningCurve присоединен к объекту Main
Camera; это значит, что его метод Start() запускается, когда камера загружается в сцену. Метод Start() в основном используется для установки переменных или выполнения логики, которая должна произойти
перед первым запуском метода Update().
Все примеры, которые мы рассматривали до сих пор, работали в методе Start(), даже если не выполняли действия по настройке, но обычно так не делается. Однако он срабатывает
только один раз, что делает его отличным инструментом для
вывода одноразовой информации в консоли.

Помимо метода Start(), есть еще один важный метод Unity, с которым
вам придется работать постоянно: метод Update(). Вы познакомитесь
с ним в следующем подразделе, а затем мы закончим эту главу.

Метод Update()
Если вы изучите пример кода, пройдя по ссылке docs.unity3d.com/ScriptRe­
ference/, то заметите, что большая часть кода выполняется в методе
Update() . Во время работы игры окно сцены отрисовывается много
раз в секунду. Количество отрисовок определяется параметром FPS —
Frames Per Second, или количество кадров в секунду. После отображения каждого кадра вызывается метод Update(), вследствие чего он
становится одним из наиболее часто выполняемых методов в игре. Это
делает его идеальным для перехвата ввода с помощью мыши и клавиатуры или выполнения логики игрового процесса.
Если вам интересно узнать FPS на вашем компьютере, то нажмите
кнопку Play и кнопку Stats в правом верхнем углу окна Game (рис. 3.18).
Вы будете использовать методы Start() и Update() в большей части
ваших сценариев C#, поэтому ознакомьтесь с ними. Мы подошли
к концу данной главы, располагая полным набором знаний об основных
элементах программирования.

Подведем итоги  99

Рис. 3.18

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

100  Глава 3



Погружение в переменные, типы и методы

Контрольные вопросы. Переменные
и методы
1. Как правильно задавать имя переменной на C#?
2. Как сделать так, чтобы переменная появилась на панели Inspector
в Unity?
3. Какие четыре модификатора доступа есть в C#?
4. Когда нужны явные преобразования между типами?
5. Что нужно для определения метода?
6. Для чего нужны круглые скобки в конце имени метода?
7. Что означает возвращаемый тип void в определении метода?
8. Как часто Unity вызывает метод Update()?

4

Поток управления
и типы коллекций

Одна из главных задач компьютера — следить за тем, что происходит
при каких-то заранее известных условиях. Щелкая на папке, вы ожидаете, что она откроется. Печатая на клавиатуре, вы ожидаете, что на
экране будет появляться соответствующий текст.
Написание кода для приложений или игр концептуально такое же.
Ваше приложение должно в определенном состоянии вести себя
определенным образом, а при изменении условий менять поведение.
В терминах программирования это называется потоком управления
или, другими словами, потоком выполнения кода в различных сценариях.
Помимо работы с управляющими операторами, в текущей главе мы
на практике рассмотрим типы данных под названием «коллекции».
Это такие типы данных, которые позволяют хранить несколько значений или группы значений в одной переменной. Они часто применяются совместно с часто встречающимися сценариями потока
управления.
В свете вышесказанного мы обсудим такие темы, как:
zzоператоры выбора;
zzработа с коллекциями типа Array, Dictonary и List;
zzоператоры итерации: циклы for, foreach и while;
zzуправление выполнением с помощью ключевых слов break, continue

и return;
zzкак не допустить появления бесконечных циклов.

102  Глава 4



Поток управления и типы коллекций

Операторы выбора
Самые сложные задачи программирования часто можно свести к некое­
му набору вариантов действий, которые оценивает и выполняет игра
или программа. Поскольку Visual Studio и Unity не могут выбрать за
вас, вы должны сами прописать логику принятия решения.
Операторы выбора if-else и switch позволяют задать разветвление
программы на основе одного или нескольких условий, а также действия, которые вы хотите предпринять в каждом из описанных случаев.
Обычно эти условия берутся из:
zzввода со стороны пользователя;
zzоценки выражений и логики;
zzсравнения переменных или значений.

Мы начнем с простейшего из этих условных операторов: if-else.

Оператор if-else
Оператор if-else — наиболее распространенный способ принятия
решений в коде. Если не брать пока синтаксис, основная идея состоит
в следующем: если некое условие выполнено, то мы должны выполнить
один блок кода, а если нет, то другой. Данный оператор сродни множеству дверей, а условие — это ключ от одной из них. Чтобы пройти, ключ
должен подходить к замку. В противном случае во входе будет отказано
и код будет пробовать другие «двери». Посмотрим, как выглядит синтаксис этого оператора.

Базовый синтаксис
Чтобы записать оператор if-else, нам потребуется:
zzключевое слово if в начале строки;
zzпара круглых скобок, куда мы запишем условие;
zzтело условия:
if (условие истинно)
Выполнить эту строку кода

Операторы выбора  103

Однако если тело оператора состоит более чем из одной строки, то
потребуется также пара фигурных скобок, в которых можно будет записать больший блок кода:
if (условие истинно)
{
Выполнить эти строки
кода
}

При желании мы можем добавить оператор else, чтобыперечислить
действия, которые должны произойти, если условие окажется ложным.
Оформление будет таким же:
else

Выполнить эту строку кода

// ИЛИ
else
{
}

Выполнить эти строки
кода

Если собрать все воедино, то синтаксис оператора будет читаться почти
как предложение:
if(условие истинно)
{
Выполнить эти строки
кода
}
else
{
Выполнить эти строки
кода
}

Данный оператор дает отличный повод потренировать логическое
мышление, по крайней мере в программировании, поэтому разберем
три различных варианта if-else более подробно.
1. Единственный оператор if может существовать сам по себе в тех
случаях, когда вас не волнует, что произойдет при невыполнении
условия. В следующем примере, если переменная hasDungeonKey имеет значение true, будет выведено сообщение, а если false, то ничего
не произойдет (рис. 4.1).

104  Глава 4



Поток управления и типы коллекций

Рис. 4.1

Если условие «выполнено», то имеется в виду, что его результат равен true, поэтому иногда такое условие еще называют «пройденным».

2. Оператор else мы добавляем в случаях, когда необходимо выполнить что-то и в случае истинности, и в случае ложности условия.
Если переменная hasDungeonKey окажется ложной, то оператор if
пропустит свое тело и передаст выполнение кода оператору else
(рис. 4.2).

Рис. 4.2

Операторы выбора  105

3. Если нужно рассмотреть несколько возможных вариантов, то
можно добавить оператор else-if с такими же круглыми скобками,
условиями и фигурными скобками. Лучше покажу сразу на примере.
Имейте в виду, что только оператор if может использоваться
сам по себе, в отличие от остальных рассмотренных нами
операторов.
Вы можете создавать и более сложные условия с помощью
основных математических операций, таких как > (больше),
< (меньше), >= (больше или равно), 3) вернет false и не пройдет, а условие
(2