В Unity есть средство для маркировки объектов с помощью тэгов. Тэг это текстовое имя, по которому можно искать и работать с объектами сцены. Пользователь может создать сколько угодно тэгов, но так же есть встроенные по умолчанию:
- Respawn
- Finish
- EditorOnly
- MainCamera
- Player
- GameConroller
Создать или выбрать теги можно выбрав любой GameObject и в инспекторе используя поле Tag:
Теперь пример использования.
Нам понадобится тэг "Menu", на скриншотах выше он уже создан, так что с его созданием Вы справитесь.
Далее я предлагаю рассмотреть три скрипта, на основе которых мы должны будем собрать сцену.
MainMenu.cs
using UnityEngine;
public class MainMenu : MonoBehaviour
{
public void OnGUI()
{
// позиция меню
Rect areaPos = new Rect(Screen.width / 2f - 60f, Screen.height / 2f - 100f, 120, 200);
// создаем стиль с выравниванием по центру
GUIStyle label = new GUIStyle(GUI.skin.label);
label.alignment = TextAnchor.MiddleCenter;
// область со стилем window
GUILayout.BeginArea(areaPos, GUI.skin.window);
{
GUILayout.Space(-20);
// рисуем название меню
GUILayout.Label("Main Menu", label);
GUILayout.Space(10);
// кнопка "Start Game"
if (GUILayout.Button("Start Game", GUILayout.Height(25)))
{
// активируем меню StartGame
ActivateMenu("StartGame");
}
GUILayout.Space(8);
// кнопка "Options"
if (GUILayout.Button("Options", GUILayout.Height(25)))
{
// активируем меню Options
ActivateMenu("Options");
}
GUILayout.Space(8);
// кнопка выхода
if (GUILayout.Button("Quit", GUILayout.Height(25)))
{
Application.Quit();
}
}
GUILayout.EndArea();
}
// с помощью этой функции будем активировать меню
public static void ActivateMenu(string menuName)
{
// получаем все объекты сцены, комеченные тэгом Menu
GameObject[] menus = GameObject.FindGameObjectsWithTag("Menu");
// перебираем
foreach (GameObject menu in menus)
{
// если имя совпадает с указанным, то активируем компоненты объекта, если нет - деактивируем
bool active = menu.name == menuName;
foreach (MonoBehaviour behaviour in menu.GetComponents<MonoBehaviour>())
{
behaviour.enabled = active;
}
}
}
}
OptionsMenu.cs
using System;
using UnityEngine;
public class OptionsMenu : MonoBehaviour
{
public void OnGUI()
{
Rect areaPos = new Rect(Screen.width / 2f - 60f, Screen.height / 2f - 125f, 120, 250);
// создаем стиль с выравниванием по центру
GUIStyle label = new GUIStyle(GUI.skin.label);
label.alignment = TextAnchor.MiddleCenter;
GUILayout.BeginArea(areaPos, GUI.skin.window);
{
GUILayout.Space(-20);
// название меню
GUILayout.Label("Options", label);
GUILayout.Space(5);
GUILayout.Label("Graphics Level:", label);
GUILayout.Space(8);
// кнопки выбора качества
foreach (QualityLevel qualityLevel in Enum.GetValues(typeof (QualityLevel)))
{
// цвет кнопки в зависимости что выбрано
GUI.color = (QualitySettings.currentLevel == qualityLevel) ? Color.red : Color.white;
// кадая кнопка выбирает качество
if (GUILayout.Button(qualityLevel.ToString()))
{
QualitySettings.currentLevel = qualityLevel;
}
}
GUI.color = Color.white;
GUILayout.Space(12);
// кнопка Back
if (GUILayout.Button("Back", GUILayout.Height(25)))
{
MainMenu.ActivateMenu("MainMenu");
}
}
GUILayout.EndArea();
}
}
LoadingGameMenu.cs
using UnityEngine;
using System.Collections;
public class LoadingGameMenu : MonoBehaviour
{
// строка с прогрессом
private string _progress = "Loading";
// флаг загрузки
private bool _loaded;
// при активации компонента
public void OnEnable()
{
StartCoroutine(ProgressBarUpdater());
}
// сопрограмма загрузки
public IEnumerator ProgressBarUpdater()
{
for (int i = 0; i < 9; i++)
{
_progress += ".";
yield return new WaitForSeconds(1);
}
_loaded = true;
}
// вывод GUI части
public void OnGUI()
{
Rect pos = new Rect(Screen.width / 2f - 60f, Screen.height / 2f - 10f, 120, 20);
if (!_loaded)
{
// отображаем процесс загрузки
GUI.Label(pos, _progress);
}
else
{
if(GUI.Button(pos, "Play"))
{
// старт игры
}
}
}
}
Обратите внимание на статическую функцию ActivateMenu первого скрипта. Эта функция принимает имя объекта сцены на который происходит переключение. Из остальных скриптов так же используется эта функция. Она ведет себя следующим образом: 1) находит все объекты помеченные тэгом "Menu"; 2) по имени объекта определяет что нужно сделать с компонентами объекта - включить или выключить; 3) собственно включает и выключает компоненты.
Для того чтобы активировать например меню Options мы передаем этой функции его имя и она оставляет включенными компоненты только на объекте с именем Options.
Попробуем собрать сцену:
- Создайте следующую иерархию объектов их пустых GameObject'ов:
- Назначьте соответствующие скрипты объектам меню и так же назначьте им тэг "Menu".
Заметьте что, включенным должен быть только один скрипт меню (в нащем случае MainMenu). - Можно протестировать сцену.
Я не буду описывать работу скриптов, т.к. там хватает комментариев, а остальное должно быть понятно
Иногда одного тэга на объекте не хватает, но в стандартных средствах юнити нет поддержки назначения нескольких тэгов на один объект. Данная проблема решена в проекте Antares, о котором Вы уже наверное много раз слышали.
Скачать его можно здесь.
Удачи!