본문 바로가기
유니티/개념 정리

대리자 활용

by fore4022 2024. 11. 19.

대리자를 통해서 다양한 기능을 편리하게 구현 가능하다.


예시

참조 줄이기

예시 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