(유니티) MVP2 (예제2)

티원·2025년 11월 24일

디자인패턴

목록 보기
13/16

MVP가 생각보다 어려워서 두번째 예제를 만듬

MVP 예시 (Player가 가지고있는 Gold량 변화)

Monster가 죽으면 싱글톤 MonsterManager에서 MonsterDead라는 이벤트를 Invoke한다.
Gold변화량을 UI에 표시해야할때 아래처럼 사용.

  1. 골드를 필드로서 들고 있을 대상(플레이어)이 모델, 얘한테 골드 변동 이벤트 및 골드 추가하는 메서드 두기
  2. 프리젠터는 몬스터 킬이벤트 받고, 플레이어 골드 추가 이벤트 호출하고, 뷰에게 뿌리기
  3. UI업뎃하는거는 View

Inspector

Inspector에서는 Player의 데이터와 Present이므로 이렇게 Player 스크립트 폴더 안에다가 구성했다.
GameObject에 컴포넌트 넣는 부분은 없음. Present와 Model은 Monobehavior가 없는 class 파일이므로 new로 생성 해주면된다

  • 아래 예제코드처럼 Player의 데이터라서 Player에 model을 넣은 경우는 Player에서 Model new를 해주면되고
  • View에서 Present를 필드로 두고 new 해주면된다

코드 예시

  1. 플레이어 모델 (Monobehavior없음)
    플레이어가 가지고있는 골드 정보, 계산로직
public class PlayerModel
{
    //플레이어가 가지고있는 골드와 추가하는 메서드 기능 정의
    public int Gold { get; private set; } = 0;
    public void AddGold(int amount)
    {
        Gold += amount;
    }
}
  1. 인터페이스 (View와 Presenter에서 사용할거)
    View에서 어떤 메서드로 Presenter와 연결될것인지 정의
public interface IPlayerMVPView 
{
    //UI에서 정의되어야할, 처리할 기능
    public void UpdateGoldValue(int goldValue);
}
  1. Presenter (Monobehavior없음)
  • 여기서 중요한점은 모델과 인터페이스를 private 필드로 가지고있고
  • 생성자로 입력을 받는다는 점이다.
  • 생성자로 입력을 받을때, 이번같은 경우 Player가 Gold정보가 가지고있어야하므로 PlayerManager에서 가져왔다. (이거는 케이스바이케이스 상황마다 다름)
  • 아래에는 어떤 이벤트를 받을때 Presenter의 메서드를 호출하고, 또 View의 Interface에 정의된 메서드를 호출시켜서 사용했다
public class PlayerMVPPresenter
{
    //Model과 View를 private 필드로 가지고있는다
    private PlayerModel _model;
    private IPlayerMVPView _playerView;
    //생성자로 값을 넣어줌 (이 케이스는 싱글톤에서 Model을 가져옴)
    public PlayerMVPPresenter(IPlayerMVPView view)
    {
        //골드는 Player의 정보이므로 PlayerManager라는 싱글톤에서 가져왔다
        _model = PlayerManager.Instance.Model;
        _playerView = view;
        //몬스터가 사망했을때 골드가 변화하므로 이벤트 구독
        MonsterManager.Instance.monsterDead += OnMonsterDead;
    }
    //몬스터 사망 시 돈이 오름
    private void OnMonsterDead(int reward)
    {
        _model.AddGold(reward);
        //View에서 정의될 메서드에 정보를 넣어준다
        _playerView.UpdateGoldValue(_model.Gold);
    }
    //해당 Present가 정의된곳에 Dispose로 이벤트 해지 등 하도록
    public void Dispose()
    {
        MonsterManager.Instance.monsterDead -= OnMonsterDead;
    }
}
  1. UIManager(View)
  • Interface에 정의된 메서드와 Presenter를 필드로 가짐
  • Text 등 UI에 표시될것들을 변경시켜준다
public class UIManager : Singleton<UIManager>, IPlayerMVPView
{
    //텍스트 UI 지정
    [SerializeField] TextMeshProUGUI goldText;
    //Present 지정
    private PlayerMVPPresenter _presenter;
    //별건아니고 싱글톤이라서 Awke할때 1개만 존재하도록 부모에 정의되어있다
    protected override void Awake()
    {
        base.Awake();
    }
    //_presenter를 만들어줘서 동작하도록 한다
    private void Start()
    {
        goldText.text = "Gold!!";
        _presenter = new PlayerMVPPresenter(this);
    }
    //인터페이스 메서드를 구현해서 해당값으로 UI텍스트 변화하도록
    public void UpdateGoldValue(int goldValue)
    {
        goldText.text = "Gold: " + goldValue.ToString();
    }
}
  1. PlayerManager
    별건아니고 Player Model을 get만 가능하게 설정하고, Awake에서 new 해줬다
public class PlayerManager : Singleton<PlayerManager>
{
    [SerializeField] private Player _player;
    public Player _Player => _player;
    //플레이어 모델 필드로 추가(어디서든 가져올수있게 싱글톤에 public으로)
    public PlayerModel Model { get; private set; }
    protected override void Awake()
    {
        base.Awake();
        //new로 초기 생성
        Model = new PlayerModel();
    }
	//아래는 그냥 싱글톤에서 Player가 Start되면 스스로 Set하는 코드 (MVP코드는 아니다)
    public void SetPlayer(Player player)
    {
        _player = player;
    }
}

0개의 댓글