UE5でFPSゲーム制作 Part7-ダッシュ

ダッシュ

ダッシュをGASで実装するためには、AttributeクラスとGameplay Effectクラスが必要になります。

 

このあたりは内容が非常に難しく実装方法だけ記述しているので、ちゃんと理解されたい方は自分が参考にした記事を載せておきます。

参考にしたブログ様

GameplayAbilitiesの使い方(アトリビュートセット・エフェクト編) - おかわりはくまいのアンリアルなメモ (hatenablog.com)

GAS入門 その4 グレイマン疲れさせよう - FutureSoftware UnrealEngine Study BLOG

UE4 C++ GameplayAbilitiesを勉強していくPart.2 AttributeSetとGameplayEffect - pto8913のメモ帳 (hatenablog.com)

 

新規C++クラスからAttributeSetクラスを選択し、TutoAttributeSetと名付けます。

TutoAttributeSet.h
#pragma once

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "TutoAttributeSet.generated.h"

// AttributeSet.hで紹介されているアトリビュートへのSetter,Getter定義マクロ
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
		GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
		GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

UCLASS()
class TUTORIALFPS_API UTutoAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
	
public:
	UTutoAttributeSet();

	// Blueprintアクセス可能としたMaxSpeed定義、ATTRIBUTE_ACCESSORSによるアクセサ追記
	UPROPERTY(Category = "Attributes", EditAnywhere, BlueprintReadWrite)
		FGameplayAttributeData MaxSpeed;
	ATTRIBUTE_ACCESSORS(UTutoAttributeSet, MaxSpeed);
	FGameplayAttribute MaxSpeedAttribute();// アトリビュート型取得関数

	/** エフェクトによりアトリビュートが変化した場合のPost処理。主にUE5で直接管理しているメンバへの書き戻しを行う */
	virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
};
TutoAttribute.cpp
#include "TutoAttributeSet.h"
#include "GameplayEffectExtension.h"
#include "CharacterBase.h"

/** コンストラクタにより初期値設定 */
UTutoAttributeSet::UTutoAttributeSet()
	: MaxSpeed(400.0f)
{
}

// アトリビュート型取得関数
FGameplayAttribute UTutoAttributeSet::MaxSpeedAttribute()
{
	static FProperty* Property = FindFieldChecked<FProperty>(UTutoAttributeSet::StaticClass(), GET_MEMBER_NAME_CHECKED(UTutoAttributeSet, MaxSpeed));
	return FGameplayAttribute(Property);
}

void UTutoAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
	Super::PostGameplayEffectExecute(Data);

	// 受け取ったデータから各種情報を取得
	FGameplayEffectContextHandle Context = Data.EffectSpec.GetContext();
	UAbilitySystemComponent* Source = Context.GetOriginalInstigatorAbilitySystemComponent();
	const FGameplayTagContainer& SourceTags = *Data.EffectSpec.CapturedSourceTags.GetAggregatedTags();

	// GameplayEffectにより指定されたアトリビュート変化値を計算
	float DeltaValue = 0;
	if (Data.EvaluatedData.ModifierOp == EGameplayModOp::Type::Additive)
	{
		// If this was additive, store the raw delta value to be passed along later
		DeltaValue = Data.EvaluatedData.Magnitude;
	}

	// 受け取ったデータからターゲットアクター、コントローラ、キャラクタの取得
	AActor* TargetActor = nullptr;
	AController* TargetController = nullptr;
	ACharacterBase* TargetCharacter = nullptr;
	if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
	{
		TargetActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
		TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
		TargetCharacter = Cast<ACharacterBase>(TargetActor);
	}

	// 受け取ったデータがMaxSpeedだった場合にCharacter側の最大移動スピードに反映させる
	if (Data.EvaluatedData.Attribute == GetMaxSpeedAttribute())
	{
		if (TargetCharacter)
		{
			TargetCharacter->HandleMaxSpeedChanged(DeltaValue, SourceTags);
		}
	}
}
    

 

次にCharacterBaseにTutoAttributeSetをインクルードして中身を書いていきます。

CharacterBase.h

クラス内の全文

#include "TutoAttributeSet.h"

public:	
	/** AttributeSet */
	UPROPERTY()
		UTutoAttributeSet* AttributeSet;

	// アトリビュート変更時のキャラクタへの反映関数
	void HandleMaxSpeedChanged(float DeltaValue, const struct FGameplayTagContainer& EventTags);
CharacterBase.cpp

クラス内の全文

#include "GameFramework/CharacterMovementComponent.h"

ACharacterBase::ACharacterBase()
{
	// ability system component
	AbilitySystem = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));

	// create the attribute set
	AttributeSet = CreateDefaultSubobject<UTutoAttributeSet>(TEXT("AttributeSet"));
}

void ACharacterBase::HandleMaxSpeedChanged(float DeltaValue, const struct FGameplayTagContainer& EventTags)
{
	GetCharacterMovement()->MaxWalkSpeed = AttributeSet->GetMaxSpeed();
}

 

これでGameplay Effectを通じてキャラクターの移動速度を変更することができるようになりました。

次にBPでGameplay Effectを作成していきます。

新規ブループリントからGameplay Effectを選択してGE_MaxSpeedNormalと名付けます。

Duration PolicyをInstant、ModifilersのAttributeをTutoAttributeSet.MaxSpeedにします。

Modifiler OpはOverride、Modifiler MagnitudeでScalable Float、400.0にします。400.0が通常時の移動速度になります。

GE_MaxSpeedNormal

同じようにGE_MaxSpeedHigh(ダッシュ時のGE)を作成し、800にします。

GE_MaxSpeedHigh

 

次にGameplay AbilityからGA_Dashを作成します。

GA_Dash

Apply Gameplay Effect To OwnerはこのGAを使用した人にGameplayEffectを与えるノードです。

Activate AbilityノードからはGE_MaxSpeedHighを選択し、On End AbilityノードからはGE_MaxSpeedNormalを選択します。

Wait Gameplay Eventノードは次に指定されたTagがくるまでこのGAを実行し続けます。この場合はAbility.Action.Dash.Cancelというタグを受け取るまで実行することになります。

前回のジャンプと同じように入力アクションでIA_Jumpを作成します。Value TypeはDigital(bool)です。IMC_FPSにはTriggersでPressedとReleasedを追加します。これで押した時と離した時に実行されます。

 

最後にBP_CharacterからAbilitiesでGA_Dashを登録し、IA_DashノードからAbilityを実行します。

BP_PlayerCharacter

離した時はCompletedから処理が流れます。ここで先ほどのAbility.Action.Dash.Cancelタグを自身に送ることでGA_DashのWait Gameplay Eventノードの先が実行されます。

これでダッシュの完成です。