[2026_01_21] 지휘관 스킬 전역 이벤트 시스템
2026. 1. 21. 21:02ㆍTIL
문제 상황
모바일 오토배틀 게임에서 지휘관 스킬이라는 특수한 버프가 필요했다.
요구사항:
- 지휘관 스킬 활성화 시 → 모든 플레이어 유닛의 기존 버프 제거
- 지휘관 스킬 활성화 시 → 모든 버퍼 유닛은 스킬 사용 중단
- 지휘관 스킬 비활성화 시 → 버퍼 유닛들 스킬 재개
- 각 유닛에게 지휘관 버프 이펙트 표시
핵심 문제: 지휘관 스킬 하나의 상태 변화가 필드 위의 모든 유닛에게 영향을 미쳐야 함
이벤트 정의
csharp
// 지휘관 스킬 활성화 이벤트
public struct ActiveBuffSkillOnEvent
{
public ActiveBuffSkillOnEvent(bool _) { }
}
// 지휘관 스킬 비활성화 이벤트
public struct ActiveBuffSkillOffEvent
{
public ActiveBuffSkillOffEvent(bool _) { }
}
2. 유닛들이 이벤트 구독
csharp
public abstract class UnitBase : MonoBehaviour
{
private GameObject commanderBuffEffect;
public virtual void Init(...)
{
// ... 기존 초기화 ...
// 플레이어 유닛만 지휘관 스킬 이벤트 구독
if (Team == Enums.TeamType.Player)
{
StaticEventSystem.Subscribe<ActiveBuffSkillOnEvent>(OnCommanderSkillActivated);
StaticEventSystem.Subscribe<ActiveBuffSkillOffEvent>(OnCommanderSkillDeactivated);
}
}
3. 지휘관 스킬에서 이벤트 발행
csharp
// 지휘관 스킬 활성화
public void ActivateCommanderSkill()
{
// 이벤트 발행 - 모든 구독자에게 알림
StaticEventSystem.Publish(new ActiveBuffSkillOnEvent(true));
// 지휘관 버프 적용 (다른 곳에서 처리)
}
// 지휘관 스킬 비활성화
public void DeactivateCommanderSkill()
{
// 이벤트 발행
StaticEventSystem.Publish(new ActiveBuffSkillOffEvent(true));
}
동작 흐름
- 지휘관 스킬 ON → StaticEventSystem.Publish(new ActiveBuffSkillOnEvent(true))
- 모든 플레이어 유닛 (10+ 유닛)
- OnCommanderSkillActivated() 호출
- 기존 버프 전부 제거
- 지휘관 버프 이펙트 생성 (각자)
- 모든 버퍼 유닛 (버퍼 3명)
- isCommanderSkillActive = true
- 스킬 사용 중단
- 기존 적용 중인 버프 이펙트 정리
- 지휘관 스킬 OFF → StaticEventSystem.Publish(new ActiveBuffSkillOffEvent(true))
- 모든 플레이어 유닛
- 지휘관 버프 이펙트 제거
- 모든 버퍼 유닛
- isCommanderSkillActive = false
- 스킬 사용 재개
핵심 패턴
1. Publish-Subscribe 패턴
- 발행자(Publisher): 지휘관 스킬
- 구독자(Subscriber): 모든 플레이어 유닛, 모든 버퍼 유닛
- 느슨한 결합: 지휘관 스킬은 몇 명의 유닛이 있는지 몰라도 됨
2. 이벤트 구독 해제의 중요성
csharp
// Init에서 구독
StaticEventSystem.Subscribe<ActiveBuffSkillOnEvent>(OnCommanderSkillActivated);
// Die/Destroy에서 해제 (필수!)
StaticEventSystem.Unsubscribe<ActiveBuffSkillOnEvent>(OnCommanderSkillActivated);
해제하지 않으면:
- 죽은 유닛이 계속 이벤트를 받음
- 메모리 누수 발생
- NullReferenceException 위험
3. 팀 필터링
csharp
if (Team == Enums.TeamType.Player)
{
StaticEventSystem.Subscribe<...>(...);
}
- 적 유닛은 지휘관 스킬의 영향을 받으면 안 되므로
- 플레이어 팀만 구독
장점
- 확장성: 유닛이 100개든 1000개든 코드 변경 없음
- 유지보수: 지휘관 스킬 로직과 유닛 로직이 분리됨
- 명확한 의도: 이벤트 이름만 봐도 무슨 일이 일어나는지 알 수 있음
- 디버깅 용이: 이벤트 발행 시점에 로그 찍으면 전체 흐름 파악 가능
주의사항
- 구독 해제 필수: Init에서 구독했으면 Die/Destroy에서 반드시 해제
- 순환 참조 방지: 이벤트 핸들러 내에서 같은 이벤트를 발행하면 무한 루프
- 성능: 이벤트가 너무 자주 발생하면 오버헤드 발생 (이 경우는 ON/OFF 2회뿐이라 괜찮음)
배운 점
- 전역 상태 변화가 필요할 때 이벤트 시스템이 효과적
- 직접 참조(GetComponent, FindObjectsOfType)보다 이벤트가 더 깔끔
- 이벤트 구독 해제를 습관화해야 함
- 단순한 플래그(isCommanderSkillActive) 하나로 복잡한 동작 제어 가능
'TIL' 카테고리의 다른 글
| [2025_01_23] 반사 스킬 무한 루프 방지 & 관통 투사체 최적화 (0) | 2026.01.23 |
|---|---|
| [2026_01_22] 임원 모의 면접 (0) | 2026.01.22 |
| [2026_01_09] 사운드 고르기... (0) | 2026.01.09 |
| [2026_01_08] 버프/디버프 적용 시 실제 적용값(appliedValue) 저장 (0) | 2026.01.08 |
| [2026_01_07] Unity UI Mask를 활용한 역마스크(Cutout Mask) (0) | 2026.01.07 |