Recherche…


Modèle de conception MVC (Model View Controller)

Le contrôleur de vue de modèle est un modèle de conception très courant qui existe depuis un certain temps. Ce modèle vise à réduire le code des spaghettis en séparant les classes en parties fonctionnelles. Récemment, j'ai expérimenté ce motif dans Unity et je voudrais donner un exemple de base.

Une conception MVC se compose de trois parties principales: modèle, vue et contrôleur.


Modèle: Le modèle est une classe représentant la partie données de votre objet. Cela pourrait être un joueur, un inventaire ou un niveau entier. Si programmé correctement, vous devriez pouvoir prendre ce script et l'utiliser en dehors de Unity.

Notez quelques points à propos du modèle:

  • Il ne devrait pas hériter de Monobehaviour
  • Il ne doit pas contenir de code spécifique à Unity pour la portabilité
  • Comme nous évitons les appels d'API Unity, cela peut entraver des choses comme les convertisseurs implicites dans la classe Model (des solutions de contournement sont requises)

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

Une classe Vector3 personnalisée à utiliser avec notre modèle de données.

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

Affichage: la vue est une classe représentant la partie de visualisation liée au modèle. Ceci est une classe appropriée à dériver de Monobehaviour. Cela devrait contenir du code qui interagit directement avec les API spécifiques à Unity, y compris OnCollisinEnter , Start , Update , etc.

  • Hérite généralement de Monobehaviour
  • Contient un code spécifique à Unity

PlayerView.cs

using UnityEngine;

public class PlayerView : Monobehaviour
{
    public void SetPosition(Vector3 position)
    {
        transform.position = position;
    }
}

Controller: le contrôleur est une classe qui lie le modèle et la vue. Les contrôleurs conservent à la fois le modèle et la vue en synchronisation, ainsi que l'interaction entre les lecteurs. Le contrôleur peut écouter les événements de l'un ou l'autre partenaire et les mettre à jour en conséquence.

  • Lie le modèle et la vue en synchronisant l'état
  • Peut générer une interaction entre les partenaires
  • Les contrôleurs peuvent être ou ne pas être portables (vous devrez peut-être utiliser le code Unity ici)
  • Si vous décidez de ne pas rendre votre contrôleur portable, envisagez d’en faire un Monobehaviour pour faciliter l’inspection de l’éditeur.

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

Utilisation finale

Maintenant que nous avons toutes les pièces principales, nous pouvons créer une usine qui générera les trois parties.

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

Et enfin, nous pouvons appeler l'usine d'un directeur ...

Manager.cs

using UnityEngine;

public class Manager : Monobehaviour
{
    [ContextMenu("Load Player")]
    private void LoadPlayer()
    {
        new PlayerFactory().Load();
    }
}

Joignez le script Manager à un GameObject vide dans la scène, cliquez avec le bouton droit sur le composant et sélectionnez "Load Player".

Pour une logique plus complexe, vous pouvez introduire l'héritage avec des classes de base abstraites et des interfaces pour une architecture améliorée.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow