09
21

https://developers.cyberagent.co.jp/blog/archives/4262/

 

Web出身のUnityエンジニアによる大規模ゲームの基盤設計 | CyberAgent Developers Blog

みなさま、こんにちは。 2013年度新卒入社の吉成(@y_yoshinari)と申します。 現在私は『ボーイフレンド(仮)きらめき☆ノート』(以下、ボイきら)というサービスのUnityの実装を担当して

developers.cyberagent.co.jp

 

Model과 View를 분리하기 위해 MVP 패턴을 기반으로 함.

MVP의 MModel , VView , PPresenter 를 나타냄.

 

MVP패턴은 구현방법이 워낙 다양해서 정도는 없다.

 

Presenter는 Model과 View를 알고있지만

Model과 View는 Presenter를 몰라서 상호참조를 하지 않음.

 

 

MVP 패턴의 필수요소

1. Presenter가 Model의 값의 변화를 감지하여 View를 조작 함

2. Presenter가 View의 사용자 입력을 감지하여 Model을 조작함

Presenter는 Model과 View를 알고있기 때문에 직접 조작가능하지만, View와 Model은 모르기 때문에 이벤트 방식으로 구현해야한다.

Model -> Presenter의 값 변경은 UniRX의 ReactiveProperty을 사용하면 쉽게 구현 가능하다.

 

 

Model의 구현

IReadOnlyReactiveProperty 인터페이스만을 공개하여 외부에서 값을 직접 변경하는 것을 금지함.

사실 public으로 SetTiming이 공개되어있기때문에 같기는 하다.

public class SettingModel
{
    private ReactiveProperty<int> _timing;
    public IReadOnlyReactiveProperty<int> Timing
    {
        get { return _timing; }
    }

    public SettingModel()
    {
        _timing = ReactiveProperty<int>(0);
    }

    public void SetTiming(int timing)
    {
        _timing.Value = timing;
    }
}

 

 

View의 구현

View쪽에서는 각 입력에 대한 이벤트 호출로 이루어져있다.

함수 중 OnTimingChanged(int)는 Model 값에 변화을 업데이트함

public class SettingView : MonoBehavior
{
    [SerializeField]
    private UILabel _timingLabel;

    public Action OnPlusButtonClickedListener;
    public Action OnMinusButtonClickedListener;
    public Action OnAutoButtonClickedListener;
    public Action OnResetButtonClickedListener;
    
    public void OnTimingChanged(int timing)
    {
        _timingLabel.text = timing.ToString();
    }
    
    public void OnPlusButtonClicked()
    {
        OnPlusButtonClickedListener?.Invoke();
    }

    public void OnMinusButtonClicked()
    {
        OnMinusButtonClickedListener?.Invoke();
    }

    public void OnAutoButtonClicked()
    {
        OnAutoButtonClickedListener?.Invoke();
    }

    public void OnResetButtonClicked()
    {
        OnResetButtonClickedListener?.Invoke();
    }
}

 

 

Presenter의 구현

View는 인스펙터에서 할당하고 Model은 내부에서 생성한다.

(내부로직도 Presenter가 맡는 형태로 구현되었다.)

public class SettingPresenter : MonoBehavior
{
    [SerializeField]
    private SettingView _view;
    private SettingModel _model;

    public void Initialize()
    {
        _model = new SettingModel();

        Bind();
        SetEvents();
    }

    private void Bind()
    {
        _model.Timing
            .Subscribe(_view.OnTimingChanged)
            .AddTo(gameObject);
    }

    private void SetEvents()
    {
        _view.OnPlusButtonClickedListener = OnPlusButtonClicked;
        _view.OnMinusButtonClickedListener = OnMinusButtonClicked;
        _view.OnAutoButtonClickedListener = OnAutoButtonClicked;
        _view.OnResetButtonClickedListener = OnResetButtonClicked;
    }

    private void OnPlusButtonClicked()
    {
        if (_model.Timing.Value < MAX_TIMING)
            _model.SetTiming(_model.Timing.Value + 1);
    }

    private void OnMinusButtonClicked()
    {
        if (MIN_TIMING < _model.Timing.Value)
            _model.SetTiming(_model.Timing.Value - 1);
    }

    private void OnAutoButtonClicked()
    {
    }

    private void OnResetButtonClicked()
    {
        _model.SetTiming(0);
    }
}

 

 

MVP 덤 1

개체를 모니터링 할 때, 값타입이 아니라면 null 인 경우가 있을 수 있으니 null체크를 고려해야한다.

public class View : MonoBehavior
{
    public void OnPlayerChanged(PlayerData player)
    {
        if (player == null)
            return;
        
        _nicknameLabel.value = player.Nickname;
        _levelLabel.value = player.Level.ToString();
    }
}

만약 UniRX를 사용한다면 데코레이터를 사용하면 된다.

_model.Player
    .Where(player => player != null)
    .Subscribe(_view.OnPlayerChanged)
    .AddTo(gameObject);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'🌍 Unity 연구 > 아키텍처' 카테고리의 다른 글

MVP 정리  (0) 2021.09.20
UIView  (0) 2021.09.19
MVC / MVP / MVVM 패턴 자료수집  (0) 2021.09.17
COMMENT