GUI или как перестать страдать (Unity)

Пример GUI
Пример GUI

Всем привет, первая моя игра умерла сразу после того как я закончил геймплей и перешёл к Интерфейсу. Отсутствие опыта в этом разделе геймдева превратило разработку в АД и проект скоропостижно скончался. Но я не отчаивался, ̶я̶ ̶о̶т̶к̶о̶ф̶е̶в̶а̶л̶с̶я̶, поэтому и пишу данный текст.

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

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

Пример использования скрипта
Пример использования скрипта

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

using UnityEngine.UI; using UnityEditor; #if UNITY_EDITOR [InitializeOnLoad] #endif public class StateMachine : MonoBehaviour { [SerializeField] private GameManager.Mode ThisState; [SerializeField] private GameManager.Mode ThisStateSecond= GameManager.Mode.None; private float speed; bool Fade; [SerializeField] CanvasGroup CG; #if UNITY_EDITOR static StateMachine() { Selection.selectionChanged += SelectionChange; } static void SelectionChange() { if (Selection.activeGameObject && !Selection.activeGameObject.GetComponent<StateMachine>()) return; StateMachine[] stateMachines = FindObjectsOfType<StateMachine>(); for (int i = 0; i < stateMachines.Length; i++) { if (stateMachines[i].OnSelectionChange()) break; } for (int i = 0; i < stateMachines.Length; i++) { stateMachines[i].OnSelectionChange(); } } #endif void Awake() { speed = 0; GameManager.EventChangeState += Onchange; Onchange(); } private void OnDestroy() { GameManager.EventChangeState -= Onchange; } void Onchange() { if (GameManager.Mode.None == ThisStateSecond) { if ((GameManager.State == ThisState)) { Fade = true; } else Fade = false; } else { if (GameManager.State == ThisState || GameManager.State == ThisStateSecond) Fade = true; else Fade = false; } CG.interactable = Fade; CG.blocksRaycasts = Fade; speed = 0; } private void Update() { speed += Time.unscaledDeltaTime; if (Fade == false) { CG.alpha = Mathf.Lerp(CG.alpha, 0, speed); } else { CG.alpha = Mathf.Lerp(CG.alpha, 1, speed); } } #if (UNITY_EDITOR) public bool OnSelectionChange() { bool result = false; if (!Application.isPlaying) { if (Selection.activeGameObject == gameObject) { GameManager.State = ThisState; result = true; } if (GameManager.State == ThisState) { CG.alpha = 1; } else { CG.alpha = 0; } } return result; } #endif }

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

public static event Action EventChangeState; public enum Mode { Play, Lose, Pause, Resume, MainMenu, ChapterSelection ,Settings, AreYouSure, Achievments, Restart, ChangeQualityLow, ChangeQualityMedium, ChangeQualityHigh, ChangeQualityFantastic, SelectChapterOne, SelectChapterTwo, SelectChapterThree, SelectChapterFour, ExitGame, Yes, No, Fade, None, InventoryInInventory, InvestigateItem, LoadLevel, UseBinocular }

Когда я "изобрёл" данную фича моя жизнь изменилась навсегда. Теперь создание игровых менюшек крайне простое занятие и не ведёт в АД :)

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

PS: скрин из текущей игры в разработке Perfect Valley

6161
50 комментариев

Комментарий недоступен

12
Ответить

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

Тогда причём здесь машина состояний?

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

Если вам приходится в цикле отключать уже отключенное то это не машина состояний.


Идея игры с подземными червями очень понравилась!

9
Ответить

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

Ответить

А что вы будете делать, если глав будет 20?

2
Ответить

Когда будет, тогда и будем решать проблему. Мой способ подходит мне больше всего, это результат моих страданий, если у вас есть более простой и эффективный метод: Welcome в GameDev раздел в качестве автора :)

4
Ответить

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

Ответить

лол ты это еще не страдал. Вот, когда не было еще Unity UI, а был только GUI, вот там реально было адово и больно, или плагины юзай или страдай и все через код делай )

4
Ответить