プラグインの有効化
タグの追加
モジュールの追加
SampleProject.build.cs
PublicDependencyModuleNames.AddRange(new string[] { "GameplayAbilities", "GameplayTags", "GameplayTasks" });
スタートアップ処理
SampleProject.cpp
#include "Interfaces/IPluginManager.h"
#include "Modules/ModuleManager.h"
#include "AbilitySystemGlobals.h"
#include "GameplayTagsManager.h"
class FSampleGameModule : public FDefaultGameModuleImpl
{
public:
virtual void StartupModule() override
{
check(LoadTagIni("Config/Tags"));
auto& AbilitySystem = UAbilitySystemGlobals::Get();
if ( ! AbilitySystem.IsAbilitySystemGlobalsInitialized())
{
/* システムの初期化 */
AbilitySystem.InitGlobalData();
}
}
private:
bool LoadTagIni(const FString& Directory)
{
if (const auto ThisPlugin = IPluginManager::Get().FindPlugin(TEXT("CommonConversation")))
{
/* GameplayTag 用の .ini ファイル配置ディレクトリパスを登録する */
UGameplayTagsManager::Get().AddTagIniSearchPath(ThisPlugin->GetBaseDir() / *Directory);
return true;
}
return false;
}
};
IMPLEMENT_PRIMARY_GAME_MODULE(FSampleGameModule, SampleProject, "SampleProject");
AttributeSet の継承クラス
SampleAttributeSet.h
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectAggregatorLibrary.h"
/* Attribute の Getter & Setter 関数の自動生成マクロ */
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
UCLASS()
class USampleAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UFUNCTION()
virtual void OnRep_SampleValue(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(USampleAttributeSet, SampleValue, OldValue);
}
public: /* UObject interface */
/* 生存中に複製されるプロパティを返す */
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(USampleAttributeSet, SampleValue, COND_None, REPNOTIFY_Always);
}
public: /* UAttributeSet interface */
/* CurrentValue の変更が行われる直前に呼ばれるクランプ処理などを行う関数 */
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override
{
if (Attribute == GetSampleValueAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, 100.0f);
}
}
/* GameplayEffect から BaseValue の変更が行われた際に呼ばれる */
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override
{
Super::PostGameplayEffectExecute(Data);
}
/* Aggregator 生成時に呼ばれる */
virtual void OnAttributeAggregatorCreated(const FGameplayAttribute& Attribute, FAggregator* NewAggregator) const override
{
if (NewAggregator != nullptr)
{
if (Attribute == GetSampleValueAttribute())
{
/* 最も否定的な Modifier とすべての肯定的な Modifier のみを許可する */
NewAggregator->EvaluationMetaData = &FAggregatorEvaluateMetaDataLibrary::MostNegativeMod_AllPositiveMods;
}
}
}
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Sample", ReplicatedUsing = OnRep_SampleValue)
FGameplayAttributeData SampleValue{ 100.0f };
ATTRIBUTE_ACCESSORS(USampleAttributeSet, SampleValue) /* 初期化関数の自動生成マクロ */
};
Ability System を保持するクラス
SampleCharacter.h
#include "Abilities/GameplayAbility.h"
#include "AbilitySystemInterface.h"
#include "AbilitySystemComponent.h"
#include "GameplayTags.h"
#include "GameplayEffectTypes.h"
UCLASS()
class ASampleCharacter : public ACharacter,
, public IAbilitySystemInterface
, public IGameplayTagAssetInterface
{
GENERATED_BODY()
public:
ASampleCharacter(const FObjectInitializer& ObjectInitializer)
{
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("Ability System"));
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Full);
AbilitySystemComponent->RegisterGenericGameplayTagEvent().AddUObject(this, &ASampleCharacter::OnAbilitySystemGenericGameplayTagEvent);
/* UAbilitySystemComponent に自動登録 */
SampleAttributeSet = CreateDefaultSubobject<USampleAttributeSet>(TEXT("AbilitySet"));
GameplayTagCountContainer.RegisterGenericGameplayEvent().AddUObject(this, &ASampleCharacter::OnGameplayTagCounterGenericGameplayTagEvent);
}
public: /* UObject */
virtual void BeginPlay() override
{
Super::BeginPlay();
if (auto ThisComponent = GetAbilitySystemComponent())
{
int32 Index = 0;
for (auto& GameplayAbiliity : StartupGameplayAbiliities)
{
if (IsValid(GameplayAbiliity.GetGCPtr()))
{
ThisComponent->GiveAbility(FGameplayAbilitySpec(GameplayAbiliity, 1, Index++));
}
}
ThisComponent->InitAbilityActorInfo(this, this);
}
}
public: /* APawn interface */
/* 所有された際に呼ばれる */
virtual void PossessedBy(AController* NewController) override
{
Super::PossessedBy(NewController);
if (auto ThisComponent = GetAbilitySystemComponent())
{
ThisComponent->RefreshAbilityActorInfo();
if (ThisComponent->ReplicationMode == EGameplayEffectReplicationMode::Mixed)
{
SetOwner(NewController);
}
}
}
public: /* IAbilitySystemInterface */
/* UAbilitySystemComponent の取得 */
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override
{
return AbilitySystemComponent;
}
public: /* IGameplayTagAssetInterface */
/* 所有している GameplayTag の取得 */
virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override
{
for (const auto& GameplayTag : GameplayTagContainer.GetGameplayTagArray())
{
if ( ! TagContainer.HasTag(GameplayTag))
{
TagContainer.AddTag(GameplayTag);
}
}
}
public:
/* UAttributeSet 追加 */
bool AddAttributeSet(UAttributeSet* Attribute)
{
if (IsValid(Attribute))
{
if (auto ThisComponent = GetAbilitySystemComponent())
{
ThisComponent->AddSpawnedAttribute(Attribute);
ThisComponent->ForceReplication();
return true;
}
}
return false;
}
/* UAttributeSet 削除 */
void RemoveAttributeSet(UAttributeSet* Attribute)
{
if (IsValid(Attribute))
{
if (auto ThisComponent = GetAbilitySystemComponent())
{
ThisComponent->RemoveSpawnedAttribute(Attribute);
ThisComponent->ForceReplication();
}
}
}
/* サンプル値の設定 */
bool SetAttributeSampleValue(const float& Value)
{
if (IsValid(SampleAttributeSet))
{
if (auto ThisComponent = GetAbilitySystemComponent())
{
ThisComponent->SetNumericAttributeBase(USampleAttributeSet::GetSampleValueAttribute(), Value);
return true;
}
}
return false;
}
/* サンプル値の取得 */
float GetAttributeSampleValue() const
{
if (IsValid(SampleAttributeSet))
{
if (auto ThisComponent = GetAbilitySystemComponent())
{
return ThisComponent->GetNumericAttribute(USampleAttributeSet::GetSampleValueAttribute());
}
}
return 0.0f;
}
private:
/* GameplayTag 参照カウントが更新された際に呼ばれる */
void OnAbilitySystemGenericGameplayTagEvent(const FGameplayTag GameplayTag, int32 NewCount)
{
if ( ! GameplayTagContainer.HasTag(GameplayTag))
{
GameplayTagContainer.AddTag(GameplayTag);
}
if ( ! GameplayTagCountContainer.HasMatchingGameplayTag(GameplayTag))
{
GameplayTagCountContainer.SetTagCount(GameplayTag, NewCount);
}
else
{
static_cast<void>(GameplayTagCountContainer.UpdateTagCount(GameplayTag, (NewCount - GameplayTagCountContainer.GetTagCount(GameplayTag))));
}
}
/* GameplayTag のカウントが 0 になった際に呼ばれる */
void OnGameplayTagCounterGenericGameplayTagEvent(const FGameplayTag GameplayTag, int32 NewCount)
{
if (NewCount <= 0)
{
GameplayTagContainer.RemoveTag(GameplayTag);
}
}
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Abilities)
TArray<TSubclassOf<UGameplayAbility>> StartupGameplayAbiliities;
private:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Sample", meta = (AllowPrivateAccess = "true"))
TObjectPtr<USampleAttributeSet> SampleAttributeSet{ nullptr };
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = Abilities, meta = (AllowPrivateAccess = "true"))
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent{ nullptr };
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Sample", meta = (AllowPrivateAccess = "true", Categories = "GameplayCue"))
FGameplayTagContainer GameplayTagContainer;
FGameplayTagCountContainer GameplayTagCountContainer;
};
アニメーションモンタージュの作成
Gameplay Effect BP の作成
※ BaseValue、CurrentValue ともに影響する。