옵저버 패턴,
UI뿐만 아니라 데이터를 일괄로 전달하기 위해 자주 사용하는 패턴
UI가 오픈 되어 있을 때에만 해당 UI에 데이터를 전달하는 예제를 작성
실행화면
ObserverPattern.cs
using UnityEngine;
// 옵저버 패턴의 원형
public class KMS_ObserverPattern : MonoBehaviour
{
public KMS_ObserverPattern nextOb = null;
public UIType type;
// 옵저버를 상속받는 클래스들은 다음 함수를 꼭 구현해야 한다
public virtual void Notify(Event type)
{
// 데이터가 전달 되었을 때 수행해야 하는 일들을 진행할 수 있다
}
}
해당 클래스를 상속받은 UI들
Equipment.cs
using UnityEngine;
public class KMS_UI_Equipment : KMS_ObserverPattern
{
private void Start()
{
type = UIType.Equip;
}
public override void Notify(Event type)
{
switch (type)
{
// 장비 관련 부분만 업데이트
case Event.Equipment:
Debug.Log("장비 UI를 업데이트 합니다.");
break;
}
}
}
Inventory.cs
using UnityEngine;
public class KMS_UI_Inventory : KMS_ObserverPattern
{
private void Start()
{
type = UIType.Inventory;
}
public override void Notify(Event type)
{
switch (type)
{
// 아이템 획득과 장비 변경때
case Event.Equipment:
case Event.GetItem:
Debug.Log("인벤토리 UI를 업데이트 합니다.");
break;
}
}
}
Status.cs
using UnityEngine;
public class KMS_UI_Status : KMS_ObserverPattern
{
private void Start()
{
type = UIType.Status;
}
public override void Notify(Event type)
{
switch (type)
{
// 캐릭터 상태창과 장비 변경때
case Event.StatusChange:
case Event.Equipment:
Debug.Log("스테이터스 UI를 업데이트 합니다.");
break;
}
}
}
이런 상황에서 Subject class가 해당 UI들을 컨트롤 한다
// 게임에서 넘어 올 수 있는 이벤트들
public enum Event
{
StatusChange,
Equipment,
GetItem,
}
public class KMS_Subject
{
KMS_ObserverPattern head = null;
// 메시지를 받을 UI
public void AddObserver(KMS_ObserverPattern ob)
{
ob.nextOb = head;
head = ob;
}
// 더이상 메시지를 받지 않을 UI
public void RemoveObserver(KMS_ObserverPattern ob)
{
if (head == ob)
{
head = ob.nextOb;
ob.nextOb = null;
return;
}
KMS_ObserverPattern current = head;
while (current != null)
{
if (current.nextOb == ob)
{
current.nextOb = ob.nextOb;
ob.nextOb = null;
return;
}
current = current.nextOb;
}
}
// 메시지 전달
public void Message(Event type)
{
KMS_ObserverPattern ob = head;
while (ob != null)
{
ob.Notify(type);
ob = ob.nextOb;
}
}
}
UI가 켜지고 꺼질때 마다 Add,Remove 되면서
켜져 있는 UI에게만 메시지를 보내서 서로가 각자 디커플링 된 상태에서 처리 할 수 있도록 진행한다.
GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 샘플 UI
public enum UIType
{
Status,
Inventory,
Equip,
}
public class KMS_GameManager : MonoBehaviour
{
// 옵저버 패턴을 상속받은 3개의 UI
public KMS_ObserverPattern statusUI;
public KMS_ObserverPattern InventoryUI;
public KMS_ObserverPattern EquipUI;
// UI가 생성되거나 삭제 될때 Subject를 통해서 진행
KMS_Subject subject = new KMS_Subject();
// UI가 열릴 때 호출
public void OnClickOpen(int type)
{
switch ((UIType)type)
{
case UIType.Status: // 상태창
statusUI.gameObject.SetActive(true);
subject.AddObserver(statusUI);
break;
case UIType.Inventory: // 인벤토리
InventoryUI.gameObject.SetActive(true);
subject.AddObserver(InventoryUI);
break;
case UIType.Equip: // 장비창
EquipUI.gameObject.SetActive(true);
subject.AddObserver(EquipUI);
break;
}
}
// UI가 닫힐 때 호출
public void OnClickClose(int type)
{
switch ((UIType)type)
{
case UIType.Status:
statusUI.gameObject.SetActive(false);
subject.RemoveObserver(statusUI);
break;
case UIType.Inventory:
InventoryUI.gameObject.SetActive(false);
subject.RemoveObserver(InventoryUI);
break;
case UIType.Equip:
EquipUI.gameObject.SetActive(false);
subject.RemoveObserver(EquipUI);
break;
}
}
// 게임 내 변화가 있을 때
private void Update()
{
// 키 입력으로 대체
if (Input.GetKeyUp(KeyCode.A))
{
// 캐릭터 채인지
Debug.Log("캐릭터에 변화가 있습니다.");
subject.Message(Event.StatusChange);
}
else if (Input.GetKeyUp(KeyCode.S))
{
// 아이템 획득
Debug.Log("아이템을 획득 했습니다.");
subject.Message(Event.GetItem);
}
else if (Input.GetKeyUp(KeyCode.D))
{
// 장비 장착
Debug.Log("장비를 장착합니다.");
subject.Message(Event.Equipment);
}
}
}
'프로그래밍 > 디자인패턴' 카테고리의 다른 글
Singleton Pattern_싱글톤_유니티(Unity)에서 사용가능한 5가지 싱글톤_유니티(C#)로 사용해 보는 디자인 패턴 (0) | 2020.06.06 |
---|---|
유니티(C#)로 사용해 보는 디자인 패턴_ProtoType Pattern_프로토타입 (0) | 2020.05.30 |
유니티(C#)로 사용해 보는 디자인 패턴_Flyweight Pattern_경량 패턴 (0) | 2020.05.24 |
유니티(C#)로 사용해 보는 디자인 패턴_Command Pattern_커맨드 패턴 (0) | 2020.02.23 |
Factory Mathod Pattern (0) | 2017.04.12 |