MVC dans Unity avec des objets scriptables. 3e partie

Achèvement d'une série d'articles de Cem Ugur Karacam sur la mise en œuvre de MVC dans Unity à l'aide d'objets scriptables. Vous pouvez lire les parties précédentes ici et ici .



Ceci est la dernière étape de notre projet.

J'ai essayé de faire un diagramme pour illustrer le flux de travail MVC dans Unity.



Dans l'application Unity, les objets MonoBehaviour sont dans la scène, vous pouvez donc voir leur hiérarchie. Mais ces objets ne peuvent pas communiquer directement entre eux. Le modèle MVC d'Unity est la solution à ce problème.

Autrement dit: l'utilisateur entre dans le contrôleur, ce qui crée une vue pour le modèle, et la vue affiche les données du modèle à l'écran.

Tout d'abord, nous attendons l'entrée de l'utilisateur, par exemple, en cliquant sur un bouton. Le contrôleur crée ensuite la vue et sélectionne le modèle à afficher dans cette vue. La vue est maintenant prête, elle contient des liens vers les objets de l'interface utilisateur et transmet les données à ces liens pour affichage.

Continuons le projet avec ce sur quoi nous nous sommes installés dans le dernier article. Nous allons travailler sur la présentation. Je vais créer un panneau qui contiendra des objets d'interface utilisateur.



Nous avons un panneau, un objet Image pour l'icône de l'élément et trois objets texte pour afficher le nom, le type et la force de l'attaque. Pour gérer ces objets, créez une classe dans le projet appelée InfoView et ajoutez-la à la scène.



Ajoutez des liens vers les éléments d'interface.

 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; } 

Créez ensuite la méthode Init pour configurer ces éléments en fonction de l'entrée.

 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; } } } 

Attribuez maintenant les champs dans l'éditeur.



Nous sommes prêts à faire un préfabriqué à partir de cette vue. J'ai créé un dossier appelé Resources . Il s'agit d'un dossier spécial qui permet à Unity de télécharger des fichiers à partir de celui-ci via une API spéciale. Placez nos prefabs dans le dossier Resources .



Étant donné que j'utiliserai des préfabriqués, je supprimerai l' InfoView de la scène.



Il est temps d'ouvrir le contrôleur.

J'ajouterai une variable publique Transform pour savoir quel objet sera le parent de cette vue, et une variable privée pour garder le lien vers InfoView au démarrage.

 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"); } } 

Nous allons écrire une méthode pour créer des instances d'une vue dans une scène.

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

Je vais transmettre cette méthode ItemView à InitItem utilisant des événements en C #. Pour ce faire, modifiez un peu 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) ); } } 

J'ai ajouté un paramètre pour passer la méthode. Et maintenant, vous pouvez connecter le contrôleur.

 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); } } 

Dans la méthode Start, je remplis l'inventaire d'articles, et lorsque vous cliquez sur l'un d'eux, la méthode CreateInfoView sera appelée. Mais avant de commencer à tester cela, je vais vous signaler un problème. Le contrôleur ne sait pas si nous avons créé InfoView auparavant. Corrigeons-le.

 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); } } 

Nous avons créé la variable infoView et l' infoView testée avant de créer une nouvelle instance d' InfoView dans la scène.

Testons-le.



Il semble que nous l'avons fait!

Projet sur GitHub .

Ce ne sont que les bases de l'implémentation de MVC dans Unity à l'aide d'objets scriptables. Mais je crois qu'une approche similaire peut être mise en œuvre dans n'importe quel projet. Par exemple, lorsque vous travaillez avec des appels REST, ce modèle peut vous faire gagner beaucoup de temps et garder le code extensible. En général, dans Unity, il est assez difficile de transférer des objets de scène vers le code et de travailler avec eux. Quelqu'un peut s'opposer et dire qu'à ces fins, vous pouvez utiliser le modèle Singleton. Oui, la méthode que j'ai décrite n'est pas la seule, mais elle est très bonne.

Je pense que nous n'utilisons peut-être pas de modèles du tout, mais nous ne serons pas différents du Moyen Âge. :)

Dans tous les cas, puisque cette série d'articles est terminée, je vous suggère de lire mes autres textes, qui parlent également du modèle MVC et des objets scriptables: créer un service REST à l'aide de Node et Express à utiliser avec Unity .

C’est tout. Bon codage!

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


All Articles