Schnittstellenorganisation in Unity mit UI Canvas

Unity verfügt über ein gutes System zum Erstellen einer UI Canvas-Benutzeroberfläche. Es wurde viel Schulungsmaterial darauf geschrieben, aber die meisten Anleitungen sagen Ihnen nur, welche Tasten Sie drücken müssen und welchen Code Sie schreiben müssen, damit es funktioniert. Beispielsweise besteht eine kleine Benutzeroberfläche normalerweise aus zwei Fenstern: dem Hauptmenü und den Einstellungen. In Spielen gibt es jedoch viel mehr Fenster, und wenn mindestens ein Dutzend davon vorhanden sind, besteht die Notwendigkeit einer Organisation. Als Teil dieses Artikels möchte ich darüber sprechen, wie ich dieses Problem löse.

Zuerst müssen Sie einzelne Fenster in Ihrer Benutzeroberfläche auswählen. Mit Fenster meine ich ein Panel mit einigen Steuerelementen.

Fensterbeispiele






Jedes Fenster sollte ein Stammobjekt haben, das alle Steuerelemente enthält. Dieses Objekt repräsentiert das Fenster als Ganzes. Beispielsweise gibt es ein Bedienfeld, in dem sich die Steuerelemente befinden. Es ist logisch, diese Elemente in Bezug auf das Bedienfeld untergeordnet zu machen. Jedem Fenster ist eine Komponente zugeordnet, die der Nachkomme der abstrakten Fensterklasse ist.

Fenster


Das Fenster wird unter der Annahme geschrieben, dass Fenster untergeordnete Fenster haben können, d. H. Die Fenster, die gleichzeitig aus dem aktuellen Fenster geöffnet werden können, können gleichzeitig ein untergeordnetes Fenster geöffnet werden, und der Rest sollte geschlossen werden. Zu diesem Zweck enthält die Klasse die CurrentWindow-Eigenschaft, in der der Link zum aktuell geöffneten Fenster gespeichert ist. Außerdem gibt es ein OnOpen-Ereignis, das das Öffnen eines Fensters meldet. Die ChangeCurrentWindow () -Methode kann dieses Ereignis in der Nähe von untergeordneten Fenstern abonniert werden, sodass jedes Mal, wenn ein untergeordnetes Fenster geöffnet wird, das geöffnete untergeordnete Fenster geschlossen und der Link zum aktuell geöffneten Fenster geändert wird. Im Folgenden wird eine Beispielimplementierung aufgeführt. Auch in der Klasse gibt es SelfClose () - und SelfOpen () -Methoden. Diese Methoden sind dafür verantwortlich, wie das Fenster geöffnet und geschlossen wird. Bei der Awake () -Methode wird das Fenster im UIManager registriert, d. H. Ein Link zum Fenster wird hinzugefügt.

public abstract class Window : MonoBehaviour { public bool IsOpen { get; private set; } public Window CurrentWindow { get; protected set; } = null; public delegate void OpenEventHandler(Window sender); public event OpenEventHandler OnOpen; void Awake() { UIManager.Instance.Windows.Add(this.gameObject); } public void Open() { IsOpen = true; if (OnOpen != null) OnOpen(this); SelfOpen(); } protected abstract void SelfOpen(); public void Close() { IsOpen = false; if (CurrentWindow != null) CurrentWindow.Close(); SelfClose(); } protected abstract void SelfClose(); protected void ChangeCurrentWindow(Window sender) { if (CurrentWindow != null) CurrentWindow.Close(); CurrentWindow = sender; } } 

UIManager


Als nächstes fahren wir mit der UIManager-Klasse fort, die eine Sigleton-Klasse ist, sodass alle Fenster bei Bedarf darauf zugreifen können. Wie Sie sehen können, enthält es eine Liste von Windows-Fenstern und speichert Links zu allen Fenstern auf der Bühne. InitUI () wird benötigt, um etwas zu initialisieren. Wenn Sie beispielsweise Fenster aus Prefabs erstellen möchten, können Sie hier deren Instanzen ausführen.
Mit der Start () -Methode können Sie Fenster öffnen, die von Anfang an geöffnet sein sollten, oder umgekehrt unnötige Fenster schließen. Mit der Get () -Methode können Sie einen Link zu einem bestimmten Fenster abrufen.

 using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class UIManager : MonoBehaviour { public static UIManager Instance = null; public List<GameObject> Windows; void Awake() { if (Instance == null) Instance = this; else if (Instance != this) Destroy(gameObject); InitUI(); } private void InitUI() { //to do } void Start() { foreach(var window in Windows) { var windowComponent = window.GetComponent<Window>(); if (windowComponent is StartWindow) windowComponent.Open(); else windowComponent.Close(); } } public Window Get<T> () where T : Window { foreach(var window in Windows) { var windowComponent = window.GetComponent<Window>(); if (windowComponent is T) return windowComponent; } return null; } } 

SettingsWindow


Als Beispiel werde ich meine Implementierung des Einstellungsfensters geben:

 using System.Collections; using System.Collections.Generic; using UnityEngine; public class SettingsWindow : Window { private VideoSettingsWindow videoSettingsWindow; private LanguageSettingsWindow languageSettingsWindow; private AudioSettingsWindow audioSettingsWindow; private ControlSettingsWindow controlSettingsWindow; public void Start() { videoSettingsWindow = UIManager.Instance.GetWindow<VideoSettingsWindow>(); languageSettingsWindow = UIManager.Instance.GetWindow<LanguageSettingsWindow>(); audioSettingsWindow = UIManager.Instance.GetWindow<AudioSettingsWindow>(); controlSettingsWindow = UIManager.Instance.GetWindow<ControlSettingsWindow>(); videoSettingsWindow.OnOpen += ChangeCurrentWindow; languageSettingsWindow.OnOpen += ChangeCurrentWindow; audioSettingsWindow.OnOpen += ChangeCurrentWindow; controlSettingsWindow.OnOpen += ChangeCurrentWindow; } protected override void SelfOpen() { this.gameObject.SetActive(true); } protected override void SelfClose() { this.gameObject.SetActive(false); } public void Apply() { } public void VideoSettings() { videoSettingsWindow.Open(); } public void LanguageSettings() { languageSettingsWindow.Open(); } public void AudioSettings() { audioSettingsWindow.Open(); } public void ControlSettings() { controlSettingsWindow.Open(); } } 

Über das Einstellungsfenster kann ich 4 andere Fenster öffnen, sodass nur ein Fenster geöffnet ist. Ich abonniere die ChangeCurrentWindow () -Methode des Einstellungsfensters für die OnOpen-Ereignisse der untergeordneten Fenster, sodass geöffnete Fenster geschlossen werden, wenn andere geöffnet werden. Die Implementierungen SelfOpen () und SelfClose () aktivieren oder deaktivieren einfach das Fenster.

Auf diese Weise erhalten Sie ein leicht erweiterbares UI-System. Sie müssen keine Links zu Fenstern im Inspektor oder anderswo manuell hinzufügen. Um ein neues Fenster hinzuzufügen, müssen Sie nur die entsprechende Klasse erstellen und von Window erben. Ein solches System hat einige Nachteile: Je mehr Fenster, desto mehr Klassen müssen erstellt werden und die Suche nach einem Link zum Fenster erfolgt durch Sortieren der Links, aber meiner Meinung nach zahlen sich diese Mängel mit Vorteilen aus.

Repository-Link

Source: https://habr.com/ru/post/de472770/


All Articles