다양한 기록

[Unreal GAS] Implementing Combo Action 본문

언리얼 엔진/Unreal Ability System

[Unreal GAS] Implementing Combo Action

라구넹 2025. 1. 12. 20:42

헤더에서 콤보에서 쓸 함수 및 변수 선언

void UABGA_Attack::CheckComboInput()
{
	ComboTimerHandle.Invalidate();
	if ( HasNextComboInput )
	{
		MontageJumpToSection(GetNextSection());
		StartComboTimer();
		HasNextComboInput = false;
	}
}

다른 건 별 차이 없고, MontageJumpToSection 이라는 걸 지원해서 AnimInstance 가져올 필요 없음

 

 

콤보 액션 잘 됨

 

 

상태를 가지는 점프 구현

* 어빌리티 태스크(AT)의 제작 규칙

- AT는 UAbilityTask 클래스를 상속받아 제작

- AT 인스턴스를 생성해 반환하는 static 함수를 선언해 구현

- AT가 종료되면 GA에 알려줄 델리게이트를 선언

- 시작과 종료 처리를 위해 Activate와 OnDestroy 함수를 재정의해 구현

- 일정 시간이 지난 후 AT를 종료하고자 한다면 활성화 시 SetWatingOnAvatar 함수를 호출해 Wating 상태로 설정

- 만일 Tick을 활성화하고 싶다면 bTickingTask 값을 true로 설정

- AT가 종료되면 델리게이트를 브로드캐스팅

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Abilities/Tasks/AbilityTask.h"
#include "ABAT_JumpAndWaitForLanding.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FJumpAndWaitForLandingDelegate);

/**
 * 
 */
UCLASS()
class ARENABATTLEGAS_API UABAT_JumpAndWaitForLanding : public UAbilityTask
{
	GENERATED_BODY()
	
public:
	UABAT_JumpAndWaitForLanding();

	static UABAT_JumpAndWaitForLanding* CreateTask(UGameplayAbility* OwningAbility);

	virtual void Activate() override;
	virtual void OnDestroy(bool AbilityEnded) override;

	FJumpAndWaitForLandingDelegate OnComplete;

protected:
	UFUNCTION()
	void OnLandedCallback(const FHitResult& Hit);
};

점프 어빌리티 태스크 헤더

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "GA/AT/ABAT_JumpAndWaitForLanding.h"
#include "GameFramework/Character.h"

UABAT_JumpAndWaitForLanding::UABAT_JumpAndWaitForLanding()
{
}

UABAT_JumpAndWaitForLanding* UABAT_JumpAndWaitForLanding::CreateTask(UGameplayAbility* OwningAbility)
{
	UABAT_JumpAndWaitForLanding* NewTask = NewAbilityTask<UABAT_JumpAndWaitForLanding>(OwningAbility);
	return NewTask;
}

void UABAT_JumpAndWaitForLanding::Activate()
{
	Super::Activate();
	ACharacter* Character = CastChecked<ACharacter>(GetAvatarActor());
	Character->LandedDelegate.AddDynamic(this, &UABAT_JumpAndWaitForLanding::OnLandedCallback);
	Character->Jump();

	SetWaitingOnAvatar();
}

void UABAT_JumpAndWaitForLanding::OnDestroy(bool AbilityEnded)
{
	ACharacter* Character = CastChecked<ACharacter>(GetAvatarActor());
	Character->LandedDelegate.RemoveDynamic(this, &UABAT_JumpAndWaitForLanding::OnLandedCallback);
	Super::OnDestroy(AbilityEnded);
}

void UABAT_JumpAndWaitForLanding::OnLandedCallback(const FHitResult& Hit)
{
	if ( ShouldBroadcastAbilityTaskDelegates() )
	{
		OnComplete.Broadcast();
	}
}

SetWaitingOnAvatar 해줘야 함

점프가 언제 끝날지 모르기 때문

대신 LandedDelegate가 캐릭터에서 자체적으로 지원되는데, 거기에 콜백 넣어서 OnComplete 브로드캐스트

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Abilities/GameplayAbility.h"
#include "ABGA_Jump.generated.h"

/**
 * 
 */
UCLASS()
class ARENABATTLEGAS_API UABGA_Jump : public UGameplayAbility
{
	GENERATED_BODY()
	
public:
	UABGA_Jump();

	virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
	virtual void InputReleased(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) override;
	virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;

protected:
	UFUNCTION()
	void OnLandedCallback();
};

점프 게임 어빌리티 헤더

 

// Fill out your copyright notice in the Description page of Project Settings.


#include "GA/ABGA_Jump.h"
#include "GameFramework/Character.h"
#include "GA/AT/ABAT_JumpAndWaitForLanding.h"

UABGA_Jump::UABGA_Jump()
{
	InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
}

void UABGA_Jump::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
	UABAT_JumpAndWaitForLanding* JumpAndWaitForLandingTask = UABAT_JumpAndWaitForLanding::CreateTask(this);
	JumpAndWaitForLandingTask->OnComplete.AddDynamic(this, &UABGA_Jump::OnLandedCallback);
	JumpAndWaitForLandingTask->ReadyForActivation();
}

void UABGA_Jump::InputReleased(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo)
{
	ACharacter* Character = CastChecked<ACharacter>(ActorInfo->AvatarActor.Get());
	Character->StopJumping();
}

bool UABGA_Jump::CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, OUT FGameplayTagContainer* OptionalRelevantTags) const
{
	bool bResult = Super::CanActivateAbility(Handle, ActorInfo, SourceTags, TargetTags, OptionalRelevantTags);

	if ( !bResult )
	{
		return false;
	}

	const ACharacter* Character = Cast<ACharacter>(ActorInfo->AvatarActor.Get());

	return Character && Character->CanJump();
}

void UABGA_Jump::OnLandedCallback()
{
	bool bReplicatedEndAbility = true;
	bool bWasCancelled = false;
	EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, bReplicatedEndAbility, bWasCancelled);
}

ActivateAbility에서 어빌리티 태스크 만들고 델리게이트 등록

실행하면 정상 작동 확인 가능

 

* 블루프린트에서 호출을 위한 제작 규칙

- static 함수에 UFUCNTION(BlueprintCallable)을 지정

- 콜백을 위한 델리게이트는 Dynamic Delegate로 선언

- AT의 델리게이트에 UPROPERTY(BlueprintAssignable) 지정

 

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Abilities/Tasks/AbilityTask.h"
#include "ABAT_JumpAndWaitForLanding.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FJumpAndWaitForLandingDelegate);

/**
 * 
 */
UCLASS()
class ARENABATTLEGAS_API UABAT_JumpAndWaitForLanding : public UAbilityTask
{
	GENERATED_BODY()
	
public:
	UABAT_JumpAndWaitForLanding();
	UFUNCTION(BlueprintCallable, Category = "Ability|Tasks", meta = (DisplayName = "JumpAndWaitForLanding", HidePin = "OwningAbility", DefaultToSelf = "OwningAbility", BlueprintInternalUseOnly = "TRUE"))
	static UABAT_JumpAndWaitForLanding* CreateTask(UGameplayAbility* OwningAbility);

	virtual void Activate() override;
	virtual void OnDestroy(bool AbilityEnded) override;

	UPROPERTY(BlueprintAssignable)
	FJumpAndWaitForLandingDelegate OnComplete;

protected:
	UFUNCTION()
	void OnLandedCallback(const FHitResult& Hit);
};

어빌리티 태스크에서 CreateTask에 UFUCNTION, OnComplete에 UPROPERTY 지정

어빌리티에서 태스크 만드는 건 주석처리 해주고

블루프린트에서 설정

 

Activation Blocked Tags 지정

이미지대로면 공격 중일 때 점프 불가

반대도 어빌리티 가서 설정해주면 됨

'언리얼 엔진 > Unreal Ability System' 카테고리의 다른 글

[Unreal GAS] Character Input Handling  (0) 2025.01.12
[Unreal GAS] 개요  (0) 2025.01.11