Дизайн, как можно себе представить, это тема искусства и художественный способ создания объектов. Не только в компьютерной сфере, но и в реальной жизни.
Тем не менее, я попытаюсь обобщить основные и наиболее важные концепции разработки игрового дизайна. Несмотря на то, что моя тема называется «Дизайн игр и геймификация», в первую очередь я хочу поговорить о концепциях программирования игр. Узнайте больше о дополнительной информации, есть книга, которую я определенно рекомендую, книга Роберта Нистрома «Шаблоны игрового программирования».
Итак, давайте начнем!
- Шаблон команды. Узнайте, как легко переназначить клавиши, как отменить старые движения и как сделать классную функцию воспроизведения.
- Шаблон наилегчайшего веса. Узнайте, как сэкономить память, повторно используя общие объекты.
- Шаблон наблюдателя. Узнайте, как заставить ящики прослушивать события, прежде чем они прыгнут.
- Прототип. Основная идея этого шаблона заключается в том, что объект может порождать другие объекты, похожие на него самого. Но вывод автора книги таков, что вам это на самом деле не нужно: «Честно говоря, я не могу сказать, что нашел случай, когда я чувствовал, что шаблон проектирования Prototype был лучшим ответом». Поэтому я не буду освещать это здесь.
- Одиночка. С шаблоном проектирования singleton вы сможете просто создать один экземпляр класса. Но вывод из книги таков, что этот паттерн обычно приносит больше вреда, чем пользы, поэтому его следует использовать с осторожностью. Я еще не придумал хороший пример игрового приложения для шаблона, поэтому не буду его здесь описывать. Если вам нужен пример одноэлементного класса C#, в Google есть несколько.
- Шаблон состояния. Узнайте, как сделать простой клон Minecraft, в котором на вас нападают криперы и скелеты.
- Двойной буфер. Согласно Википедии, множественная буферизация — это использование более чем одного буфера для хранения блока данных, так что читатель увидит полную (хотя, возможно, и старую) версию данных, а не частично обновленную версию данные создаются писателем.
Если вы хотите увидеть это в действии, вам следует обратиться к моему руководству по водяным следам. Там я использую 2 массива, где я вычисляю новые высоты всех точек в сетке, глядя на окружающие высоты. Я не могу добавить результат вычислений одной точки в тот же массив, потому что это повлияет на вычисления других высот, потому что они должны использовать старые окружающие высоты. Поэтому я сохраняю высоту в новом массиве, а затем переворачиваю массивы, когда закончу. - Игровой цикл. В Unity встроен собственный игровой цикл, и мы не можем написать свой собственный. Но вам следует прочитать главу книги, чтобы лучше понять, как на самом деле работает Unity, например, почему Time.deltaTime не является константой.
- Метод обновления. Этот шаблон проектирования представляет собой метод Unity Update(). Идея состоит в том, что в игровом мире есть набор объектов, поведение которых должно обновляться в каждом кадре. Каждый из этих объектов должен иметь метод обновления, и каждый кадр игры обновляет каждый объект в коллекции.
- Байт-код. Самый сложный узор в книге. Вы разрабатываете свой собственный язык программирования под названием байт-код. Это особенно полезно, если вы хотите, чтобы ваши пользователи модифицировали игру, потому что байт-код не может случайно добраться до странных частей игрового движка, и он контролирует, сколько памяти он использует.
- Песочница подкласса. Узнайте, как легко управлять всеми суперспособностями в игре.
- Введите объект. Допустим, у вас есть базовый класс монстров и несколько разных монстров, унаследованных от этого базового класса. Основная идея шаблона типа объекта состоит в том, чтобы дать базовому классу монстра тип монстра (или породу, как в книге), вместо того, чтобы иметь несколько монстров, наследуемых от базового класса. Таким образом, у вас будет просто два класса: монстр и порода, а не монстр, дракон, тролль и т. д. Таким образом, каждый монстр в игре является экземпляром класса монстр, а класс породы содержит информацию, разделяемую между всеми монстрами одного и того же класса. порода, такая как порода дракона.
Будет намного проще создать новый объект породы, чем создавать еще один подкласс. А если у вас разные типы драконов, то тип дракона может наследоваться от более общего типа дракона. Этот шаблон дизайна чрезвычайно полезен, если вы позволяете своим пользователям загружать новые породы монстров. Но недостатком является то, что сложнее специализировать разные типы поведения монстров. - Компонент. Идея этого шаблона заключается в том, что в Unity есть разные компоненты, которые можно прикрепить к игровому объекту. Вы можете добавить компонент звука, компонент твердого тела и/или компонент системы частиц. Что, если бы все они были частью одного и того же класса? Теперь вы можете изменять каждый из компонентов по отдельности, не задумываясь об остальных компонентах. Компоненты по-прежнему могут общаться друг с другом.
- Очередь событий. Этот шаблон проектирования похож на шаблон Observer и используется для высокоуровневой связи между игровыми системами, которые хотят оставаться несвязанными. Очередь событий в основном представляет собой список. Когда событие произошло (например, нажатие клавиши), вы добавляете событие в список, а затем другая часть игры выбирает самые старые события из очереди и обрабатывает их.
Этот шаблон действительно полезен, если вы делаете учебник. Вы хотите избежать смешивания обучающего кода с другим игровым кодом. Таким образом, код игры может отправлять события в очередь событий, а затем код учебника выбирает события из очереди. Вы также можете использовать его для воспроизведения звуковых эффектов, объединяя звуковые эффекты перед добавлением их в список, если они одинаковы (и затем воспроизводить только самые громкие). Причина в том, что мы не можем воспроизводить несколько одинаковых звуковых эффектов одновременно. Когда звуковые эффекты имеют одинаковую форму волны, это то же самое, что один звуковой эффект воспроизводится в два раза громче. - Поиск сервисов. Служба может быть чем-то таким простым, как генератор случайных чисел. Это система, которая должна быть доступна для всей игры. Таким образом, вы можете сказать, что шаблон Service Locator похож на шаблон Singleton. Можно также сказать, что Service Locator похож на телефонную книгу, в которой мы можем найти и имя, и адрес. Но используйте этот шаблон только в случае необходимости, потому что создание чего-то глобального всегда навлекает на себя неприятности. Unity использует этот шаблон вместе с шаблоном Component в методе GetComponent().
- Местность данных. Здесь вам нужно знать, что память медленная, а процессоры быстрые. Чтобы попытаться компенсировать это, ЦП хранит немного памяти самостоятельно, что называется кэшированием ЦП. Это намного быстрее, чем доступ к другой памяти, поэтому вам нужно оптимизировать этот небольшой участок памяти. Вы измеряете эти улучшения, измеряя «промах кеша». Чтобы оптимизировать промах chache, вы должны организовать свои структуры данных так, чтобы вещи, которые вы обрабатываете, находились рядом друг с другом в памяти. Это легче сказать, чем сделать, но, согласно книге, следует избегать ненужных указателей, не отправлять деактивированные игровые объекты или другие ненужные данные в кеш и избегать создания подклассов.
- Грязный флаг. Допустим, у вас есть игровой объект с определенной позицией и вращением. У этого игрового объекта также есть дочерний игровой объект со своей позицией и вращением. Если родительский игровой объект движется, то мы должны пересчитывать позицию дочернего элемента (это затратно с точки зрения производительности), в противном случае мы этого не делаем. Чтобы определить, нужно ли пересчитывать положение и поворот дочернего элемента, мы устанавливаем логическое значение с именем Dirty Flag, если родитель сдвинулся. Если родитель не двигался, мы просто используем старую позицию и поворот. Другой пример: вы позволяете своим игрокам что-то построить, а затем загружаете сборку на сервер. Затем вы можете установить Dirty Flags на то, что действительно изменилось, и загружать только изменения.
- Пул объектов. Если у вас есть оружие, стреляющее пулями, то вам следует повторно использовать пули, а не уничтожать их и создавать новые. Поэтому, когда пуля попадает в цель (или покидает экран), вы деактивируете пулю. Когда вы затем стреляете новой пулей, вы активируете старую пулю, перемещаете ее в положение пистолета и придаете ей скорость. Это улучшит производительность и память игры. Этот паттерн уже охвачен самими Unity: Object Pooling.
- Пространственный раздел. Изучите быстрый способ найти ближайшего врага на поле боя.
Я собираюсь сделать эту тему как частичное представление моих действий и творений.