MVC no Unity com objetos programáveis. Parte 3

Concluindo uma série de artigos de Cem Ugur Karacam sobre a implementação do MVC no Unity usando Objetos Script. Você pode ler as partes anteriores aqui e aqui .



Esta é a última etapa do nosso projeto.

Tentei fazer um diagrama para ilustrar o fluxo de trabalho do MVC no Unity.



No aplicativo Unity, os objetos MonoBehaviour estão em cena, para que você possa ver sua hierarquia. Mas esses objetos não podem se comunicar diretamente. O padrão MVC do Unity é a solução para esse problema.

Simplificando: a entrada do usuário chega ao controlador, que cria uma visualização para o modelo, e a visualização exibe os dados do modelo na tela.

Primeiro, estamos aguardando a entrada do usuário, por exemplo, clicando em um botão. O controlador cria a vista e seleciona o modelo necessário para ser exibido nessa vista. Agora a visualização está pronta, contém links para objetos da interface do usuário e passa dados para esses links para exibição.

Vamos continuar o projeto com o que decidimos no último artigo. Vamos trabalhar na apresentação. Vou criar um painel que conterá objetos da interface do usuário.



Temos um painel, um objeto de imagem para o ícone do item e três objetos de texto para exibir o nome, o tipo e a força do ataque. Para gerenciar esses objetos, crie uma classe no projeto chamada InfoView e adicione-a à cena.



Adicione links aos elementos da 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; } 

Em seguida, crie o método Init para configurar esses elementos de acordo com a 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; } } } 

Agora atribua os campos no editor.



Estamos prontos para fazer uma pré-fabricação a partir dessa visualização. Eu criei uma pasta chamada Resources . Essa é uma pasta especial que permite ao Unity baixar arquivos dele por meio de uma API especial. Coloque nossos prefabs na pasta Resources .



Como usarei prefabs, removerei o InfoView da cena.



Hora de abrir o controlador.

Vou adicionar uma variável pública Transform para saber qual objeto será o pai dessa exibição e uma variável privada para manter o link para o InfoView na inicialização.

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

Vamos escrever um método para criar instâncias de uma exibição em uma cena.

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

Vou passar esse método InitItem para InitItem usando eventos em C #. Para conseguir isso, altere um pouco o 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) ); } } 

Eu adicionei um parâmetro para passar o método. E agora você pode conectar o 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); } } 

No método Start, preencho o inventário com itens e, quando você clica em um deles, o método CreateInfoView será chamado. Mas antes de começarmos a testar isso, mostrarei um problema. O controlador não sabe se criamos o InfoView antes. Vamos consertar.

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

Criamos a variável infoView e testamos antes de criar uma nova instância do InfoView na cena.

Vamos testar.



Parece que conseguimos!

Projeto no GitHub .

Estes são apenas os princípios básicos da implementação do MVC no Unity usando objetos Scriptable. Mas acredito que uma abordagem semelhante possa ser implementada em qualquer projeto. Por exemplo, ao trabalhar com chamadas REST, esse modelo pode economizar muito tempo e manter o código extensível. Em geral, no Unity, é bastante difícil transferir objetos de cena para codificar e trabalhar com eles. Alguém pode se opor e dizer que, para esses fins, você pode usar o modelo Singleton. Sim, o método que descrevi não é o único, mas é muito bom.

Acho que podemos não usar modelos, mas não seremos diferentes da Idade Média. :)

De qualquer forma, uma vez que esta série de artigos foi concluída, sugiro que você leia meus outros textos, que também falam sobre o padrão MVC e Objetos Scriptable: Criando um serviço REST usando Node e Express para usar com o Unity .

Só isso. Boa codificação!

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


All Articles