인프런 : https://www.inflearn.com/course/%EC%9D%B4%EB%93%9D%EC%9A%B0-%EC%96%B8%EB%A6%AC%EC%96%BC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-part-4/dashboard

Udemy : https://www.udemy.com/course/unreal-engine-5-gas-top-down-rpg/

추가 문서 : https://kkadalg.tistory.com/29

command list

- showdebug abilitysystem

  - PageUp/Down으로 ASC를 가진 객체들을 순환할 수 있음

  -> DefaultGame.ini에서 [/Script/GameplayAbilities/AbilitySystemGlobals] bUseDebugTargetFromHud=True로 해줘야 AI도 보임

 

1. ASC ( AbilitySystemComponent )

- Actor에 interface 설정 : public IAbilitySystemInterface

- ASC . InitAbilityActorInfo( 실 소유자, 시각효과 발현자 ) ( possessed시(server), onrep_playerstate시(client) )

   -> 실 소유자의 owner는 항상 playercontroller야 함 ( playerstate owner는 항상 controller, pawn은 possess시 controller )

- ASC . TryActivateAbility, CancelAbilityHandle ( FGameplayAbilitySpec* . Handle )

- 접근 - UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent( 소유 액터 )

- 외부에서는 GetGameplayAttributeValueChangeDelegate() 같은걸로 attribute change noti delegate를 구독할 수있음

- SetReplicationMode Minimal AI용, Mixed 플레이어용, Full 싱글플레이어용

  Use Case GE Tag, Cue
Full Single o o
Mixed Multi, PlayerControlled owner-only o
Minimal Multi, AI-Controlled x o

 

2. GA ( GamePlayAbility )

- 액션단위

- ASC에선 FGameplayAbilitySpec* 으로 액션에 대한 instance를 제어 ( . handle을 통해 asc에서 내부 function에 접근 )

- FGameplayAbilitySpec* .. = ASC . FindAbilitySpecFromClass ( {GamePlayAction.child}::StaticClass() ) 로 생성

  - InstancingPolicty ( * 꼭 설정해줄것. default가 InstancedPerExecution )

     - NonInstanced : 인스턴싱 없이 CDO에서 일괄 처리, 단순, 상태부여는 어렵

     - InstancedPerActor : 액터마다 인스턴스. 고유스테이트 - 일반적

     - InstancedPerExecution : 어빌리티 발동시마다 인스턴스 발동. 액션마다 스테이트

 - 폰들 ( ASC의 owner 및 avatar )에 대해선 각 메서드 super에서 parameter로 받는 ActorInfo 내에 owner, avatar를 통해 접근 가능

 - GA를 상속받은 BP에서 각 State ( override )에서의 GameplayTag를 정의할 수 있음

 

3. GameplayTag

- #include "GameplayTagContainer.h"

- DefaultGameplayTags.ini에 생성 및 관리

- 계층구조를 가지는 태그 ( ex Actor . Action . Rotate )

- 쿼리검색 -> HasTagExact, HasAny, HasAnyExact, HasAll, HasAllExact 등

- Gameplay Ability System에서 사전정의된 태그리스트가 있음

  - AbilityTags 태그컨테이너

  - CancelAbilitiesWithTag 태그 컨테이너 등 ( BlockAbilitiesWithTag, ActivationOwnedTags, ActivationRequiredTags ... )

- 파라미터로 사용할 Tag의 포인터는 FGameplayTag::RequestGameplayTag(FName("태그이름")) 으로 얻음

   ( FGameplayTagContainer 타입 )

 

4. 기본 Architecture

- GA에 AbilityTags.AddTag로 어빌리티 태그 할당, ActivationOwnedTags로 상태태그 추가

- ASC -> GiveAbility를 통해 ASC에 해당 GA 추가

  ( FGameplayAbilitySpec ..(GA)를 GiveAbility에 박음. FGASpec이 GA 매니저인듯 )

- ASC -> TryActivateAbilititesByTag나 CancelAbilities 를 통해 Tag로 GA 트리거

 

5. GASpec ( Gameplay Ability Spec )

- ASC에서 GA를 관리할때 사용하는 중간매개체 ( 정확히는 GASpec의 Handle을 통해 관리 )

- 추가적인 메타데이터, 설정값을 포함

- GA의 상태 등에 대해 가져올 수 있음

- Handle값은 전역이며, 스펙생성시 1씩증가 ( 기본값 -1 )

- GA의 instance에 in32 InputID를 할당하고 ASC에서 ID를통해 접근할 수 있음 ( FindAbilitySpecFromInputID )

    -> GA가 발동중이면 입력신호전달 ( AbilitySpecInputPressed, 아니라면 발동 TryActivateAbility 하는 등 )

    -> 입력 release시 AbilitySpecInputReleased

 

6. AT ( Ability Task )

- NewAbilityTask < child class > ( owner GA ) 로 생성

- GA는 1frame내 동기처리가 기본

- animation과 타이밍 등 비동기적 요소가 포함된 스펙을 AT에서 관리

  - UAbilityTask_PlayMontageAndWait 등

    - 해당 태스크의 static 변수로 이닛 ( ex. CreatePlayMontageAndWaitProxy )

    - OnComplated 등에 AddDynamic으로 콜백함수 연결하고 ( GA의 ActivateAbility 메서드 시점에서 AT의 델리게이트를 GA 콜백함수에 연결 )

    - FreadyForActivation();으로 실행개시

    - 필요시 콜백함수에서 GA의 EndAbility ( GA종료 ) 호출

    - MontageJumpToSection 등 내장된 편의기능이 많음 ( GA )

 - 시작 : Activate ( override ) , 종료 : OnDestroy ( override )

 - static method에서 NewAbilityTask < AT class(보통자신) > ( GA ) 넣어서 해당 ga용 특정 at 생성 가능

 - 얘넨 그냥 GetAvatarActor 가지고있네 내장함수로

 

예제에서는 EnhancedInputSystem에서 IA에 Callback함수를 binding할 때, 같은 Callback을 바인딩하고 input param에 GA의 Id를 줘서 하나의 callback 함수로 여러 input(IA) -> action(GA)을 바인딩하고있음

 

7. GE ( Gameplay Event )

- ( Anim Notify등에서 ) Actor(보통 캐릭터)의 가상함수에

FGameplayEventData PayloadData;
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(OwnerActor, TriggerGameplayTag, PayloadData);

  를 보낼 수 있음. TriggerGameplayTag는 블프나 notify detail에서 할당해도되고, 코드에 직접박아도 되고

그리고 액터의 ASC에 GA를 바인딩한 다음, GA의 AbilityTriggers ( TArray<FAbilityTriggerData>)에 해당 TriggerGameplayTag를 등록

  - 등록은 걍 BP에서 하는게 편함

 

8. TA ( GameplayAbilityTargetActor )

- StartTagetting -> ConfirmTargeting(AndContinue), CancelTargeting 등

- 타켓 판정 및 관리 ( line trace, collision trace 등 )

  - Target Data Handle에서 Target Data들을 묶어서 전달

- SpawnActorDeffered로 지연생성하고, 델리게이트 구독 등 초기화 별도로 해줌 ( AT에서 )

   -> FinishSpawning -> StartTargetting(in Ability) -> ConfirmTargeting

- Start에서 SourceActor에 타격판정할 액터 등록 // #If Enable Draw Debug

 

9. Attribute Set

- GameplayAttributeData : 단일 프로퍼티

   - Base Value

   - Current Value : 버프등으로 인한 변동값

- ASC는 등록될 때, Owner에있는 Attribute Set 객체들을 자동으로 등록함 ( ASC variable과 동일한 클래스 내에서 )

   -> 그냥 variable 선언하고, CreateDefaultSubobject로 할당하면됨

   -> ASC->GetSet<class>()

- Attribute Set class 안에있는 매크로 참조하여 사용. 아래쪽에 전처리#def 해서 getter, setter, inniter 자동생성 매크로 있음

#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
    GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
ATTRIBUTE_ACCESSORS(UABCharacterAttributeSet, AttackRange);

- PreAttributeChange, PostAttributeChange등의 가상함수를 제공

- MetaAttribute

   - 확장성을 위해 중간단계에 추상성 계산단계를 추가

   - ex. 공격로직을 hp에 직접 적용하지 않고 공격로직 -> Damage attritue -> hp attribute 등 ( 회복, 쉴드 등 추가개념 확장을 위해. 데미지는 음수가된다고 회복처리가 아니어야 함 )

 - PostGameplayEffectExecution 함수에는 Effect에 의해 Modi된 값이 들어옴

 - delegate 선언 시 mutable 선언을 통해서 const를 뺀 get/set에 접근

 - Data.Target.AddLosseGameplayTag로 태그추가가능

 

10. GE ( Gameplay Effect )

- GA에서 MakeOutgoingGameplayEffectSpec(GE클래스) 만들어서 핸들러로 사용

  -> ApplyGameplayEffectSpecToTarget

- 기본타입(DurationPolicy) : instant, duration, infinite

- 모디파이어로 어트리뷰트 변형방법을 지정 ( 혹은 GameplayEffectExecutionCalculation을 통해 커스텀 )

   -> .Attribute, .ModifierOp -> FGameplayEffectModifierMagnitude타입 변수를 생성 -> [Modifier].ModifierManitude = 해당변수

   -> MagnitudeType - Custom Calc Class  : Gameplay Mod Magnitude Calculator를 참조

- 로직보단 세팅위주여서 BP를 권장

- DataTag를 통해서도 호출가능

 ( GE에 DataTag 등록 -> EffectSpecHandle.Data->SetSetbyCallerMagnitude(태그, attribute ), 다음 apply )

- GEContext : 정보를 담은 객체 ( instigator, causer, hit result 등 )

- GESpec : GE관련 정보 ( level, modifier, tag, context handle 등 )

 -> GESpecHandle -> GESpec -> GEContextHandle -> GEContext ( GA없이 ASC가 직접 접근도 가능 )

 -> 그래서 GEContext만들고, handle만든다음, 해당핸들을 param으로 GESpec 생성하고, GESpecHandle 생성

FGameplayEffectContextHandle EffectContextHandle = ASC->MakeEffectContext();
EffectContextHandle.AddSourceObject(this);
FGameplayEffectSpecHandle EffectSpecHandle = ASC->MakeOutgoingSpec(InitStatEffect, Level, EffectContextHandle);
if (EffectSpecHandle.IsValid())
{
    ASC->BP_ApplyGameplayEffectSpecToSelf(EffectSpecHandle);
}

- type이 Instance거나, bisPeriod = true인 경우에는 base value를 바꾸지만, 아닌 경우에는 current value 변경(버프취급)

 

11. GC ( Gameplay Cue )

- VFX나 SFX같이 로직과 상관없는 애들

  - Static GC 순간발생

  - Actor GC 기간발생

- Tag를 통해 발동시킬떄는, GameplayCue로 시작하는 태그를 사용해야 함

- GA에서 GCParam을 만들고, 해당파람.EffectContext에 GEContextHandle을 주입 -> ASC->ExecutecuteGameplayCue()

 

 

 

 

ps.

float 유효범위 정의 : FString::Printf(TEXT("%.0f / %0.f"), float, float)

'Unreal > UE Architecture' 카테고리의 다른 글

Unreal Interface  (0) 2024.06.16
Cpp -> BP Pipeline 1  (0) 2024.05.17
문자열 처리  (0) 2024.05.16
UE Macro & Reflection System  (0) 2024.05.16
Smart Pointer & Container & Serialize  (0) 2024.05.16

+ Recent posts