내일배움캠프 Unity 10일차 TIL - C# 문법 종합반 4주차 강의

Wooooo·2023년 11월 10일
0

내일배움캠프Unity

목록 보기
12/94

오늘의 키워드

오늘은 강의에서 Interfacedelegate, lambda 등의 개념이 나왔다.
중요한 개념인데 나는 많이 써보질 않아서 아직 헷갈리기도 하고 손에 안익는다...
그래서, 저 3개의 키워드를 다 같이 사용해보기 좋은 Observer Pattern을 Unity로 구현해보면서 실습을 해보려고 했다.


Observer Pattern

Observer Pattern이란

Observer Pattern은 디자인 패턴 중의 하나로, 어떤 객체 A가 있고, 그 객체의 상태 변화를 주시하는 옵저버들이 있다고 치자. 이때, A의 상태가 변하면 A는 자신을 주시하는 옵저버들에게 자신의 상태가 변했음을 알린다.
여기서 어떤 객체 A를 우리는 subject라고 부르기로 했다. subject를 주시하는 객체는 observer라고 부른다.

특징

한 개의 subject에 여러 개의 observer가 있을 수 있으므로, 1:N의 의존성을 가진다.

subject는 자신을 주시하는 observer들을 모아서 관리하고, 상태가 변하면 observer들에게 일제히 알린다. observer는 자신이 주시하는 subject로부터 호출이 들어오면, 자기 자신이 할 일(callback)을 한다. 이러한 이유로 observer pattern은 다음과 같은 장점을 가진다.

  • 둘 사이의 의존성이 낮다. 느슨한 결합(loose coupling)이라고도 한다.
  • subjectobserver가 수행하는 일이 분리되어 캡슐화, 확장성, 유지보수 등에 유리하다.

구현

Interface를 이용한 방법

subjectISubject라는 인터페이스를, observerIObserver라는 인터페이스를 각각 상속받아서 구현한다.

public interface ISubject
{
	void AddObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
	void Notify();
	void Notify(object obj);
}
  
public interface IObserver
{
	public void OnNotify();
    public void OnNotify(object obj);
}

subject 객체들은 ISubject 인터페이스를 상속받아서 AddObserver()를 이용하여 자신을 주시하는 observer들을 등록한다. 마찬가지로 RemoveObserver()를 이용하여 자신을 주시하고 있는 observer를 해지할 수 있다. Notify()를 이용해서 등록된 observer들에게 자신의 상태가 변했음을 알린다. (등록된 IObserver 객체들의 OnNotify()를 호출한다.)

observer 객체들은 IObserver 인터페이스를 상속받아서 OnNotify()를 이용해 주시 중인 subject의 상태가 변했을 때의 로직을 수행한다.

delegate를 이용한 방법

C#에서는 delegate를 이용해서도 Observer Pattern을 구현할 수 있다고 한다. 그 이유는 delegate의 다음과 같은 특성들 때문인데,
delegate에는 반환값, 매개변수의 자료형이 같은 메서드들이 여러 개 등록 가능하다.
Invoke()를 이용하여 자신에게 등록된 메서드들을 한 번에 호출한다.

public delegate void StatusChangeHandler(float current, float max);
public event StatusChangeHandler OnHPChanged;
public event StatusChangeHandler OnMpChanged;
public event StatusChangeHandler OnExpChanged;
  
void Start()
{
	OnHPChanged += OnDead;
    OnHPChanged += GameObject.Find("Player Info UI").transform.GetChild(0).GetComponent<InfoUI>().SetUIBar;
    OnMpChanged += GameObject.Find("Player Info UI").transform.GetChild(1).GetComponent<InfoUI>().SetUIBar;
    OnExpChanged += GameObject.Find("Player Info UI").transform.GetChild(2).GetComponent<InfoUI>().SetUIBar;
    OnExpChanged += LevelUp;

	currentHP = MaxHP;
    currentMP = MaxMP;
    currentExp = 0;
    LV = 1;
}

현재 스탯과 최대 스탯을 매개변수로 받는 delegate를 만들어서, 각각 HP가 변했을 때, MP가 변했을 때, 경험치가 변했을 때 호출될 메서드들을 등록했다.

public float MaxHP;
public float currentHP;
public float HP
{
	get { return currentHP; }
    set
    {
    	currentHP = value;
        OnHPChanged?.Invoke(currentHP, MaxHP);
	}
}

스탯들은 property의 setter를 이용해서 delegate를 호출한다.


실습

Interface, delegate와 친해지기 위해서 Unity에서 간단한 Observer Pattern 실습을 해보기로 했다. 우선은 delegate를 이용해 UI와 Player의 status를 연결시켜봤다.

아직 기능이 많이 없다. interface를 이용한 observer로 업적 시스템도 만들어볼 생각이다.


마치며

delegate는 아직 쓰면 쓸 수록 신기하다. 뭔가 멋있기도 하다. 친해지고 싶다. 근데 어렵다.

profile
game developer

0개의 댓글