2022.12.04 네이버 블로그에 업로드했던 글을 이전한 게시글입니다.
Unity로 MVC, MV(R)P, MVVM패턴을 구현해보려고한다.
MVC, MVP, MVVM에대한 설명은 많았지만 유니티로 구현한 설명은 적은것같아 공부겸 정리해보려고한다.
간단하게
체력 100인 캐릭터가 존재하며
Attack을 누르면 체력이 10씩 깎이며
Heal을 누르면 5씩 늘어나는 기능을 만들어보려고 한다.
[VIEW와 MODEL]
각 패턴의 공통인 View와 Model부터 작성한다
●Model
사용되는 데이터의 모임이다.
데이터와 데이터를 처리하는 부분을 Model 이라고 한다.
우선 HP가 필요하므로 Model에 HP를 작성한다.
public class Model
{
private int _hp;
public int HP { get=>_hp; set=>_hp = value; }
}
●VIEW
사용자에게 보여지는 UI부분이다.
현재 상태로는 버튼과 HP를 표현하는 텍스트가 있다.
변하는값은 HP를 표현하는 텍스트이므로 텍스트만 우선 작성한다
using UnityEngine;
using UnityEngine.UI;
public class View : MonoBehaviour
{
[SerializeField]
private Text _hpTxt;
}
[ MVC 패턴 ]
MVC패턴은 Model, View, Controller이다.
Model과 View가 연결되어있고, Controller에서 입력을 담당한다.
현재의 기능으로 설명하면,
- 버튼을 누르는 Action이 Controller로 들어온다.
- Controller에서 Model에게 HP값 변경을 요청한다.
- Model에서는 HP를 변경하고 이 값을 View에서 표시한다
●Controller
Controller에서는 버튼이 눌렸는지 확인만 담당한다.
using UnityEngine;
using UnityEngine.UI;
public class Controller : MonoBehaviour
{
[SerializeField]
private Button _attactButton;
[SerializeField]
private Button _healButton;
[SerializeField]
private Model _model;
private void Start()
{
//Attack버튼이 눌리면 Model의 Attack을 호출한다
_attactButton.onClick.AddListener(() =>
{
_model.Attack();
});
//Heal버튼이 눌리면 Model의 Heal을 호출한다
_healButton.onClick.AddListener(() =>
{
_model.Heal();
});
}
}
●View
View에서는 받은 값을 사용자가 보는 화면에 표시만 한다.
using UnityEngine;
using UnityEngine.UI;
public class View : MonoBehaviour
{
[SerializeField]
private Text _hpTxt;
public void ShowHPTxt(int hpValue)
{
_hpTxt.text = hpValue.ToString();
}
}
●Model
Model에서 실제 데이터 처리와 View와의 연동을 담당한다.
using UnityEngine;
public class Model : MonoBehaviour
{
private int _hp = 100;
[SerializeField]
private View _view;
/// <summary>
/// Attack버튼이 눌렸을 때
/// hp - 10
/// View에 표시요청
/// </summary>
public void Attack()
{
_hp -= 10;
_view.ShowHPTxt(_hp);
}
/// <summary>
/// Heal버튼이 눌렸을 때
/// hp + 5
/// View에 표시요청
/// </summary>
public void Heal()
{
_hp += 5;
_view.ShowHPTxt(_hp);
}
}
[ MVP 패턴 ]
MVP(MV(R)P)패턴은 Model, View, Presenter이다.
Model에서 데이터, View에서 화면을 담당하고 중간에 중개자 역할을 하는 Presenter가 존재한다.
현재의 기능으로 설명하면,
- 버튼을 누르는 Action이 View로 들어온다.
- View에서 Presenter에게 HP값 변경을 요청한다.
- Presenter는 Model에게 정보를 요청하고 받아온 정보를 View로 재송신한다
●View
이제 View에서 버튼 액션을 확인한다.
View의 버튼이 눌리면 Presenter에 값 변경을 요청한다.
using UnityEngine;
using UnityEngine.UI;
public class View : MonoBehaviour
{
[SerializeField]
private Text _hpTxt;
[SerializeField]
private Button _attactButton;
[SerializeField]
private Button _healButton;
[SerializeField]
private Presenter _presenter;
private void Start()
{
//Attack버튼이 눌리면 Model의 Attack을 호출한다
_attactButton.onClick.AddListener(() =>
{
_presenter.Attack();
});
//Heal버튼이 눌리면 Model의 Heal을 호출한다
_healButton.onClick.AddListener(() =>
{
_presenter.Heal();
});
}
public void ShowHPTxt(int hpValue)
{
_hpTxt.text = hpValue.ToString();
}
}
●Presenter
Presenter에서는 Model의 값을 가지고있고,
View에서 요청한 값을 Model에서 받아와
다시 View 표시한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Presenter : MonoBehaviour
{
private Model _model = new Model();
[SerializeField]
private View _view;
public void Attack()
{
_view.ShowHPTxt(_model.Attack());
}
public void Heal()
{
_view.ShowHPTxt(_model.Heal());
}
}
●Model
Model은 데이터 처리만을 담당한다.
public class Model
{
private int _hp = 100;
/// <summary>
/// Attack버튼이 눌렸을 때
/// hp - 10
/// View에 표시요청
/// </summary>
public int Attack()
{
return _hp -= 10;
}
/// <summary>
/// Heal버튼이 눌렸을 때
/// hp + 5
/// View에 표시요청
/// </summary>
public int Heal()
{
return _hp += 5;
}
}
MVP방식의 장점은 View와 Model의 의존성이 줄어든 것이지만
반대로 View와 Presenter와의 의존성이 높다.
[ MVVM 패턴 ]
MVVM패턴은 Model, View, View Model이다.
Model에서 데이터, View에서 화면을 담당하고
Model의 데이터를 View에 맞게 파싱해주는 ViewModel이 존재한다.
View에 맞게 파싱해주는 역할이므로 View의 갯수만큼 ViewModel이 늘어난다.
현재의 기능으로 설명하면,
- 값을 받아오는 것 까지는 MVP패턴과 비슷하다.
- Presenter의 중재자역할 대신 ViewModel에서는 Model에서 받아온 값을 View에 맞게 파싱한다.
●ViewModel
이번엔 ViewModel에서 View용 데이터를 가지고있고,
Model에서 받아온 데이터를 View용으로 파싱한 후 이 값을 View에서 표시한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ViewModel : MonoBehaviour
{
[SerializeField]
private View _view;
[SerializeField]
private Model _model;
private string _hpStr = string.Empty;
public void Attack()
{
_hpStr = _model.Attack().ToString();
_view.ShowHPTxt(_hpStr);
}
public void Heal()
{
_hpStr = _model.Heal().ToString();
_view.ShowHPTxt(_hpStr);
}
}
●Model
using UnityEngine;
public class Model : MonoBehaviour
{
private int _hp = 100;
/// <summary>
/// Attack버튼이 눌렸을 때
/// hp - 10
/// View에 표시요청
/// </summary>
public int Attack()
{
return _hp -= 10;
}
/// <summary>
/// Heal버튼이 눌렸을 때
/// hp + 5
/// View에 표시요청
/// </summary>
public int Heal()
{
return _hp += 5;
}
}
●View
using UnityEngine;
using UnityEngine.UI;
public class View : MonoBehaviour
{
[SerializeField]
private Text _hpTxt;
[SerializeField]
private Button _attactButton;
[SerializeField]
private Button _healButton;
private ViewModel _viewModel = new();
private void Start()
{
//Attack버튼이 눌리면 Model의 Attack을 호출한다
_attactButton.onClick.AddListener(() =>
{
_viewModel.Attack();
});
//Heal버튼이 눌리면 Model의 Heal을 호출한다
_healButton.onClick.AddListener(() =>
{
_viewModel.Heal();
});
}
public void ShowHPTxt(string hpValue)
{
_hpTxt.text = hpValue;
}
}
Unity에서는 MVVM패턴이 잘맞지않는다는 의견이 있었다.
웹에 잘 맞는 패턴
디자인패턴은 개인의 자유이며 프로젝트의 요구사항에 따라 편한 패턴을 선택해서 사용하는것이 좋을 것 같다
'UNITY' 카테고리의 다른 글
[UNITY] 자동으로 헤더를 추출하는 CSV 파일 로드 (0) | 2025.06.04 |
---|---|
UNITY로 투명화 커브드 영상 배경화면 제작 (0) | 2023.11.03 |
Unity로 스칼렛 스트링스 염력 만들어보기 (2) | 2023.11.03 |
UNITY로 스와이프 메뉴 UI 만들기 -3- Circle Swipe (0) | 2023.11.03 |
UNITY로 스와이프 메뉴 UI 만들기 -2- Canvas Swipe (1) | 2023.11.03 |