GameplayAbility - GameplayAbility と コンポーネント の準備編
こんばんは、ごりです。
今日は、こちらの記事の続きからです。
goolee.hatenablog.com
今回は、実際に使う GameplayAbility と Component のクラスを作っていきます。
コンテンツブラウザの 新規C++クラスをクリック。
全てのクラスを表示にチェックし、 GameplayAbility と打ちます。
GameplayAbility を選択し、次へ。
ファイル名は 「GameplayAbilityBase」 とします。
続いて、新規C++クラスから 「AbilitySystemComponent」と打ちます。
ファイル名は 「AbilitySystemComponentBase 」とします。
作成が終わったら、
Component に処理を追加していきます。
今回もソースコードを記述します。
まず AbilitySystemComponentBase.h
/** *@file AbilitySystemComponentBase.h *@brief GameplayAbility を用いるためのComponent *@author goolee *@date 2018/12/01 */ #pragma once #include "CoreMinimal.h" #include "AbilitySystemComponent.h" #include "GameplayTagContainer.h" #include "AbilitySystemComponentBase.generated.h" class UGameplayAbilityBase; /** * GameplayAbility を扱う Component * ゲーム中に指定したデータを扱うために、AbilitySystemComponent を拡張 */ UCLASS() class GPASTUDY_API UAbilitySystemComponentBase : public UAbilitySystemComponent { GENERATED_BODY() public: /** *@fn *コンストラクタ */ UAbilitySystemComponentBase(); /** *@fn *現在実行中の Ability の中から指定した GameplayTag と一致するものすべて取得 *@param (GameplayTagContainer) 指定するGameplayTagの集まり *@return (ActiveAbilities) 指定したタグと一致したAbility */ void GetActiveAbilitiesWithTags( const FGameplayTagContainer& GameplayTagContainer, TArray<UGameplayAbilityBase*>& ActiveAbilities ); };
つづいて AbilitySystemComponent.cpp
#include "AbilitySystemComponentBase.h" #include "GameplayAbilityBase.h" UAbilitySystemComponentBase::UAbilitySystemComponentBase() {} void UAbilitySystemComponentBase::GetActiveAbilitiesWithTags(const FGameplayTagContainer& GameplayTagContainer, TArray<UGameplayAbilityBase*>& ActiveAbilities) { TArray<FGameplayAbilitySpec*> AbilitiesToActivate; GetActivatableGameplayAbilitySpecsByAllMatchingTags( GameplayTagContainer, AbilitiesToActivate, false ); // Iterate the list of all ability specs for (FGameplayAbilitySpec* Spec : AbilitiesToActivate) { // Iterate all instances on this ability spec TArray<UGameplayAbility*> AbilityInstances = Spec->GetAbilityInstances(); for (UGameplayAbility* ActiveAbility : AbilityInstances) { ActiveAbilities.Add(Cast<UGameplayAbilityBase>(ActiveAbility)); } } }
GameplayAbilityBase には今回は処理を追加しません。
ではこのComponentとAbility をキャラクターに持たせて、
GameplayAbilityを使えるようにしていきます。
CharacterBase.h と CharacterBase.cpp です。
/** *@file CharacterBase.h *@brief GameplayAbility を用いる キャラクターの基底クラス *@author goolee *@date 2018/12/01 */ #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "AttributeSetBase.h" #include "AbilitySystemInterface.h" #include "AbilitySystemComponentBase.h" #include "CharacterBase.generated.h" UCLASS() class GPASTUDY_API ACharacterBase : public ACharacter, public IAbilitySystemInterface { GENERATED_BODY() public: /** * @fn * コンストラクタ */ ACharacterBase(); /** *@fn *コントローラ所有された際の処理 *@param このキャラクターを所有するコントローラ * *前回、この処理書いてなかったです、すみません。 */ virtual void PossessedBy(AController* NewController) override; protected: /** * GameplayAbilityを扱うコンポーネント */ UPROPERTY() UAbilitySystemComponentBase* AbilitySystem; /** * キャラクターのステータス * ブループリントから呼び出しはできないが、 * ガベージコレクションに追加するため UPROPERTY() を記述 */ UPROPERTY() UAttributeSetBase* AttributeSet; /** *キャラクター生成時から実行可能なAbility */ UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Abilities") TArray<TSubclassOf<UGameplayAbilityBase>> Abilities; /** * @fn * ゲーム開始時や、生成時に呼ばれる処理 */ virtual void BeginPlay() override; /** * @fn * キャラクターの体力を取得 * @return キャラクターの体力 */ UFUNCTION(BlueprintCallable) virtual float GetHealth() const; public: /** * @fn * 毎フレーム呼ばれる処理 */ virtual void Tick(float DeltaTime) override; /** *@fn *AbilitySystemComponentを取得 *@return AbilitySystemComponent */ UAbilitySystemComponent* GetAbilitySystemComponent() const override; /** *@fn *指定したタグと一致するAbilityを実行 *@param (AbilityTags) 実行するAilityがもつGameplayTag *@param (bAllowRemoteActivation) true...ローカル/サーバーで実行 false...ローカルでのみ実行 *@return true...実行に成功 false...失敗 */ UFUNCTION(BlueprintCallable, Category = "Abilities") bool ActivateAbilitiesWithTags(FGameplayTagContainer AbilityTags, bool bAllowRemoteActivation = true); /** *@fn *キャラクターが現在実行中の Ability の中から指定した GameplayTag と一致するものすべて取得 *@param (AbilityTags) 指定するGameplayTagの集まり *@return (ActiveAbilities) 指定したタグと一致したAbility */ UFUNCTION(BlueprintCallable, Category = "Abilities") void GetActivateAbilitiesWithTags( FGameplayTagContainer AbilityTags, TArray<UGameplayAbilityBase*>& ActiveAbilities); };
#include "CharacterBase.h" #include "GameplayAbilityBase.h" ACharacterBase::ACharacterBase(){ //trueにすると毎フレームTick関数を呼び出す設定 PrimaryActorTick.bCanEverTick = true; //AbilitySystemConponentの生成 AbilitySystem = CreateDefaultSubobject<UAbilitySystemComponentBase>(TEXT("AbilitySystem")); //マルチプレイヤー用の設定 AbilitySystem->SetIsReplicated(true); //AttributeSet の生成 AttributeSet = CreateDefaultSubobject<UAttributeSetBase>(TEXT("AttributeSet")); } void ACharacterBase::PossessedBy(AController* NewController) { Super::PossessedBy( NewController ); if (AbilitySystem) { //AbilitySytemを持つ Actor情報と このAbilitySystemで動く Actor情報の初期化 AbilitySystem->InitAbilityActorInfo(this, this); } } void ACharacterBase::BeginPlay() { Super::BeginPlay(); /** * AbilitySytemに使えるAbilityを登録 * これをしないとTagでAbilityを指定しても実行されない。 */ if (AbilitySystem) { for (auto Ability : Abilities) { AbilitySystem->GiveAbility(FGameplayAbilitySpec(Ability, 1, INDEX_NONE, this)); } } } void ACharacterBase::Tick(float DeltaTime){ Super::Tick(DeltaTime); } float ACharacterBase::GetHealth() const { return AttributeSet->GetHealth(); } UAbilitySystemComponent* ACharacterBase::GetAbilitySystemComponent() const { return AbilitySystem; } bool ACharacterBase::ActivateAbilitiesWithTags(FGameplayTagContainer AbilityTags, bool bAllowRemoteActivation) { if (AbilitySystem) { return AbilitySystem->TryActivateAbilitiesByTag( AbilityTags, bAllowRemoteActivation ); } return false; } void ACharacterBase::GetActivateAbilitiesWithTags(FGameplayTagContainer AbilityTags, TArray<UGameplayAbilityBase*>& ActiveAbilities) { if (AbilitySystem) { AbilitySystem->GetActiveAbilitiesWithTags( AbilityTags, ActiveAbilities ); } }
ここまで出来たら、ビルドして BP_CharacterBase を見てみましょう。
コンポーネントに AbilitySystemが追加され、
デフォルトの詳細に、Abilitiesが増えているのがわかりますね。
これで GameplayAbilityを使う準備は整いました。
次回から使い方を書いていきたいと思います。
その都度、機能拡張をしていきます。
ソースコードのコメントに、説明書きましたが、
不明な点があれば、ご連絡ください。
ではでは。