Какие кнопки, текст, выпадающие списки и т. Д. Можно увидеть во время игры? Все это является частью того, что называется пользовательским интерфейсом (UI). Большинство игр имеют своего рода пользовательский интерфейс, который позволяет игрокам легче переключаться между уровнями и активировать определенные элементы управления (например, приостановка игры или перезапуск уровня). В предыдущей статье, описывающей, как создать Dodger в Unity, мы создали маленькую кнопку, чтобы обновить игру, если игрок проиграл.
В этом уроке мы собираемся перейти на следующий уровень и позволить пользователям приостанавливать или перезапускать игру и переключаться между различными сценами. Мы также рассмотрим, как отображать определенные элементы интерфейса только в определенное время, например, когда игра приостановлена или когда игрок умирает / проигрывает.
Большинство игр содержат меню паузы, экран поверх игры и главное меню. Так как это некоторые из немногих элементов, которые требуются для «готовой» игры, мы вставим все три в наш клон Dodger. Кроме того, мы также создадим экран инструкций, чтобы игроки могли изучить элементы управления, которые они могут использовать, прежде чем они начнут играть в игру.
Завершенную игру можно сыграть на itch.io.
Создание основного экрана паузы
Экран паузы имеет общий набор элементов управления, которые игроки могут использовать для перезапуска уровня, возврата в главное меню или для приостановки игры. Экраны паузы должны быть видны только тогда, когда игра приостановлена. В Unity мы, как правило, можем различать игру с Time.timescale
и без паузы, используя Time.timescale
. Если временной масштаб равен нулю, игра приостанавливается. Если оно больше нуля, игра не приостанавливается (мы обсудим это позже). Давайте начнем!
Создание текста паузы
Во-первых, нам нужно создать заголовок, который сообщает игроку, что игра приостановлена. Мы должны создать текстовый объект, щелкнув правой кнопкой мыши на панели иерархии и выбрав UI -> Text. Давайте назовем только что созданный объект PauseText.
Нам нужно создать заголовок, который сообщает игроку, что игра приостановлена. Мы должны создать текстовый объект, щелкнув правой кнопкой мыши на панели иерархии и выбрав UI -> Text. Давайте назовем только что созданный объект PauseText.
Теперь мы можем отформатировать объект Text, чтобы он лучше выглядел на экране игры. Чтобы изменить текст объекта «Текст», мы должны щелкнуть на панели «Инспектор» под атрибутом текста, где находятся слова «Новый текст». Внутри атрибута text мы можем изменить текст нашего текста паузы на «Paused». Чтобы придерживаться цветовой схемы игры, мы должны изменить цвет текста на белый. Это можно сделать, щелкнув по цветному объекту (где может быть выбран черный или другой цвет) и выбрав белый.
Давайте отрегулируем размещение нашего текста. Текст паузы должен быть центрирован горизонтально на экране и находиться примерно в верхней трети игрового экрана. Текст паузы можно перемещать, изменяя значения X и Y внутри атрибута Rect Transform или используя четырехсторонние стрелки в элементах управления мыши в верхнем левом углу редактора Unity. При необходимости или желании мы также можем изменить размер текста, изменив значение и изменив размер атрибутов width и height (в разделе Rect Transform).
Все, что нам нужно сделать, — это пометить объект так, чтобы после добавления кода программа могла сказать, что мы хотим, чтобы этот объект показывался только тогда, когда игра приостановлена. Мы можем нажать под названием текста паузы, где написано «Без тегов», а затем нажать «Добавить тег…». Теперь мы можем создать тег с именем «ShowOnPause». После того, как этот тег создан, нам нужно добавить его в текст паузы.
Создание приостановленных кнопок
Так как мы создали текст паузы и добавили новый тег для игровых объектов, который должен появляться, когда игра приостановлена, мы можем начать создавать кнопки, которые будут составлять меню приостановленной игры.
Мы будем создавать три разные кнопки: кнопку воспроизведения, кнопку перезагрузки и кнопку главного меню. Кнопка воспроизведения отключит игру, кнопка перезапуска перезапустит игру, а кнопка главного меню вернет игроков на сцену главного меню игры.
Давайте начнем с создания новой кнопки (щелчок правой кнопкой мыши в иерархии -> UI -> Button) и присвоения ей названия «PlayButton». Мы должны установить тег кнопки воспроизведения на ShowOnPause, чтобы он отображался только тогда, когда игра приостановлена. Теперь давайте установим текст кнопки воспроизведения на «Play». Это можно сделать, открыв текстовый дочерний объект в инспекторе (щелкните раскрывающийся список рядом с кнопкой воспроизведения в иерархии и выберите текстовый объект), а затем изменив свойство текста на «Воспроизвести». Мы должны выровнять кнопку воспроизведения по центру экрана, чтобы она находилась под текстом паузы.
Быстрый способ создать две другие кнопки — выбрать кнопку воспроизведения в иерархии и дважды ее дублировать (Command / CTRL + D). Мы можем назвать новые кнопки «RestartButton» и «MainMenuButton». Мы также должны дать каждой новой кнопке соответствующий текст. Кнопка перезагрузки должна сказать «Перезагрузка», а кнопка главного меню — «Главное меню». Теперь давайте удалим кнопку обновления, которая была создана в последнем уроке . Теперь мы видим, что у нас есть основное меню паузы. Однако меню ничего не делает, потому что мы не прикрепили код к объектам.
Давайте откроем скрипт UIManager, который был создан в последнем уроке. Мы должны отредактировать наш скрипт UIManager так, чтобы он выглядел как код ниже.
GameObject [ ] pauseObjects ; // Use this for initialization void Start ( ) { Time . timeScale = 1 ; pauseObjects = GameObject . FindGameObjectsWithTag ( "ShowOnPause" ) ; hidePaused ( ) ; } // Update is called once per frame void Update ( ) { //uses the p button to pause and unpause the game if ( Input . GetKeyDown ( KeyCode . P ) ) { if ( Time . timeScale == 1 ) { Time . timeScale = 0 ; showPaused ( ) ; } else if ( Time . timeScale == 0 ) { Debug . Log ( "high" ) ; Time . timeScale = 1 ; hidePaused ( ) ; } } } //Reloads the Level public void Reload ( ) { Application . LoadLevel ( Application . loadedLevel ) ; } //controls the pausing of the scene public void pauseControl ( ) { if ( Time . timeScale == 1 ) { Time . timeScale = 0 ; showPaused ( ) ; } else if ( Time . timeScale == 0 ) { Time . timeScale = 1 ; hidePaused ( ) ; } } //shows objects with ShowOnPause tag public void showPaused ( ) { foreach ( GameObject g in pauseObjects ) { g . SetActive ( true ) ; } } //hides objects with ShowOnPause tag public void hidePaused ( ) { foreach ( GameObject g in pauseObjects ) { g . SetActive ( false ) ; } } //loads inputted level public void LoadLevel ( string level ) { Application . LoadLevel ( level ) ; }
Теперь, когда у нас есть код, который нам нужен в скрипте UIManager, мы можем вернуться к Unity. В Unity давайте выберем кнопку воспроизведения и прикрепим к ней метод pauseControl. Для этого мы можем выбрать кнопку воспроизведения и перетащить игровой объект UIManager в пространство игровых объектов под OnClick()
на панели инспектора. Добавив игровой объект UIManager, мы теперь можем использовать второй выпадающий список для выбора функции pauseControl (UIManager -> pauseControl).
Используя те же шаги, мы можем добавить метод reload()
к кнопке перезапуска и метод loadLevel()
к кнопке главного меню. Поскольку метод loadLevel()
принимает строковый параметр, мы должны ввести «MainMenu» в поле под выпадающим списком функций.
Если мы нажмем «Играть» сейчас, мы заметим, что кнопки «Воспроизвести» и «Перезагрузить» работают Кроме того, если мы нажмем P во время игры, мы сможем приостановить и отменить паузу в игре. Единственная проблема в том, что кнопка главного меню не работает. Это потому, что мы не добавили сцену с именем «MainMenu» в настройки сборки.
Создание сцены главного меню
Создание сцены
С помощью меню паузы, созданного в игровой сцене, мы можем теперь создать новую сцену, которая будет функционировать как главное меню игры. Главное меню, которое мы создадим, будет простым и содержит только кнопку «Воспроизведение», которая приведет игроков на игровую сцену.
Во-первых, мы должны сохранить текущую сцену, в которой мы работаем, чтобы проделанная нами работа не удалялась при открытии новой. Давайте создадим новую сцену (Command / CTRL + N или File -> New Scene). Когда сцена открыта, сохраните ее и назовите «MainMenu».
Примечание. Мы называем его «MainMenu», потому что это свойство строки, для которого мы устанавливаем кнопку главного меню в сцене воспроизведения. Если бы мы хотели другое имя, то мы могли бы изменить строковое свойство функции loadLevel()
прикрепленной к кнопке главного меню в сцене воспроизведения.
Создание меню
Теперь, когда сцена была сохранена, мы можем начать работать над ней. Давайте начнем с выбора игрового объекта основной камеры и изменения его фона на тот же цвет, что и на игровой сцене (R: 0, G: 223, B: 255).
Для этой сцены нам понадобится доступ к loadLevel()
внутри скрипта UIManager. Это означает, что нам нужно создать игровой объект UIManager и присоединить к нему скрипт UIManager, чтобы мы могли добавить функцию к нашей кнопке.
Давайте создадим пустой игровой объект (щелкните правой кнопкой мыши в иерархии -> Создать пустой) и назовите его UIManager. Теперь мы можем добавить скрипт UIManager к игровому объекту UIManager.
Мы можем начать создавать простое меню, которое будет содержать текст с надписью «Dodger» и кнопку воспроизведения. Мы начнем с создания текста (щелкните правой кнопкой мыши в иерархии -> UI -> Текст) и назовите его «TitleText». Мы должны изменить текст на «Dodger» и выровнять его по центру экрана, немного ближе к вершине. Теперь давайте установим цвет текста заголовка на белый.
С созданным и отредактированным текстом мы можем создать новую кнопку и назвать ее «PlayButton». Мы должны изменить текст дочернего объекта кнопки воспроизведения на «Play». Наконец, давайте добавим игровой объект OnClick()
атрибут кнопки OnClick()
и выберем loadLevel()
. Параметр функции loadLevel()
зависит от имени сцены воспроизведения из последнего урока. Мы можем найти название игровой сцены, найдя сцену на панели Активы.
Если мы запустим игру и нажмем кнопку воспроизведения, мы заметим, что кнопка не работает. Причина та же, что и в том случае, когда кнопка главного меню не работала в нашей игровой сцене: мы не добавили сцену MainMenu в настройки сборки. Чтобы добавить нашу текущую сцену в настройки сборки, мы можем открыть настройки сборки («Файл» -> «Настройки сборки») и нажать «Добавить текущую».
Завершение игры
Чтобы игра считалась «законченной», она должна иметь игру поверх экрана, чтобы игроки могли определить, когда они проиграли. Мы также добавим счетчик очков в игру, чтобы игроки знали, как высоко они забили.
Добавление оценки
Мы должны сохранить нашу текущую сцену и открыть игровую сцену. Открыв игровую сцену, мы можем создать текстовый объект и назвать его «ScoreText». Текстовый объект партитуры должен быть выровнен по верху экрана. Выбрав текстовый объект Score, мы можем добавить привязку к верхнему растяжению, посмотрев в свойство Rect transform и щелкнув меню привязки. Мы также должны отцентрировать текст и сделать его белым.
Условие, которое мы будем использовать для обновления счета, будет блокировать выход за пределы экрана (то есть блоки, которые игрок уже уклонился). Для того чтобы это условие было активным, нам нужно проверить, нет ли столкновения блоков за пределами экрана, и увеличить переменную для оценки.
Давайте создадим пустой игровой объект и назовем его «BottomBorder». Мы добавляем BoxCollider2D к нижней границе и устанавливаем большой размер X, который немного выходит за границы камеры. Теперь мы можем добавить Rigidbody2D к объекту нижней границы и установить для атрибута масштаба гравитации значение 0, чтобы объект нижней границы не падал. Мы можем выровнять объект нижней границы немного ниже плеера, убедившись, что он находится за пределами экрана.
Нам нужно создать новый скрипт, чтобы выставить счет игроку. Давайте создадим новый скрипт C # с именем «PointCounter» внутри нашей папки Scripts. После того, как скрипт PointCounter был создан, мы можем открыть его в нашей IDE и набрать:
public int score ; // Use this for initialization void Start ( ) { score = 0 ; } // Update is called once per frame void Update ( ) { } //checks for entering a trigger void OnTriggerEnter2D ( Collider2D other ) { //checks other collider's tag if ( other . gameObject . tag == "Enemy" ) { score ++ ; //increments score Destroy ( other . gameObject ) ; //destroys other collider's gameobject } }
Сценарий PointCounter должен быть добавлен к игровому объекту с нижней границей, чтобы при столкновении блока с ним блок уничтожался и счет обновлялся.
Теперь давайте создадим скрипт с именем «PointUpdater», который будет обновлять текст партитуры. Мы можем открыть скрипт PointUpdater в нашей IDE и набрать:
public PointCounter pointCounter ; // Use this for initialization void Start ( ) { text = gameObject . GetComponent < Text > ( ) ; text . text = "Score: 0" ; } // Update is called once per frame void Update ( ) { text . text = "Score: " + pointCounter . score . ToString ( ) ; }
Мы должны добавить скрипт PointUpdater к объекту текстовой игры Score. Игровой объект нижней границы должен быть добавлен к значению счетчика очков, чтобы оценка могла быть обновлена.
Создание игры поверх меню
Чтобы закончить игру, нам нужно добавить меню «поверх игры», которое появится после смерти игрока.
Давайте откроем скрипт PlayerController в нашей IDE и добавим ниже последнего объявления переменной:
public bool alive ; // Use this for initialization void Start ( ) { alive = true ; }
Внутри скрипта EnemyController давайте добавим:
void OnTriggerEnter2D ( Collider2D other ) { //Checks if other gameobject has a Tag of Player if ( other . gameObject . tag == "Player" ) { other . gameObject . GetComponent < PlayerController > ( ) . alive = false ; Time . timeScale = 0 ; } }
Чтобы начать работу с меню, мы можем создать новый текстовый игровой объект и назвать его «GameOverText». Текст должен быть установлен на «Game Over», а цвет текста должен быть белым. Мы должны выровнять игру по тексту, чтобы она была немного выше центра экрана. Чтобы это меню появилось только после смерти игрока, мы должны создать новый тег с именем «ShowOnFinish» и добавить его в игру поверх текста.
Теперь давайте продублируем кнопки перезагрузки и главного меню. Мы должны переименовать кнопки в «FinRestartButon» и «FinMainMenuButton» и добавить тег ShowOnFinish к обеим кнопкам.
Наконец, давайте откроем скрипт UIManager в нашей IDE и отредактируем его так, чтобы он выглядел как код ниже.
GameObject [ ] pauseObjects ; GameObject [ ] finishObjects ; PlayerController playerController ; // Use this for initialization void Start ( ) { Time . timeScale = 1 ; pauseObjects = GameObject . FindGameObjectsWithTag ( "ShowOnPause" ) ; //gets all objects with tag ShowOnPause finishObjects = GameObject . FindGameObjectsWithTag ( "ShowOnFinish" ) ; //gets all objects with tag ShowOnFinish hidePaused ( ) ; hideFinished ( ) ; //Checks to make sure MainLevel is the loaded level if ( Application . loadedLevelName == "MainLevel" ) playerController = GameObject . FindGameObjectWithTag ( "Player" ) . GetComponent < PlayerController > ( ) ; } // Update is called once per frame void Update ( ) { //uses the p button to pause and unpause the game if ( Input . GetKeyDown ( KeyCode . P ) ) { if ( Time . timeScale == 1 && playerController . alive == true ) { Time . timeScale = 0 ; showPaused ( ) ; } else if ( Time . timeScale == 0 && playerController . alive == true ) { Time . timeScale = 1 ; hidePaused ( ) ; } } //shows finish gameobjects if player is dead and timescale = 0 if ( Time . timeScale == 0 && playerController . alive == false ) { showFinished ( ) ; } } //Reloads the Level public void Reload ( ) { Application . LoadLevel ( Application . loadedLevel ) ; } //controls the pausing of the scene public void pauseControl ( ) { if ( Time . timeScale == 1 ) { Time . timeScale = 0 ; showPaused ( ) ; } else if ( Time . timeScale == 0 ) { Time . timeScale = 1 ; hidePaused ( ) ; } } //shows objects with ShowOnPause tag public void showPaused ( ) { foreach ( GameObject g in pauseObjects ) { g . SetActive ( true ) ; } } //hides objects with ShowOnPause tag public void hidePaused ( ) { foreach ( GameObject g in pauseObjects ) { g . SetActive ( false ) ; } } //shows objects with ShowOnFinish tag public void showFinished ( ) { foreach ( GameObject g in finishObjects ) { g . SetActive ( true ) ; } } //hides objects with ShowOnFinish tag public void hideFinished ( ) { foreach ( GameObject g in finishObjects ) { g . SetActive ( false ) ; } } //loads inputted level public void LoadLevel ( string level ) { Application . LoadLevel ( level ) ; }
Вывод
Теперь мы добавили простой интерфейс в нашу игру. Игроки теперь смогут перемещаться по двум сценам с помощью кнопок. Мы также приобрели опыт разработки модульных Unity и DRY-кодирования (Don’t-Repeat-Yourself). То, как мы создали текст партитуры, является хорошим примером того, как код Unity должен быть разделен так, чтобы его можно было использовать повторно.
Вопросов? Комментарии? Пожалуйста, оставьте их ниже!
Готовый проект можно скачать с GitHub .