1. 스펙(Spec)이란?
- 스펙(Spec)은 게임플레이 어빌리티(Ability)에 대한 정보를 담고 있는 구조체입니다.
- ASC(Ability System Component)는 어빌리티 인스턴스를 직접 참조하지 않고, 스펙 정보만을 가지고 관리합니다.
- 스펙은 어빌리티의 현재 상태 등 다양한 정보를 포함합니다.
- ASC에서 어빌리티를 제어할 때는, 스펙에 포함된 Handle 값을 사용해 컨트롤합니다.
- 핸들 값은 전역으로 관리되며, 스펙이 생성될 때마다 1씩 증가합니다. 기본값은 -1이며,
이는 잘못된 핸들인지 여부를 판별하는 데 사용됩니다. - 요약
- 어빌리티 정보: 스펙(Spec)
- 어빌리티 인스턴스 레퍼런스: 스펙 핸들(Handle)
2. 어빌리티 시스템 컴포넌트의 입력 처리
- 게임 어빌리티 스펙에는 입력 값을 지정할 수 있는 필드인 InputID가 제공됩니다.
- InputID를 통해 모든 GAS(게임 어빌리티 시스템)에서 일관된 방식으로 입력 처리를 할 수 있습니다.
입력 처리 순서:
- 입력 발생
- 사용자의 입력이 들어오면, ASC는 등록된 스펙 중에서 입력에 매핑된 GA(게임 어빌리티)를 찾습니다.
- → FindAbilitySpecFromInputID 함수 사용
- GA 발동 상태 체크
- 해당 GA가 이미 발동 중이면, 입력 신호를 GA에 전달합니다.
- → AbilitySpecInputPressed
- GA가 발동 중이 아니라면, 어빌리티를 새로 발동시킵니다.
- → TryActivateAbility
- 해당 GA가 이미 발동 중이면, 입력 신호를 GA에 전달합니다.
- 입력 해제 처리
- 입력이 해제되면, 동일하게 GA에 입력 해제 신호를 전달합니다.
- → AbilitySpecInputReleased
- 입력이 해제되면, 동일하게 GA에 입력 해제 신호를 전달합니다.
- EnhancedInputComponent의 BindAction 함수를 활용하면 이러한 입력 처리를 범용적으로 쉽게 구현할 수 있습니다.
게임플레이 어빌리티의 인스턴싱 옵션
상황에 따라 어빌리티의 인스턴스 생성(Instancing) 정책을 선택할 수 있습니다.
1. NonInstanced
- 설명: 별도의 인스턴스 없이 CDO(Class Default Object)에서 모든 로직을 처리합니다.
- 특징: 상태를 가지지 않는, 완전히 동일한 어빌리티에 적합합니다.
2. InstancedPerActor
- 설명: 액터(플레이어 등)마다 하나의 어빌리티 인스턴스를 생성해서 관리합니다.
- 특징: 각 액터가 고유의 어빌리티 상태를 가질 수 있으며, 네트워크 리플리케이션(동기화)까지 고려했을 때 가장 무난한 선택입니다.
- 별칭: Primary Instance
3. InstancedPerExecution
- 설명: 어빌리티가 발동될 때마다 새로운 인스턴스를 생성해서 처리합니다.
- 특징: 어빌리티 사용 시마다 별도 상태나 임시 데이터를 저장해야 할 때 유용합니다.
네트워크 리플리케이션(동기화) 고려
- InstancedPerActor 옵션은 액터마다 하나의 어빌리티 인스턴스를 생성해 처리하므로,
- 클라이언트와 서버 간의 상태 동기화 및 관리가 용이합니다.
- 실무적으로 네트워크 게임에서는 InstancedPerActor가 가장 널리 사용됩니다.
1. NonInstanced 예시
상황
- 어빌리티가 상태를 가지지 않고, 전역적으로 동일한 동작만 하면 되는 경우
(ex. 모든 플레이어가 동일하게 적용되는 버프, 단순 효과)
코드 예시
// 헤더 파일에서 인스턴싱 정책 지정
AbilityInstancingPolicy = EGameplayAbilityInstancingPolicy::NonInstanced;
// 실제 C++ 클래스 선언부
UCLASS()
class UGA_NonInstanced : public UGameplayAbility
{
GENERATED_BODY()
public:
// 상태를 저장하지 않는 순수 효과 예시
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override
{
// 효과만 적용
// ex: 체력 +10
}
};
2. InstancedPerActor 예시
상황
- 각 액터(플레이어/몬스터 등)별로 어빌리티의 상태(쿨타임, 카운터, 스택 등)가 필요할 때
- 네트워크 멀티플레이에서 동기화가 중요한 어빌리티
코드 예시
AbilityInstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
UCLASS()
class UGA_InstancedPerActor : public UGameplayAbility
{
GENERATED_BODY()
public:
// 액터마다 개별 상태를 가짐
int32 CooldownCount;
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override
{
CooldownCount++;
// ex: 쿨타임 적용 등 액터별 상태 관리
}
};
3. InstancedPerExecution 예시
상황
- 어빌리티가 매번 발동 시마다 개별 임시 상태나 데이터를 관리해야 할 때
(ex. 발동 중에만 유지되는 임시 변수, 여러 번 동시 발동 가능)
코드 예시
AbilityInstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerExecution;
UCLASS()
class UGA_InstancedPerExecution : public UGameplayAbility
{
GENERATED_BODY()
public:
// 매 실행마다 개별 데이터 관리
float Duration;
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle,
const FGameplayAbilityActorInfo* ActorInfo,
const FGameplayAbilityActivationInfo ActivationInfo,
const FGameplayEventData* TriggerEventData) override
{
Duration = 2.0f; // 예: 이번 실행에만 사용되는 타이머
// 이 인스턴스는 곧 GC됨
}
};
정리
- NonInstanced : 상태 불필요, 가볍고 단순 효과용
- InstancedPerActor : 액터마다 별도 상태 필요, 네트워크 동기화에 적합(가장 일반적)
- InstancedPerExecution : 발동마다 개별 데이터 필요, 여러 번 동시 발동 가능
'UE5 > GAS' 카테고리의 다른 글
어빌리티 태스크 (AT)의 활용 (1) | 2025.06.10 |
---|---|
GAS 캐릭터 입력 처리 (0) | 2025.06.07 |
GAS 시스템 시작 (0) | 2025.05.23 |
GAS 어빌리티 시스템 컴포넌트-ASC (0) | 2025.05.09 |
[GAS] 언리얼 게임플레이 어빌리티 시스템 개요 (UE GAS Overview) (1) | 2025.04.26 |