unity3d
Modelli di progettazione
Ricerca…
Modello di progettazione Model View Controller (MVC)
Il controller della vista del modello è un modello di progettazione molto comune che esiste da un po 'di tempo. Questo modello si concentra sulla riduzione del codice degli spaghetti separando le classi in parti funzionali. Recentemente ho sperimentato questo modello di design in Unity e vorrei presentare un esempio di base.
Un design MVC è costituito da tre parti principali: Modello, Vista e Controller.
Modello: il modello è una classe che rappresenta la porzione di dati del tuo oggetto. Questo potrebbe essere un giocatore, inventario o un intero livello. Se programmato correttamente, dovresti essere in grado di prendere questo script e usarlo al di fuori di Unity.
Nota alcune cose sul modello:
- Non dovrebbe ereditare da Monobehaviour
- Non dovrebbe contenere codice Unity specifico per la portabilità
- Dal momento che stiamo evitando le chiamate Unity API, questo può ostacolare cose come convertitori impliciti nella classe Model (sono necessari workaround)
Player.cs
using System;
public class Player
{
public delegate void PositionEvent(Vector3 position);
public event PositionEvent OnPositionChanged;
public Vector3 position
{
get
{
return _position;
}
set
{
if (_position != value) {
_position = value;
if (OnPositionChanged != null) {
OnPositionChanged(value);
}
}
}
}
private Vector3 _position;
}
Vector3.cs
Una classe Vector3 personalizzata da utilizzare con il nostro modello di dati.
using System;
public class Vector3
{
public float x;
public float y;
public float z;
public Vector3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
Visualizza: la vista è una classe che rappresenta la porzione di visualizzazione legata al modello. Questa è una classe appropriata per derivare da Monobehaviour. Questo dovrebbe contenere codice che interagisce direttamente con API specifiche di Unity, tra cui OnCollisinEnter
, Start
, Update
, ecc ...
- Tipicamente eredita da Monobehaviour
- Contiene codice specifico di unità
PlayerView.cs
using UnityEngine;
public class PlayerView : Monobehaviour
{
public void SetPosition(Vector3 position)
{
transform.position = position;
}
}
Controller: il controller è una classe che unisce sia il modello che la vista. I controller mantengono sia il modello che la vista sincronizzati così come l'interazione tra le unità. Il controller può ascoltare gli eventi di entrambi i partner e aggiornarli di conseguenza.
- Lega sia il modello che la vista sincronizzando lo stato
- Può guidare l'interazione tra i partner
- I controller possono essere o meno portatili (potrebbe essere necessario utilizzare il codice Unity qui)
- Se decidi di non rendere portatile il tuo controller, considera la possibilità di renderlo un Monohaviour per aiutare nell'ispezione degli editor
PlayerController.cs
using System;
public class PlayerController
{
public Player model { get; private set; }
public PlayerView view { get; private set; }
public PlayerController(Player model, PlayerView view)
{
this.model = model;
this.view = view;
this.model.OnPositionChanged += OnPositionChanged;
}
private void OnPositionChanged(Vector3 position)
{
// Sync
Vector3 pos = this.model.position;
// Unity call required here! (we lost portability)
this.view.SetPosition(new UnityEngine.Vector3(pos.x, pos.y, pos.z));
}
// Calling this will fire the OnPositionChanged event
private void SetPosition(Vector3 position)
{
this.model.position = position;
}
}
Uso finale
Ora che abbiamo tutti i pezzi principali, possiamo creare una fabbrica che genererà tutte e tre le parti.
PlayerFactory.cs
using System;
public class PlayerFactory
{
public PlayerController controller { get; private set; }
public Player model { get; private set; }
public PlayerView view { get; private set; }
public void Load()
{
// Put the Player prefab inside the 'Resources' folder
// Make sure it has the 'PlayerView' Component attached
GameObject prefab = Resources.Load<GameObject>("Player");
GameObject instance = GameObject.Instantiate<GameObject>(prefab);
this.model = new Player();
this.view = instance.GetComponent<PlayerView>();
this.controller = new PlayerController(model, view);
}
}
E finalmente possiamo chiamare la fabbrica da un manager ...
Manager.cs
using UnityEngine;
public class Manager : Monobehaviour
{
[ContextMenu("Load Player")]
private void LoadPlayer()
{
new PlayerFactory().Load();
}
}
Allega lo script Manager a un GameObject vuoto nella scena, fai clic con il tasto destro del mouse sul componente e seleziona "Carica Player".
Per una logica più complessa è possibile introdurre l'ereditarietà con classi di base e interfacce astratte per un'architettura migliorata.