MVC in Einheit mit skriptfähigen Objekten. Teil 3

Abschluss einer Artikelserie von Cem Ugur Karacam zur MVC-Implementierung in Unity mit skriptfähigen Objekten. Die vorherigen Teile können Sie hier und hier lesen.



Dies ist die letzte Phase unseres Projekts.

Ich habe versucht, ein Diagramm zu erstellen, um den MVC-Workflow in Unity zu veranschaulichen.



In der Unity-Anwendung befinden sich MonoBehaviour-Objekte in der Szene, sodass Sie deren Hierarchie sehen können. Diese Objekte können jedoch nicht direkt miteinander kommunizieren. Das MVC-Muster von Unity ist die Lösung für dieses Problem.

Einfach ausgedrückt: Benutzereingaben werden in die Steuerung eingegeben, die eine Ansicht für das Modell erstellt, und die Ansicht zeigt die Modelldaten auf dem Bildschirm an.

Zunächst warten wir auf Eingaben des Benutzers, z. B. durch Klicken auf eine Schaltfläche. Der Controller erstellt dann die Ansicht und wählt das Modell aus, das in dieser Ansicht angezeigt werden soll. Jetzt ist die Ansicht fertig, sie enthält Links zu Benutzeroberflächenobjekten und übergibt Daten zur Anzeige an diese Links.

Setzen wir das Projekt mit dem fort, worauf wir uns im letzten Artikel geeinigt haben. Wir werden an der Präsentation arbeiten. Ich werde ein Panel erstellen, das UI-Objekte enthält.



Wir haben ein Bedienfeld, ein Bildobjekt für das Symbol des Elements und drei Textobjekte, um den Namen, den Typ und die Stärke des Angriffs anzuzeigen. Um diese Objekte zu verwalten, erstellen Sie im Projekt eine Klasse mit dem Namen InfoView und fügen Sie sie der Szene hinzu.



Fügen Sie Verknüpfungen zu Oberflächenelementen hinzu.

 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class InfoView : MonoBehaviour { public Image icon; public Text nameText; public Text typeText; public Text attackText; } 

Erstellen Sie dann die Init-Methode, um diese Elemente entsprechend der Eingabe zu konfigurieren.

 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class InfoView : MonoBehaviour { public Image icon; public Text nameText; public Text typeText; public Text attackText; public void Init(ItemData data) { icon.sprite = data.icon; nameText.text = data.name; attackText.text = "Attack Power: " + data.attack; switch (data.type) { case ItemType.Axe: typeText.text = "Type: Axe"; break; case ItemType.Dagger: typeText.text = "Type: Dagger"; break; case ItemType.Hammer: typeText.text = "Type: Hammer"; break; case ItemType.Potion: typeText.text = "Type: Potion"; break; } } } 

Ordnen Sie nun die Felder im Editor zu.



Wir sind bereit, aus dieser Sicht ein Fertighaus zu fertigen. Ich habe einen Ordner namens Resources . Dies ist ein spezieller Ordner, mit dem Unity über eine spezielle API Dateien von diesem Ordner herunterladen kann. Legen Sie unsere Prefabs in den Ordner Resources .



Da ich Prefabs verwenden werde, werde ich das InfoView aus der Szene entfernen.



Zeit zum Öffnen des Controllers.

Ich werde die öffentliche Variable Transform hinzufügen, um zu erfahren, welches Objekt das übergeordnete Objekt für diese Ansicht ist, und die private Variable, um den InfoView Link beim Start InfoView .

 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemViewController : MonoBehaviour { public Inventory inventoryHolder; public Transform inventoryViewParent; public Transform infoViewParent; private GameObject infoViewPrefab; private GameObject itemViewPrefab; private void Start() { itemViewPrefab = (GameObject)Resources.Load("Item"); infoViewPrefab = (GameObject)Resources.Load("InfoView"); } } 

Wir werden eine Methode zum Erstellen von Instanzen einer Ansicht in einer Szene schreiben.

 private void CreateInfoView(ItemData data) { var infoGO = GameObject.Instantiate(infoViewPrefab, infoViewParent); infoGO.GetComponent<InfoView>().Init(data); } 

Ich werde diese ItemView Methode mit Ereignissen in C # an InitItem . Ändern Sie dazu ein wenig ItemView .

 using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ItemView : MonoBehaviour { public Button button; public Image itemIcon; private ItemData itemData; public void InitItem(ItemData item, Action<ItemData> callback) { this.itemData = item; itemIcon.sprite = itemData.icon; button.onClick.AddListener(() => callback(itemData) ); } } 

Ich habe einen Parameter hinzugefügt, um die Methode zu übergeben. Und jetzt können Sie den Controller anschließen.

 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemViewController : MonoBehaviour { public Inventory inventoryHolder; public Transform inventoryViewParent; public Transform infoViewParent; private GameObject infoViewPrefab; private GameObject itemViewPrefab; private void Start() { itemViewPrefab = (GameObject)Resources.Load("Item"); infoViewPrefab = (GameObject)Resources.Load("InfoView"); foreach (var item in inventoryHolder.inventory) { var itemGO = GameObject.Instantiate(itemViewPrefab, inventoryViewParent); itemGO.GetComponent<ItemView>().InitItem(item, CreateInfoView); } } private void CreateInfoView(ItemData data) { var infoGO = GameObject.Instantiate(infoViewPrefab, infoViewParent); infoGO.GetComponent<InfoView>().Init(data); } } 

In der Start-Methode fülle ich das Inventar mit Elementen, und wenn Sie auf eines davon klicken, wird die CreateInfoView Methode aufgerufen. Bevor wir dies testen, möchte ich Sie auf ein Problem hinweisen. Der Controller weiß nicht, ob wir zuvor InfoView erstellt InfoView . Lass es uns reparieren.

 using System.Collections; using System.Collections.Generic; using UnityEngine; public class ItemViewController : MonoBehaviour { public Inventory inventoryHolder; public Transform inventoryViewParent; public Transform infoViewParent; private GameObject infoViewPrefab; private GameObject itemViewPrefab; private GameObject infoView; private void Start() { itemViewPrefab = (GameObject)Resources.Load("Item"); infoViewPrefab = (GameObject)Resources.Load("InfoView"); foreach (var item in inventoryHolder.inventory) { var itemGO = GameObject.Instantiate(itemViewPrefab, inventoryViewParent); itemGO.GetComponent<ItemView>().InitItem(item, CreateInfoView); } } private void CreateInfoView(ItemData data) { if (infoView != null) { Destroy(infoView); } infoView = GameObject.Instantiate(infoViewPrefab, infoViewParent); infoView.GetComponent<InfoView>().Init(data); } } 

Wir haben die infoView Variable erstellt und getestet, bevor wir eine neue Instanz von InfoView in der Szene erstellt haben.

Lass es uns testen.



Es scheint, wir haben es geschafft!

Projekt auf GitHub .

Dies sind nur die Grundlagen für die Implementierung von MVC in Unity mithilfe von skriptfähigen Objekten. Aber ich glaube, dass ein ähnlicher Ansatz in jedem Projekt umgesetzt werden kann. Wenn Sie beispielsweise mit REST-Aufrufen arbeiten, können Sie mit dieser Vorlage viel Zeit sparen und den Code erweiterbar halten. Im Allgemeinen ist es in Unity ziemlich schwierig, Szenenobjekte in den Code zu übertragen und mit ihnen zu arbeiten. Jemand kann Einwände erheben und sagen, dass Sie für diese Zwecke die Singleton-Vorlage verwenden können. Ja, die von mir beschriebene Methode ist nicht die einzige, aber sie ist sehr gut.

Ich denke, wir werden vielleicht überhaupt keine Vorlagen verwenden, aber dann werden wir uns nicht vom Mittelalter unterscheiden. :)

In jedem Fall empfehle ich Ihnen, nach Abschluss dieser Artikelserie meine anderen Texte zu lesen, in denen auch das MVC-Muster und skriptfähige Objekte behandelt werden: Erstellen eines REST-Dienstes mit Node und Express zur Verwendung mit Unity .

Das ist alles. Gute Codierung!

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


All Articles