본문 바로가기

트러블 슈팅

트러블 슈팅 - Action 델리게이트 구독 순서

카드시스템의 UI를 제작하던 중 각 턴마다 실행해 주는 action "A", 그리고 매 행동을 할 때마다 실행해 주는 action "B" 그리고 action "B"에 들어가는 각종 메서드들 "C"를 구독하던 중 문제가 생겼다.

 

위에서 설명한 구조 처럼 B += C를 하고 A += B를 하면 A를 실행했을 때 C도 가능하다, 는 Action 델리게이트를 처음 배울 때 같이 학습한 정보이지만 이때까지는 이게 단순히 "가상의 메서드 안에 메서드 B 와 메서드 C의 내용을 채워 넣어서 사용한다"인 줄 알았다.
그래서 일반적인 클라스 처럼 구독의 작동 방식도 참조적인 형태로 될 줄 알고, 구독을 할 때 순서를 신경 쓰지 않는 경우가 있었다.

 

적어도 이때 까지는 A 에 B를 B에는 C를 연속적으로 구독해서 사용한 경우는 없었으니.

하지만 이번 프로젝트에서 UI와 실제 데이터 간의 원활한 상호작용을 위해서 Action 델리게이트를 여러 행동 주기마다 사용하다 보니 구독의 순서도 중요하다는 사실을 배웠다.

 

// CombatController 클라스
private void Start()
{
    OnPlayerTurn += CardStatusUpdate;
    OnEnemyTurn += CardStatusUpdate;
}


// CardDisplay 클라스
private void Start()
{
    combatController.CardStatusUpdate += SetCardCanDrag;   
}


기존 까지는 이러한 방식으로 구독을 하고있었는데,  각 클래스의 Start 실행 순서를 따로 설정하지 않고 실행시키니,

 

구독의 순서가


CardStatusUpdate <= SetCardCanDrag;
OnPlayerTurn <= CardStatusUpdate;


가 아니라

 

OnPlayerTurn <= CardStatusUpdate;

CardStatusUpdate <= SetCardCanDrag;


로 역순이 되어서 실제로 OnPlayerTurn 을 Invoke 하게 되면 CardStatusUpdate만 실행이 되어 버리는 일이 생겼다.

그래서 구독의 순서를 임의로 정해주려면 Script Execution Order도 있지만 협업을 진행하고 있기 때문에, 되도록 다른 사람들도 흐름을 알 수 있게 만드는 것이 중요했고, 따라서 하나의 클래스에서 중간 과정의 구독을 진행하였다.

// CombatUIController 클라스
private void Start()
{
    CardStatusUpdate += cardDisplay.SetCardCanDrag;
    OnPlayerTurn += CardStatusUpdate;
    OnEnemyTurn += CardStatusUpdate;
}



이렇게 수정을 한 뒤 실행을 하니, 구독된 메서드들이 정상적으로 동작함을 확인할 수 있었다.