언리얼엔진5 GAS-점프 GameAbility 적용

조창근·2024년 6월 26일
0

언리얼엔진5 GAS

목록 보기
4/8
post-thumbnail


AbilitySystemComponent와 가장 먼저 상호작용하는 GamePlayAbility를 알아보도록 하겠습니다.
먼저 UGamePlayAbility를 상속받아 사용해야 하므로 UGamePlayAbility.h를 보면 중요한 함수들이라고 설명이 써져있는 것을 볼 수 있습니다.

먼저 알면 좋을 중요한 함수들:

CanActivateAbility(): 어빌리티를 활성화할 수 있는지 확인하는 함수입니다.

TryActivateAbility(): 어빌리티를 활성화하려고 시도합니다. CanActivateAbility()를 호출합니다. 입력 이벤트가 이 함수를 직접 호출할 수 있습니다. 실행 시 인스턴스화 논리 및 복제/예측 호출도 처리합니다.

CallActivateAbility(): 보호된 비가상 함수입니다. 일부 '사전 활성화' 작업을 수행한 다음 ActivateAbility()를 호출합니다.

ActivateAbility(): 어빌리티를 실제로 수행하는 함수입니다.이를 통해 어빌리티가 실행됩니다.

CommitAbility(): 자원/쿨다운 등을 커밋합니다. ActivateAbility()는 이 함수를 호출해야 합니다.

CancelAbility(): 외부 소스에서 어빌리티를 중단합니다.

EndAbility(): 어빌리티를 종료하기 위해 호출되는 것이 의도된 함수입니다.

UGameplayAbility_CharacterJump

언리얼 엔진에서는 UGameplayAbility_CharacterJump라는 UGamePlayAbility를 상속받은 함수를 제공해줍니다.
이를 분석하고 UGameplayAbility_CharacterJump를 AbilitySystemComponent에 적용해보도록 하겠습니다.

class GAMEPLAYABILITIES_API UGameplayAbility_CharacterJump : public UGameplayAbility
{
	GENERATED_UCLASS_BODY()

public:

	virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;

	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* OwnerInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;

	virtual void InputReleased(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) override;

	virtual void CancelAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateCancelAbility) override;
};

헤더파일을 확인해보면 위의 중요코드를 사용하는 것을 확인해 볼 수 있습니다.

ActivateAbility()분석

void UGameplayAbility_CharacterJump::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	
	if (HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo))
	{
		if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
		{
			return;
		}

		ACharacter * Character = CastChecked<ACharacter>(ActorInfo->AvatarActor.Get());
		Character->Jump();
	}
}

ActivateAbility()의 매개 변수

1. const FGameplayAbilitySpecHandle Handle:

이 핸들은 특정 능력 인스턴스를 식별합니다. 게임플레이 어빌리티 시스템은 여러 인스턴스의 능력을 관리할 수 있으며, 이 핸들을 통해 해당 인스턴스를 구별할 수 있습니다.

2. const FGameplayAbilityActorInfo ActorInfo*:

이 구조체는 능력을 활성화하는 액터에 대한 정보를 담고 있습니다. 여기에는 액터의 컨트롤러, 폰, 스킬 시스템 컴포넌트 등이 포함됩니다. 이를 통해 능력을 사용할 때 관련된 액터의 정보를 쉽게 접근할 수 있습니다.

3. const FGameplayAbilityActivationInfo ActivationInfo:

이 구조체는 능력이 어떻게 활성화되었는지에 대한 정보를 담고 있습니다. 예를 들어, 능력이 인풋에 의해 활성화되었는지, 자동으로 활성화되었는지 등의 정보를 포함합니다.

4. const FGameplayEventData TriggerEventData:

이 포인터는 능력을 트리거한 이벤트에 대한 추가 데이터를 포함할 수 있습니다. 이는 특정 이벤트가 능력을 트리거할 때 추가적인 컨텍스트 정보를 전달하기 위해 사용됩니다.

이를 통해 다양한 능력을 만들어 줄 수 있습니다.

사용된 함수 내용을 보면

1. HasAuthorityOrPredictionKey(ActorInfo, &ActivationInfo)

bool UGameplayAbility::HasAuthorityOrPredictionKey(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo* ActivationInfo) const
{
	return ActorInfo->AbilitySystemComponent->HasAuthorityOrPredictionKey(ActivationInfo);
}

bool UAbilitySystemComponent::HasAuthorityOrPredictionKey(const FGameplayAbilityActivationInfo* ActivationInfo) const
{
	return ((ActivationInfo->ActivationMode == EGameplayAbilityActivationMode::Authority) || CanPredict());
}

namespace EGameplayAbilityActivationMode
{
	enum Type : int
	{
		클라이언트 또는 서버가 이 능력을 활성화할 권한을 가지고 있는 상태를 나타냅니다.
		Authority,

		...
	};
}

위와 같이 Actorinfo의 어빌리티시스템컴포넌트의 HasAuthorityOrPredictionKey()함수를 통해
ActivationInfoActivationModeAuthority이면 true를 반환하는 것을 알 수 있습니다.

2. CommitAbility()

bool UGameplayAbility::CommitAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, OUT FGameplayTagContainer* OptionalRelevantTags)
{
	// Last chance to fail (maybe we no longer have resources to commit since we after we started this ability activation)
	if (!CommitCheck(Handle, ActorInfo, ActivationInfo, OptionalRelevantTags))
	{
		return false;
	}

	CommitExecute(Handle, ActorInfo, ActivationInfo);

	// Fixme: Should we always call this or only if it is implemented? A noop may not hurt but could be bad for perf (storing a HasBlueprintCommit per instance isn't good either)
	K2_CommitExecute();

	// Broadcast this commitment
	ActorInfo->AbilitySystemComponent->NotifyAbilityCommit(this);

	return true;
}

  1. CommitCheck(): 어빌리티의 커밋 여부 확인
  2. CommitExecute(): CooldownEffect나 CostEffect가 있으면 이펙트를 Owner에게 적용
  3. 엑터의 어빌리티시스템컴포넌트에 해당어빌리티를 알림

3. Character->Jump();

마지막으로 ActorInfo->AvatarActor.Get()를 통해 Character->Jump()로 캐릭터 점프를 진행해주게 됩니다.

Jump 어빌리티 적용

class SOULLIKE_API ASoulLikeCharacter : public ACharacter, public IAbilitySystemInterface
{
	...
    
	public:
	UPROPERTY(EditAnywhere, Category = GAS)
	TMap<int32, TSubclassOf<class UGameplayAbility>> StartInputAbilities;

}

EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this,  &ASoulLikeCharacter::GASInputPressed, 0);
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ASoulLikeCharacter::GASInputReleased, 0);
  1. 캐릭터에게 점프 어빌리티와 인풋번호(0)를 적용
  2. 인풋컴포넌트에 점프액션키와 0번을 바인드
  3. 게임 플레이 확인

0개의 댓글