Создание Minecraft на Unity3D. Часть вторая. Генерация мира

mcunity1

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

Добавляем функциональность мыши

Прежде чем мы приступим к программированию, давайте добавим на нашу сцену направленный свет. Нам нужен источник света, чтобы лучше видеть наш 3D-мир.

35_light

Да будет свет!

Вы можете поменять направление света, если хотите:

scene-light2

Позиционируем источник света

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

33_newscript

Добавляем в проект C#-скрипт

Мы назовем их WorldGenerator и ClickOnFaceScript.

34_scripts

Используемые скрипты

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

Теперь откройте WorldGenerator.cs в MonoDevelop (которая уже установлена вместе с Unity) двойным щелчком по нему и введите следующий код:

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

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

Откройте ClickOnFaceScript.cs и введите туда этот код:

Теперь переместите скрипт на каждую из шести сторон куба на сцене.

36_dragscript2

Применяем скрипт к GameObject

Скрипт должен появиться на каждой стороне во вкладке Inspector.

37_inspector_script1

Компонент скрипта

Давайте запустим игру. Нажмите 38_play и проверьте, что отладочные сообщения появляются, когда вы кликаете по кубу во вкладке Game.

39_test

Тестируем нажатия кнопок мыши

Запомните! В режиме игры любые изменения, которые вы произвели с элементами во вкладке Scene, будут отменены. Не меняйте ничего, пока игра запущена. Нажмите 38_play еще раз, чтобы остановить игру.

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

Для простоты мы назовем центр куба, по которому кликают, буквой C, а центр блока, который должен появиться — N. Мы рассматриваем эти центры как позиции в 3D-пространстве.

  • Если мы кликаем на верхнюю грань: N = C + (0, 1, 0);
  • На нижнюю: N = C + (0, -1, 0);
  • На правую: N = C + (1, 0, 0);
  • На левую: N = C + (-1, 0, 0);
  • На переднюю: N = C + (0, 0, 1);
  • На заднюю: N = C + (0, 0, -1).

Мы можем обобщить сказанное выше в простую формулу: N = C + delta, где delta — это смещение, требуемое для расчета центра нового блока. Каждая из шести сторон содержит свой экземпляр ClickOnFaceScript и разное значение delta.

Мы должны изменить ClickOnFaceScript.cs, чтобы реализовать функционал, описанный выше. Откройте скрипт и измените файл таким образом:

Вернитесь в редактор и поменяйте значения delta в соответствии с картинками:

40_values

Вся необходимая информация обведена

Проверьте, что все работает. Запустите игру несколько раз, задавая разные позиции камере (изменяя ее Transform во вкладке Inspector), чтобы проверить, что введенные нами значения delta верны.

41_tempcam

Настраиваем позицию камеры и нажимаем на стороны кубов

Создаём персонажа

Если все работает, как задумано, мы можем перейти к созданию персонажа, чтобы мы могли свободно двигаться в нашей игре. К счастью для нас, Unity предоставляет готовый пакет с контроллером персонажа от первого лица, так что нам не нужно будет создавать его с нуля. Перейдите в Assets → Import Package и выберите Character Controller.

42_addcc

Импортируем пакет Character Controller

В окне Importing package выберите следующее:

43_importcc

Выбираем необходимое

Во вкладке Project перейдите в Standard Assets → Character Controllers, выберите First Person Controller.prefab и перетащите его во вкладку Hierarchy.

44_firstpersoncontroller

Заготовка First Person Character Controller

Расположите его близко к центру сцены.

45_positioncc

Настраиваем местоположение заготовки

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

46_gravityoff

Гравитация не нужна!

Проверьте, что все работает.

47_test

У First Person Controller на нашей сцене есть Camera, прикрепленная, как дочерний GameObject. Когда мы запустим игру, эта камера станет главной на сцене, так что нам больше не нужна другая. Каждая камера содержит компонент AudioListener. Это и есть причина, по которой сообщение «There are 2 audio listeners in the scene. Please ensure there is always exactly one audio listener in the scene.» появляется во вкладке Console. Отключите объект Main Camera во вкладке Hierarchy.

48_disablecamera

Отключаем главную камеру

Мы почти закончили! Откройте скрипт WorldGenerator.cs и модифицируйте его:

Скрипт будет запускаться только тогда, когда он прикреплен к какому-нибудь GameObject на сцене. Создайте пустой Empty GameObject и перетащите WorldGenerator.cs на него.

49_dragndrop

Перетаскиваем WorldGenerator.cs на новый GameObject

Перетащите объект Voxel на соответствующее поле в скрипте. Эта версия алгоритма генерации мира хранит все блоки в памяти, так что не рекомендуется задавать большие значения полям Size X, Size Y и Size Z, иначе вам грозит низкая производительность или, что еще хуже, Unity может вылететь.

50_values

Размеры больше указанных выставлять не стоит

Прежде чем мы увидим нашу разработку в действии, не забудьте поправить поле Gravity в скрипте, прикрепленном к Character Controller.

51_cc_valback

И всё-таки гравитация важна

Готово! Нажмите 38_play и веселитесь!

52_final

Перевод статьи «Build Minecraft in Unity»Антон Корольков, full stack ньюсрайтер