대리자를 통해서 다양한 기능을 편리하게 구현 가능하다.
예시
참조 줄이기
예시 1
"Score가 100점이 넘을 때 Particle의 PlayParticle 메서드를 실행한다."
대리자를 사용하지 않은 경우
public class GameManager//Singleton
{
private int score = 0;
public Particle particle;
public int Score
{
set
{
score = value;
if(score > 100)
{
StageClear();
}
}
}
public void StageClear()
{
particle.PlayParticle;
}
}//직접 객체를 가져와서 PlayParticle 메서드를 호출
public class Particle : MonoBehaviour
{
private void Start()
{
GameManager.particle = this;
}
public void PlayParticle()
{
//Play Particle!
}
}
대리자를 사용한 경우
public class GameManager//Singleton
{
public Action stageClear = null;
private int score = 0;
public int Score
{
set
{
score = value;
if(score > 100)
{
StageClear();
}
}
}
public void StageClear()
{
if(stageClear != null)
{
stageClear.Invoke();
}
}
}//객체의 참조 없이 PlayParticle 메서드 호출
public class Particle : MonoBehaviour
{
private void Start()
{
GameManager.stageClear += PlayParticle;
}
public void PlayParticle()
{
//Play Particle!
}
}
BroadCast(브로드캐스트)
예시 2
"서로 다른 클래스에 존재하는 메서드들을 한번에 호출한다."
"게임이 시작할 때 timer 시작, 몬스터 생성 시작"
public class GameManager//Singleton
{
public Action gameStart = null;
public void GameStart()
{
gameStart?.Invoke();
}
}//gameStart 호출
public class Timer : MonoBehaviour
{
private void Start()
{
GameManager.gameStart -= TimerStart;
GameManager.gameStart += TimerStart;
}
public void TimerStart()
{
//Timer Start!
}
}//gameStart가 호출되면 TimerStart가 실행된다
public class Monster_Spawner : MonoBehaviour
{
private Action monsterSpawn = null;
private void Start()
{
monsterSpawn = () => { StartCoroutine(MonsterSpawn()); };
GameManager.gameStart += monsterSpawn;
}
private IEnumerator MonsterSpawn()
{
Debug.Log("Monster Spawn!");
yield return null;
}
}//gameStart가 호출되면 작성해서 등록하준 람다식이 실행된다
등록과 해제
예시 3
"플레이어의 체력이 낮아질 때, 체력바를 Update한다."
"보스 몬스터가 있을 경우에 보스가 플레이어의 체력이 낮을 때, 추가피해를 준다."
public void GameManager//Singleton
{
public Player player;
}
public class Player : MonoBehaviour
{
public Action<int> healthUpdate = null;
private int health;
public int Health
{
set
{
health = value;
healthUpdate!.Invoke(health);
}
}
}//플레이어 체력이 바뀔 때마다 이벤트 호출
public class Health_Slider : MonoBehaviour
{
private Slider slider;
public void Awake()
{
GameManager.player.healthUpdate += SliderUpdate;
}
public void SliderUpdate(int value)
{
slider.value = value;
}
}//플레이어 체력에 따라서 Slider Update
public class Boss_Monster : MonoBehaviour
{
private Action<int> lamda = null;
private flaot damage;
public void Awake()
{
lamda = (int health) => { damage = 100 + 100 * (health / 100); };
GameManager.player.healthUpdate += lamda;
}
public void OnDisable()
{
GameManager.player.healthUpdate -= damageUpdate;
}
}//현재 플레이어 체력에 따라서 공격력이 바뀐다
//보스 몬스터가 죽어서 비활성화 될 떄, Action의 등록을 해제한다
장점
- instance의 참조 없이 메서드를 실행할 수 있다.
- 간편하게 메서드를 등록하고, 해제할 수 있다.
단점
- 이름을 통해서 메서드를 호출하는 방식이기 때문에, 직접적으로 메서드를 호출하는 것보다 성능이 좋지 않다.
- 언제 어떤 메서드가 등록되고 해제되는지 알기 어렵다.
주의할 점
- 등록한 메서드는 해제해야한다.
- 매 프레임마다 이벤트를 호출한다면, 오히려 성능이 나빠진다.
- 이벤트에 등록한 참조를 저장하지 않은 람다식은 해제할 수 없다.
- 외부 클래스의 private 메서드는 등록하여도, 호출되지 않는다.
'유니티 > 개념 정리' 카테고리의 다른 글
| 초기화가 호출되었는가? (0) | 2024.11.28 |
|---|---|
| GC(Garbage Collector) (0) | 2024.11.25 |
| IEnumerable과 IEnumerator (0) | 2024.11.18 |
| Predicate(술어) (0) | 2024.11.11 |
| Static(정적) (0) | 2024.11.04 |