UE4 C++ GameplayAbilitiesを勉強していくPart.3-2 GameplayEffect コストとクールダウン

やあ

今回は、GameplayEffectのコストとクールダウンについて勉強するよ。
間違いなどあれば教えてくださると助かります!

前回

pto8913.hatenablog.com

GameplayEffect

CostGameplayEffectについて

GameplayAbilitiesで、能力のコストとして利用するために特別に設計されたGameplayEffectのこと。
・コストとは、GameplayAbilityを使うためにAbilitySystemComponentがどれだけのAttributeを持っている必要があるかを表しているよ。
GameplayAbilityがコストGameplayEffectを払えないなら、そのGameplayAbilityを実行できないよ。
・これを使えるGameplayEffectDuration PolicyInstantのものだけだよ。

実際にCostGameplayEffectを使ってみる

今回は、Part.2で作ったGA_Jumpにコストを持たせて、 コストが10以下ならジャンプできないようにするよ。

CostGameplayEffect用のGameplayEffectを作成

GE_Jumpを複製してGE_Jump_Costに名前を変えてね。
f:id:pto8913:20200530132154p:plain
f:id:pto8913:20200530135453p:plain

CostGameplayEffectを設定

f:id:pto8913:20200530132519p:plain

テスト

f:id:pto8913:20200530150132g:plain

あれー?
Part.2で作ったGA_Jumpはスタミナが半分以上の時、スタミナを10*2の20消費して、それ以外のときは10消費するだけのはずなのに、消費スタミナが増えてる?!

そう、GameplayAbilityCostGameplayEffectに設定したGameplayEffectの分も追加で減らされているのです!

な、なんだってー

ということで修正

GA_JumpからGE_Jumpを消して、
f:id:pto8913:20200530135236p:plain

これで安心。
f:id:pto8913:20200530150539g:plain

え?ModifierMagnitudeCalculation(MMC)はどこにいったのって?

CostGamplayEffectMMCをつかうには、GameplayAbilityを継承したクラスでGetCostGameplayEffect()をオーバーライドしてなにかするみたいなんだけど、よくわからなかったよ。

CooldownGameplayEffectについて

GameplayAbilitiesで、能力のクールダウンとしてとして利用するために特別に設計されたGameplayEffectのこと。
・クールダウンは、GamapleyAbilityを使ってからどれくらいの間で再び使えるかを決められるよ。
。 ・これを使えるGameplayEffectDuration PolicyHas Durationのものだけだよ。

実際にCooldownGameplayEffectを使ってみる(簡単版)

ただGameplayEffectを作ってそれを設定するだけ。
メリット
・簡単。
デメリット
・BPが増えすぎる

CooldownGameplayEffectの作成

f:id:pto8913:20200530165448p:plain
GrantedTagsに設定されているタグのCooldownは必須です。
これがないとクールダウンと判定してくれません。

CooldownGameplayEffectの設定

f:id:pto8913:20200530165600p:plain

テスト

f:id:pto8913:20200530170358g:plain
ちょっとわかりにくいけどアビリティを使って5秒以内は、アビリティを使えなくなってるね。

実際にCooldownGameplayEffectを使ってみる(ちょっとめんどくさいけど結果的に楽になる版)

MMCを使って、再利用性を高める
メリット
・簡単
デメリット
C++の読み書きができる必要がある。(?)

GameplayAbilityのサブクラスの作成

f:id:pto8913:20200530171309p:plain

MyGameplayAbility.hに追加

// Copyright(C)write by pto8913. 2020. All Rights Reserved.

#pragma once

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

UCLASS()
class ABILITYTEST_API UptoGameplayAbility : public UGameplayAbility
{
    GENERATED_BODY()
public:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooldowns")
        FScalableFloat CooldownDuration;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooldowns")
        FGameplayTagContainer CooldownTags;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cooldowns")
        FGameplayTagContainer Temp_CooldownTags;

    virtual const FGamepalyTagContainer* GetCooldownTags() const override;
    virtual void ApplyCooldown(
        const FGameplayAbilitySpecHandle Handle, 
        const FGameplayAbilityActorInfo* ActorInfo, 
        const FGameplayAbilityActivationInfo ActivationInfo
    ) const override;
};

MyGameplayAbility.cppに追加

// Copyright(C)write by pto8913. 2020. All Rights Reserved.

#include "Abilities/Ability/ptoGameplayAbility.h"

const FGameplayTagContainer* UptoGameplayAbility::GetCooldownTags() const
{
    FGameplayTagContainer* MutableTags = const_cast<FGameplayTagContainer*>(&Temp_CooldownTags);
    const FGameplayTagContainer* ParentTags = Super::GetCooldownTags();
    if (ParentTags)
    {
        MutableTags->AppendTags(*ParentTags);
    }
    MutableTags->AppendTags(CooldownTags);
    return MutableTags;
}

void UptoGameplayAbility::ApplyCooldown(
    const FGameplayAbilitySpecHandle Handle, 
    const FGameplayAbilityActorInfo* ActorInfo, 
    const FGameplayAbilityActivationInfo ActivationInfo
) const
{GetCooldownGameplayEffect();
    if (CooldownGE)
    {
        FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(CooldownGE->GetClass(), GetAbilityLevel());
        SpecHandle.Data.Get()->DynamicGrantedTags.AppendTags(CooldownTags);
        ApplyGameplayEffectSpecToOwner(Handle, ActorInfo, ActivationInfo, SpecHandle);
    }
}

Modifier Magnitude Calculationのサブクラスの作成

f:id:pto8913:20200530173558p:plain

MMC_Cooldown.hに追加

// Copyright(C)write by pto8913. 2020. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_Cooldown.generated.h"

UCLASS()
class ABILITYTEST_API UMMC_Cooldown : public UGameplayModMagnitudeCalculation
{
    GENERATED_BODY()
public:
    virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
};

MMC_Cooldown.cppに追加

// Copyright(C)write by pto8913. 2020. All Rights Reserved.

#include "Abilities/Calculations/MMC_Cooldown.h"

#include "Abilities/Ability/ptoGameplayAbility.h"

float UMMC_Cooldown::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
    const UptoGameplayAbility* Ability = Cast<UptoGameplayAbility>(
        Spec.GetContext().GetAbilityInstance_NotReplicated()
    );

    if (!Ability)
    {
        return 0.0f;
    }

    return Ability->CooldownDuration.GetValueAtLevel(Ability->GetAbilityLevel());
}

GameplayAbilityの設定

f:id:pto8913:20200530174540p:plain
f:id:pto8913:20200530174631p:plain

CooldownGameplayEffectの設定

f:id:pto8913:20200530174652p:plain

テスト

f:id:pto8913:20200530174904g:plain
うまくいってるね。

これでクールダウンをつけたいアビリティに、GE_Jump_Cooldownを設定してあげればクールダウンが簡単にできるよ。

GE_Jump_Cooldownの名前は変えとこうね。

今回はここまで、ありがとうございました。

次回

GameplayEffectStackingOverflowについて勉強するよ。

pto8913.hatenablog.com