MVC en Unity con Objetos Scriptables. Parte 3

Completando una serie de artículos de Cem Ugur Karacam sobre la implementación de MVC en Unity usando Objetos programables. Puedes leer las partes anteriores aquí y aquí .



Esta es la última etapa de nuestro proyecto.

Traté de hacer un diagrama para ilustrar el flujo de trabajo MVC en Unity.



En la aplicación Unity, los objetos MonoBehaviour están en la escena, por lo que puede ver su jerarquía. Pero estos objetos no pueden comunicarse entre sí directamente. El patrón MVC de Unity es la solución a este problema.

En pocas palabras: la entrada del usuario llega al controlador, que crea una vista para el modelo, y la vista muestra los datos del modelo en la pantalla.

Primero, estamos esperando la entrada del usuario, por ejemplo, haciendo clic en un botón. El controlador crea la vista y selecciona el modelo que se debe mostrar en esa vista. Ahora la vista está lista, contiene enlaces a objetos de la interfaz de usuario y pasa datos a estos enlaces para su visualización.

Continuemos el proyecto con lo que resolvimos en el último artículo. Trabajaremos en la presentación. Crearé un panel que contendrá objetos UI.



Tenemos un panel, un objeto de imagen para el ícono del elemento y tres objetos de texto para mostrar el nombre, el tipo y la fuerza del ataque. Para administrar estos objetos, cree una clase en el proyecto llamada InfoView y agréguela a la escena.



Agregar enlaces a elementos de la interfaz.

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

Luego cree el método Init para configurar estos elementos de acuerdo con la entrada.

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

Ahora asigne los campos en el editor.



Estamos listos para hacer un prefab desde esta vista. Creé una carpeta llamada Resources . Esta es una carpeta especial que le permite a Unity descargar archivos desde una API especial. Coloque nuestros prefabricados en la carpeta Resources .



Como usaré prefabricados, eliminaré el InfoView de la escena.



Hora de abrir el controlador.

Agregaré la variable pública Transform para saber qué objeto será el padre de esta vista y la variable privada para mantener el enlace InfoView al inicio.

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

Escribiremos un método para crear instancias de una vista en una escena.

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

ItemView este método ItemView a InitItem usando eventos en C #. Para lograr esto, cambie un poco 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) ); } } 

Agregué un parámetro para pasar el método. Y ahora puedes conectar el controlador.

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

En el método de Inicio, lleno el inventario con elementos, y cuando hace clic en uno de ellos, se CreateInfoView método CreateInfoView . Pero antes de comenzar a probar esto, te señalaré un problema. El controlador no sabe si creamos InfoView antes. Vamos a arreglarlo

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

Creamos la variable infoView y la probamos antes de crear una nueva instancia de InfoView en la escena.

Probémoslo.



Parece que lo hicimos!

Proyecto en GitHub .

Estos son solo los conceptos básicos de la implementación de MVC en Unity utilizando objetos de secuencias de comandos. Pero creo que se puede implementar un enfoque similar en cualquier proyecto. Por ejemplo, cuando trabaje con llamadas REST, esta plantilla puede ahorrarle mucho tiempo y mantener el código extensible. En general, en Unity es bastante difícil transferir objetos de escena a código y trabajar con ellos. Alguien puede objetar y decir que para estos fines puede usar la plantilla Singleton. Sí, el método que describí no es el único, pero es muy bueno.

Creo que es posible que no usemos plantillas en absoluto, pero no seremos diferentes de la Edad Media. :)

En cualquier caso, dado que esta serie de artículos se ha completado, le sugiero que lea mis otros textos, que también hablan sobre el patrón MVC y los Objetos de secuencias de comandos: Hacer un servicio REST usando Node y Express para usar con Unity .

Eso es todo. Buena codificación!

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


All Articles