Receiving Target Data
클라이언트에서 Target Data를 서버로 전송했으므로, 이제 서버에서는 해당 데이터를 받아야 한다. Target Data가 서버에 도착하면 GAS 내웁에서 Delegate가 Broadcast되므로, AbilitySystemComponent를 통해 해당 Delegate를 가져올 것이다.
이때 단순히 Target Data Delegate 하나를 가져오는 것이 아니라, 특정 Ability + 특정 Predictio nKEy에 해당하는 Target Data Delegate를 가져온다. 따라서 현재 실행되고 있는 Ability가 어떤 Ability인지 식별하기 위한 Ability Spec Handl,e 그리고 해당 Ability Activation과 연결된 Prediction Key가 필요하다.
Delegate를 가져왔으면 Target Data가 도착했을 때 실행될 함수를 연결해야 한다. 우선 해당 함수에 대한 몸체만 생성해주었다. 우리는 이를 AddUObject()를 통해 바인딩해줄 것이다. 필요한 변수는 Target Data 자체인 DataHandle과, Activation Tag다.

이제 Delegate에 Callback 함수를 연결해줄 것이다. 하지만 중요한 문제가 하나 있는데, 현재 서버에서 Delegate를 등록하는 시점보다 Target Data가 먼저 도착할수도 있는 것이다.
Target Data 도착
↓
Delegate Broadcast
↓
그 이후에 Callback 등록
이런 경우에는 이미 Delegate가 Broadcast된 상태이기 때문에, 나중에 Callback을 등록해도 전달되지 않는다. 따라서 GAS에서는 이미 Target Data가 도착했는지 아닌지 확인하는 과정이 필요하다.
이를 위해 사용하는 것이 CallReplicatedTargetDataDelegatesIfSet() 함수이다. 이 함수는 이미 Replicated Target Data가 도착해서 Delegate에 세팅된 상태라면 해당 Delegate를 호출한다. 해당 함수의 반환값은 bool 이기 때문에, 해당 값을 통해 Delegate가 이미 호출되었는지 아닌지를 판단하는 데 사용한다. 따라서 해당 변수가 false라면 아직 Target Data가 서버에 도착하지 않았기 때문에, SetWaitingOnRemotePlayerData() 함수를 호출하여 Player Data를 기다리도록 해준다.

이제 Callback 함수 내용을 작성해주자. Callback에서는 Target Data가 도착했으므로, 이제 Ability Task가 이 데이터를 사용할 수 있도록 전달해야 한다. 하지만 그전에 ASC 내붜에 저장되어있는 Target Data를 Consume해줄 필요가 있다.
이는 Client에서 보낸 Target Data는 서버의 ASC 내부에 저장되는데, 이를 GAS가 데이터를 받은 뒤 바로 버리는 것이 아니라, 특정 자료구조에 해당 데이터를 Cache 형태로 보관하기 때문이다. 따라서 해당 데이터를 사용했으므로 명시적으로 Consume처리를 하여 GAS에 알려주어야 하며, 해당 역할을 하는 것이 ConsumeClientReplicatedTargetData() 함수이다.
또 이어서 Ability Task가 현재 정상적으로 Delegate를 Broadcast 해도 되는 상태인지 체크해주고, 이후에 최종적으로 Target Data를 Ability Task 쪽으로 전달한다.

컴파일 후 기존 디버그 구체 출력해주는 부분을 수정해주자. 가장 먼저 기존 TargetDataUnderMouse 노드를 새로고침하여 DataHandle를 사용해 위치 좌표를 뽑아줄 것이다.

이 상태로 플레이하면 본인의 컴퓨터에서는 오류가 발생하지 않았지만, 강의에서는 클라이언트 연결이 끊기고 Output Log에 다음과 같은 오류가 발생한다.
Could not find gameplay ability target data,
single target hit in script struct cache
쉽게 말해 GAS가 Target Data를 처리하는 과정에서 필요한 정보를 찾지 못하고 있는 것이다.
따라서 Asset Manager의 CPP 파일에서 초기화 과정에 UAbilitySystemGlobals::Get().InitGlobalData();를 작성해준다. 이는 GAS의 전역 Singleton에 접근해 GAS에서 사용하는 전역 데이터를 초기화하는 역할을 한다.
Target Data는 특정 Ability 하나만 사용하는 정보가 아니라 GAS 전체에서 공통으로 사용하는 데이터이기 때문에 전역적으로 관리한다. UAbilitySystemGlobals는 이러한 GAS 전역 데이터를 관리하는 Singleton 형태의 객체이며, InitGlobalData()를 통해 Target Data Script Struct Cache 등을 초기화한다.

이제 컴파일 후, 클라이언트에서 적을 클릭하면 서버에도 정보가 전달되어 마찬가지로 디버그 구체가 표시되는 것을 볼 수 있다.

'게임 개발 학습 > [Unreal] Udemy 강의' 카테고리의 다른 글
| Gameplay Ability System - Top Down RPG / Section 11-8 (0) | 2026.09.20 |
|---|---|
| Gameplay Ability System - Top Down RPG / Section 11-6 (0) | 2026.08.20 |
| Gameplay Ability System - Top Down RPG / Section 11-5 (0) | 2026.08.07 |
| Gameplay Ability System - Top Down RPG / Section 11-4 (0) | 2026.08.05 |
| Gameplay Ability System - Top Down RPG / Section 11-3 (0) | 2026.07.26 |