unity3d
디자인 패턴
수색…
모델 뷰 컨트롤러 (MVC) 디자인 패턴
모델 뷰 컨트롤러는 아주 일반적인 디자인 패턴으로 꽤 오랫동안 사용되어 왔습니다. 이 패턴은 클래스를 기능적 부분으로 분리하여 스파게티 코드를 줄이는 데 중점을 둡니다. 최근 유니티 (Unity)에서이 디자인 패턴을 실험 해본 결과 기본 예제를 설명하고자합니다.
MVC 디자인은 모델, 뷰 및 컨트롤러의 세 가지 핵심 파트로 구성됩니다.
모델 : 모델은 개체의 데이터 부분을 나타내는 클래스입니다. 이것은 플레이어, 재고 또는 전체 레벨 일 수 있습니다. 올바르게 프로그램 되었다면이 스크립트를 가져 와서 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에서 파생되는 적절한 클래스입니다. 이것은 OnCollisinEnter
, Start
, Update
등을 포함한 Unity 특정 API와 직접 상호 작용하는 코드를 포함해야합니다.
- 일반적으로 Monobehaviour에서 상속받습니다.
- 유니티 특정 코드 포함
PlayerView.cs
using UnityEngine;
public class PlayerView : Monobehaviour
{
public void SetPosition(Vector3 position)
{
transform.position = position;
}
}
컨트롤러 : 컨트롤러는 모델과 뷰를 함께 묶는 클래스입니다. 컨트롤러는 모델 상호 작용뿐만 아니라 모델 및 뷰를 동기화 상태로 유지합니다. 컨트롤러는 파트너 중 하나의 이벤트를 수신하고 그에 따라 업데이트 할 수 있습니다.
- 동기화 상태별로 모델 및보기를 바인딩합니다.
- 파트너 간의 상호 작용을 유도 할 수 있습니다.
- 컨트롤러는 이식 가능할 수도 있고 없을 수도 있습니다 (유니티 코드를 사용해야 할 수도 있습니다)
- 컨트롤러를 휴대용으로 만들지 않으려면 편집자 검사에 도움이되는 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;
}
}
최종 사용
이제 우리는 모든 주요 부분을 가지고 있으므로 세 부분을 모두 생성하는 팩토리를 만들 수 있습니다.
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"를 선택합니다.
보다 복잡한 로직을 위해 추상적 인 기본 클래스와 인터페이스로 상속을 도입하여 개선 된 아키텍처를 구현할 수 있습니다.