게임플레이 어빌리티 시스템(Gameplay Ability System)과 상호작용하는 액터에는 보통 숫자 프로퍼티 세트가 있어야 이를 시스템에서 액세스 및 수정하여 게임플레이 로직에 영향을 주고 게임에서 벌어진 일을 추적할 수 있습니다. 이 프로퍼티를 일컬어 게임플레이 어트리뷰트(Gameplay Attribute) 또는 줄여서 '어트리뷰트'라 하며, 게임플레이 이펙트(Gameplay Effect) 에 의해 일시적 또는 영구적으로 수정됩니다.
언리얼 엔진 프로젝트에서 이를 구성하는 방법은 액션 RPG 문서의 샘플 및 튜토리얼 부분을 참조하세요.
게임플레이 어트리뷰트
게임플레이 어트리뷰트 에는 단일 부동 소수점 값으로 설명할 수 있는 액터의 현재 상태에 대한 모든 측정치가 포함되어 있습니다. 예를 들면 체력 포인트, 신체적인 힘, 이동 속도, 마법 저항력 등이 있습니다. 어트리뷰트는 어트리뷰트 세트(Attribute Sets) 안에 FGameplayAttribute 타입 UProperties로 선언합니다. 이 세트는 어트리뷰트를 포함할 뿐만 아니라 어트리뷰트 수정 시도를 감독합니다.
어트리뷰트와 어트리뷰트 세트는 네이티브 코드로 생성해야 하며, 블루프린트로는 생성할 수 없습니다.
어트리뷰트 세트 생성
어트리뷰트 세트를 생성하려면, UAttributeSet 에서 상속한 후 UPROPERTY 태그가 달린 게임플레이 어트리뷰트 데이터 멤버를 추가합니다. 예를 들어 '체력(Health)' 어트리뷰트만 포함된 어트리뷰트 세트는 다음과 같습니다.
UCLASS()
class USimpleAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
/** 디폴트값을 설정합니다. 예를 들어, 체력은 양수로 설정해야 합니다. */
USimpleAttributeSet();
/** 사망 전까지 흡수할 수 있는 대미지 양을 측정합니다. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Health;
};
최소 어트리뷰트 세트로, 단일 어트리뷰트가 포함되어 있습니다.
어트리뷰트 세트를 생성했다면, 어빌리티 시스템 컴포넌트로 등록해야 합니다. 이를 위해서는 어트리뷰트 세트를 어빌리티 시스템 컴포넌트의 소유 액터의 서브오브젝트로 추가하거나, 어빌리티 시스템 컴포넌트의 GetOrCreateAttributeSubobject 함수에 전달해야 합니다.
게임플레이 이펙트
게임플레이 이펙트(Gameplay Effect)는 게임플레이 어빌리티 시스템에서 어트리뷰트를 변경하는 방식입니다. 다음과 같은 게임플레이 이펙트가 있습니다.
- 어트리뷰트의 베이스 값 직접 변경: 대미지를 받은 액터에서 체력 포인트를 줄이는 것 등이 있습니다.
- '버프' 또는 '디버프'라고도 불리는 임시 변경: 몇 초 동안 이동 속도에 대한 부스트를 부여하는 것 등이 있습니다.
- 시간 경과에 따라 적용되는 영구 변경: 몇 초 동안 (또는 무한히) 초당 특정량의 마나를 재생하는 것 등이 있습니다.
게임플레이 이펙트는 베이스 클래스가 UGameplayEffect 인 데이터 전용 블루프린트로 구현하여 어빌리티 시스템 컴포넌트와 상호작용하고 적절한 경우 활성 상태인 동안 저장될 수 있습니다.
주요 프로퍼티
게임플레이 이펙트는 게임플레이 어빌리티 시스템의 다른 대부분의 요소와 달리 보통 UGameplayEffect 베이스 클래스를 네이티브로도 블루프린트 코드로도 오버라이드하지 않습니다. 대신 게임플레이 이펙트는 순전히 변수를 통해 환경설정하도록 설계되었습니다. 다음은 조정할 수 있는 게임플레이 이펙트의 주요 프로퍼티 중 일부입니다.
- 기간(Duration): 게임플레이 이펙트 적용은 즉시 이루어지거나(공격받을 때의 체력 감소), 제한된 시간 동안 이루어지거나(몇 초 동안 지속되는 이동 속도 부스트), 무한으로 이루어집니다(시간 경과에 따라 자연스럽게 재생되는 캐릭터의 마나). 또한 기간이 즉시가 아닌 이펙트는 간격을 다르게 해서 적용할 수도 있습니다. 이는 게임플레이 측면에서 이펙트의 작동 방식 변경에 유용할 뿐만 아니라, 오디오 또는 비주얼 이펙트 반복과 같은 타이밍 구성에도 좋습니다.
- 모디파이어 및 실행(Modifiers and Executions): 모디파이어(Modifiers)는 게임플레이 이펙트가 어트리뷰트와 상호작용하는 방식을 결정합니다. 여기에는 '방어력 5퍼센트 상승'과 같은 어트리뷰트 자체에 대한 수학적 인터랙션은 물론, 이펙트 실행에 필수인 게임플레이 태그도 포함됩니다. 게임플레이 이펙트에 모디파이어가 지원하는 것 이상의 무언가가 필요할 때는 실행(Executions)이 도움이 될 수 있습니다. 실행은
UGameplayEffectExecutionCalculation을 사용하여 실행 시 게임플레이 이펙트가 가질 커스텀 비헤이비어를 정의합니다. 모디파이어로는 충분히 커버할 수 없는 복잡한 방정식을 정의할 때 특히 유용합니다. - 적용 요건(Application Requirements): 적용 요건은 여기에 포함된 게임플레이 태그 세트가 있어야 (또는 없어야) 게임플레이 이펙트를 적용하도록 하거나, 랜덤으로 게임플레이 이펙트를 적용하지 않도록 할 수 있습니다. 이러한 요건이 게임의 니즈를 충족하지 않으면
UGameplayEffectCustomApplicationRequirement베이스 클래스에서 데이터 오브젝트를 파생한 뒤, 거기에 복잡한 적용 규칙을 임의로 정의하는 네이티브 코드를 작성할 수 있습니다. - 부여된 어빌리티(Granted Abilities): 게임플레이 이펙트는 적용되면 게임플레이 태그뿐만 아니라 어빌리티도 부여할 수 있습니다. '실행'과 함께 사용하면 매우 구체적인 게임플레이 조합을 구성할 수 있습니다. 예를 들어 화염 테마의 게임플레이 이펙트에 액터가 맞았는데, 그 액터가 기름에 젖었음을 나타내는 게임플레이 태그 또는 어트리뷰트가 있는 상태였다면, '불타오름(On Fire)' 어빌리티를 얻으면서 다음 10초 동안 주변 액터에게 수동 대미지를 입히고 파티클 및 다이내믹 라이트가 있는 비주얼 이펙트가 나타나는 식입니다.
- 스태킹(Stacking): 이미 어떤 버프 또는 디버프(이 경우 게임플레이 이펙트)를 가진 대상에게 해당 버프 또는 디버프를 다시 적용하고, 오버플로(Overflow) 상황을 처리하는 정책을 가리킵니다. 오버플로란 원래 타깃에 적용되어 있던 게임플레이 이펙트가 포화 상태에 달하면 새로운 게임플레이 이펙트가 적용되는 것을 말합니다. 예를 들어, 중독 게이지가 계속 누적되다가 오버플로가 된 후에만 독 지속 대미지를 입히는 경우입니다. 시스템에서 지원하는 스태킹 비헤이비어는 다양합니다. 한계치를 넘을 때까지 중첩되게 하거나, 새로 적용할 때마다 늘어나는 '스택 수'를 최대 한도까지 유지하도록 하거나, 시간이 제한된 이펙트의 시간이 리셋 또는 추가되도록 하거나, 단순히 이펙트의 여러 인스턴스에 개별 타이머를 독립적으로 적용할 수도 있습니다.
-
게임플레이 큐 디스플레이(Gameplay Cue Display): 게임플레이 큐(Gameplay Cues)** 는 파티클이나 사운드 같은 장식 이펙트를 관리하는 네트워크 효율적인 방식으로, 게임플레이 어빌리티 시스템으로 제어할 수 있습니다. 게임플레이 큐는 게임플레이 어빌리티 및 게임플레이 이펙트로 트리거할 수 있으며, 네이티브 또는 블루프린트 코드로 오버라이드할 수 있는 4개의 메인 함수인 활성화 시(On Active), 활성화 동안(While Active), 제거됨(Removed), 그리고 게임플레이 이펙트에만 사용되는 실행됨(Executed)을 통해 작동합니다. 모든 게임플레이 큐에는 'GameplayCue'로 시작하는 게임플레이 태그를 붙여 'GameplayCue.ElectricalSparks'나 'GameplayCue.WaterSplash.Big'과 같은 형태가 되어야 합니다.
게임플레이 큐 매니저(Gameplay Cue Manager) 는 게임플레이 큐를 실행합니다.
IGameplayCueInterface를 구현하고 게임플레이 큐의 태그와 이름이 동일한 함수가 있는 액터는 게임플레이 큐에 반응할 수 있습니다. 독립형 게임플레이 큐 알림(Gameplay Cue Notify) 블루프린트 역시 게임플레이 큐에 반응할 수 있습니다.
이펙트 및 어트리뷰트 인터랙션 프로그래밍
게임플레이 이펙트가 어트리뷰트를 수정하려고 시도하는 경우 어트리뷰트가 반응하는 방식을 처리하기 위해 어트리뷰트 세트가 오버라이드할 수 있는 여러 함수가 있습니다. 예를 들어 USimpleAttributeSet 샘플의 'Health' 어트리뷰트는 부동 소수점 값을 저장할 수 있고, 게임플레이 어빌리티 시스템이 그 값에 액세스하거나 변경할 수 있지만, 체력이 0으로 떨어져도 실제로는 아무런 일도 발생하지 않으며 체력이 0 미만으로 떨어지는 것을 방지할 수도 없습니다. 'Health' 어트리뷰트가 원하는 대로 작동하도록 하려면 어트리뷰트 세트 자체에서 어트리뷰트에 대한 수정 시도를 처리하는 여러 가상 함수를 오버라이드하면 됩니다. 어트리뷰트 세트가 흔히 오버라이드하는 함수는 다음과 같습니다.
| 함수 이름 | 목적 |
|---|---|
PreAttributeChange / PreAttributeBaseChange |
어트리뷰트 수정 직전에 호출되는 함수입니다. 'Health 값은 0과 MaxHealth 사이여야 한다'와 같이 어트리뷰트의 값에 대한 규칙을 강제하기 위한 것으로, 어트리뷰트 변경사항에 대한 게임 내 반응을 트리거하지 않습니다. |
PreGameplayEffectExecute |
이 함수는 어트리뷰트의 값 수정 직전 제안된 수정을 거부하거나 변경할 수 있습니다. |
PostGameplayEffectExecute |
이 함수는 어트리뷰트의 값 수정 직후 변경사항에 반응할 수 있습니다. 보통 어트리뷰트 최종 값에 대한 범위 제한이나, 'Health' 어트리뷰트가 0으로 떨어지면 사망하는 것과 같이 새 값에 대한 게임 내 반응 트리거가 포함됩니다. |