방명록
- 유니티 델리게이트&이벤트2023년 09월 15일 20시 55분 14초에 업로드 된 글입니다.작성자: noun06
- 게임에서 플레이어와 몬스터를 소환하는 기능을 만들고 싶을 때, 보통 다음과 같은 메서드를 만들고 호출함.
SpawnPlayer(); SpawnMonster();
- 이때 SpawnPlayer(); 메서드를 예를 들면 플레이어를 다양한 위치에 생성하고 싶을 수 있음. 즉, 하나의 동작에 다음과 같이 여러가지 상황이 부여될 수 있다는 것임.
SpawnPlayer_ARoom(); SpawnPlayer_BRoom(); SpawnPlayer_RandomPlace();
- 이때, 변수처럼 하나의 로직에서 다른 값으로 사용할 수 있게 할 수 있게하는 개념을 메서드에 적용할 수 있게 하는 것이 델리게이트임. 메서드를 변수처럼 만들어두고 할당한 기능이 작동하게 해주는 것임.
- 델리게이트의 기본 구조는 다음과 같음.
delegate 반환형 델리게이트명(매개변수);
- 앞의 소환 기능을 예시로 다음과 같이 델리게이트를 선언해야함.
delegate void SpawnDelegateFunc(); void Start() { InitStageData(); SpawnPlayer(); SpawnMonster(); }
- 다음으로 델리게이트를 저장할 변수를 만들어야함. 이때 변수의 타입은 델리게이트명을 사용하면 됨.
- 그리고 델리게이트에 사용할 함수들을 만듦. 사용될 함수들은 반환형과 매개변수가 같아야함.
delegate void SpawnDelegateFunc(); void Start() { SpawnDelegateFunc spawnAction; // << InitStageData(); SpawnPlayer(); SpawnMonster(); } void SpawnPlayer_ARoom(){...}; void SpawnPlayer_BRoom(){...}; void SpawnPlayer_RandomPlace(){...}; //사용 불가능한 경우 //int SpawnPlayer _CRoom(); //void SpawnPlayer _DRoom(string roomName);
- 준비된 함수 중 사용하고 싶은 함수를 델리게이트 변수에 할당함.
delegate void SpawnDelegateFunc(); void Start() { SpawnDelegateFunc spawnAction; spawnAction = SpawnPlayer_ARoom; // << //메서드를 변수에 저장만 한 상태이므로 ()는 붙이지 않음. InitStageData(); SpawnPlayer(); SpawnMonster(); } void SpawnPlayer_ARoom(){...}; void SpawnPlayer_BRoom(){...}; void SpawnPlayer_RandomPlace(){...};
- 이제 필요한 곳에서 저장된 델리게이트를 실행하면 됨.
delegate void SpawnDelegateFunc(); void Start() { SpawnDelegateFunc spawnAction; spawnAction = SpawnPlayer_ARoom; InitStageData(); spawnAction(); // << SpawnMonster(); } void SpawnPlayer_ARoom(){...}; void SpawnPlayer_BRoom(){...}; void SpawnPlayer_RandomPlace(){...};
- 델리게이트를 쓰는 가장 큰 이유는 확장성임. 측정 불가능한 경우의 수가 있을 때, 델리게이트를 사용하지않고 필요한 함수를 바로 가져다 쓰는 것은 힘듦.
- 예를 들어 여러 상황에 메시지를 전할 때가 많은 UI팝업 기능을 만든다 하면 델리게이트를 다음과 같이 활용할 수 있을 것임.
using UnityEngine; public class UIPopup { public delegate void PopupConfirmFunc(); public void PopupConfirm(PopupConfirmFunc confirmAction) { confirmAction(); } }
using UnityEngine; public class GameManager : MonoBehaviour { private UIPopup uiPopup; private void Start() { // UIPopup 객체 초기화 uiPopup = new UIPopup(); // 캐릭터 변경 팝업 호출 uiPopup.PopupConfirm(ChangeCharacter); // 게임 종료 팝업 호출 uiPopup.PopupConfirm(QuitGame); } // 캐릭터 변경 메서드 private void ChangeCharacter() { Debug.Log("캐릭터 변경 로직을 실행합니다."); // 여기에 캐릭터 변경 로직 추가 } // 게임 종료 메서드 private void QuitGame() { Application.Quit(); } }
- 이와 같이 메서드의 매개변수로 변수를 넘기듯이 (각종 메서드들이 담겨있는)델리게이트를 넘길 수 있음.
- 이제 각 기능별로 따로 클래스를 만들 필요도, 메서드를 따로 만들어 둘 필요가 없이 UIPopup을 모두 동일하게 사용할 수 있음.
- 별도로 기능을 구현하지 않고 전달받은 기능만 실행하도록 여러 상황에 대응할 수 있음!
- 이벤트는 델리게이트의 한 종류라고 볼 수 있음. 기본적인 구조는 다음과 같음.
event 델리게이트명 변수명;
- 이벤트는 이벤트 발생자(pubilhser)과 이벤트 구독자(subscriber)로 구성됨.
- 발생자는 이벤트가 발생하는 객체를 나타냄. 이벤트가 일어났음을 알릴 때 사용할 이벤트를 정의하고 발생 조건을 만족할 때 이벤트 핸들러라고 불리는 이벤트를 처리하는 함수를 호출함.
- 구독자는 이벤트 처리를 감지하고 처리하는 객체/함수를 나타냄. 이벤트 발생자의 이벤트에 등록하여 이벤트가 발생했을 때 행당 이벤트를 처리하도록 설정됨.
- 게임에서 플레이어 죽음 이라는 이벤트가 있을때 이벤트 발생자는 플레이이고 이벤트 구독자는 게임매니저, UI 등이 됨.
- 게임 매니저나 UI는 플레이어 죽음 이벤트에 등록하여 이벤트가 발생할 때마다 점수 감소, UI창 활성화 등의 특정 동작을 수행함.
using UnityEngine; using System; public class Player : MonoBehaviour { // 플레이어 죽음 이벤트 선언 public event Action onPlayerDeath; // 플레이어가 죽음을 처리하는 메서드 public void Die() { Debug.Log("플레이어가 죽었습니다."); // 플레이어 죽음 이벤트 발생 onPlayerDeath?.Invoke(); } }
public class GameManager : MonoBehaviour { public Player player; private void Start() { // 플레이어 죽음 이벤트에 게임 매니저의 메서드 등록 player.onPlayerDeath += OnPlayerDeath; } // 플레이어가 죽었을 때 호출되는 메서드 private void OnPlayerDeath() { Debug.Log("게임 매니저: 플레이어가 죽었습니다."); // 여기서 게임 오버 처리 또는 다른 동작 수행 } }
public class UIManager : MonoBehaviour { public Player player; private void Start() { // 플레이어 죽음 이벤트에 UI의 메서드 등록 player.onPlayerDeath += OnPlayerDeath; } // 플레이어가 죽었을 때 호출되는 메서드 private void OnPlayerDeath() { Debug.Log("UI: 플레이어가 죽었습니다."); // 여기서 UI 업데이트 또는 다른 동작 수행 } }
- 위 예시를 통해 이벤트 처리에서 유용하게 활용되는 옵저버 패턴의 핵심 아이디어의 확인이 가능함.
- 옵저버 패턴은 어떤 객체(주체)의 상태가 변할 때, 그 객체에 의존하는 다른 객체(옵저버)들이 자동으로 알림을 받고 상태 변화에 대응하는 메커니즘으로 작동함.
- 예시에서의 주체는 플레이어 객체이며 옵저버는 게임매니저와 UI매니저임. 주체가 죽음 이벤트를 발생시키면 옵저버들은 해당 이벤트를 구독하고 이벤트가 발생하면 동작을 수행하는거임.
- 그런데 위 코드에서 이상하게도 event를 활용하였지만 delegate를 만들지 않음.
- 대신 Action이라는 키워드를 사용하였는데 이는 C#에서 제공하는 내장 delegate임. 매개변수로 넘기는 부분은 Action 뒤에 제네릭으로 추가함.(뒤에 <타입>붙이기).
- 한가지 조건이 있는데 Action은 반환형이 void인 델리게이트만 처리가 가능함.
다음글이 없습니다.이전글이 없습니다.댓글