サーチ…


モデルビューコントローラ(MVC)デザインパターン

モデルビューコントローラは、非常に一般的なデザインパターンであり、かなり長い間存在してきました。このパターンは、クラスを機能部品に分けることによってスパゲッティコードを減らすことに焦点を当てています。最近、私はUnityでこのデザインパターンを試していて、基本的な例を説明したいと思います。

MVCデザインは、Model、View、Controllerの3つのコア部分で構成されています。


モデル:モデルは、オブジェクトのデータ部分を表すクラスです。これはプレーヤー、目録、またはレベル全体である可能性があります。正しくプログラムされていれば、このスクリプトを使用してUnityの外で使用することができます。

モデルについていくつか注意してください。

  • Monobehaviourから継承すべきではありません
  • それは移植性のためのUnity特有のコードを含んではいけません
  • Unity API呼び出しを避けているので、これはModelクラスの暗黙のコンバータのようなものを妨げる可能性があります(回避策が必要です)

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

データモデルで使用するカスタムVector3クラス。

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

ビュー:ビューは、モデルに関連付けられた表示部分を表すクラスです。これはMonobehaviourから派生するのに適したクラスです。これには、 OnCollisinEnterStartUpdateなどのUnity固有のAPIと直接対話するコードが含まれている必要があります。

  • 一般的にMonobehaviourから継承します
  • ユニティ固有のコードが含まれています

PlayerView.cs

using UnityEngine;

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

コントローラ:コントローラは、モデルとビューの両方をバインドするクラスです。コントローラは、モデルとビューの両方を同期させ、ドライブのやりとりを維持します。コントローラは、いずれかのパートナーからのイベントをリッスンし、それに応じて更新することができます。

  • 同期状態でモデルとビューの両方をバインドする
  • パートナー間の交流を促進できます
  • コントローラはポータブルでも、そうでなくてもかまいません(Unityコードをここで使用する必要があります)
  • コントローラを移植可能にしない場合は、エディタの検査に役立つMonobehaviourを使用することを検討してください

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

最終使用

主要な部分がすべて完成したので、3つの部分すべてを生成するファクトリを作成できます。

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

そして最後に、マネージャーから工場に電話することができます...

Manager.cs

using UnityEngine;

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

シーン内の空のGameObjectにManagerスクリプトを添付し、コンポーネントを右クリックして "Load Player"を選択します。

より複雑なロジックの場合は、抽象基本クラスとインタフェースを継承して、改良されたアーキテクチャを導入することができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow