はじめに
2021/10/2 に開催された「オンライン出張ヒストリア!ゲーム開発勉強会2021」にて、『目指せ脱UE4初心者!?知ってると開発が楽になる便利機能を紹介 DataAsset, Subsystem, GameplayAbility編 』というタイトルで講演をしました。
スライド:https://www.slideshare.net/historia_Inc/ue4-dataasset-subsystem-gameplayability
講演動画:https://www.youtube.com/watch?v=2L1Dor22Kjs
この講演ではSubsystem, GameplayAbilityを使うために必要なC++コードを紹介したのですが、オンライン上のスライドですとコピペがしづらいのでC++コード部分を抽出して記事化しました。
Subsystem
p68 GameInstance Subsystemの場合 - 準備 -
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"
UCLASS()
class ○○○_API UMyGameInstanceSubsystem
: public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
int32 GetScore(){ return Score; }
private:
int32 Score;
};
p74 BPから作成可能に(要コンパイル)
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/WorldSubsystem.h"
#include "MyWorldSubsystem.generated.h"
UCLASS(Blueprintable, Abstract)
class ACTIONRPG_API UMyWorldSubsystem : public UWorldSubsystem
{
GENERATED_BODY()
};
p82 拡張用BPのプロパティを持たせるには
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"
// 拡張用BPのベースとなるクラス
UCLASS(Abstract, Blueprintable, MinimalAPI, meta = (ShowWorldContextPin))
class UMyGameInstanceSubsystemHelperBase : public UObject
{
GENERATED_BODY()
};
UCLASS()
class SUBSYSTEMBP_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
// 拡張用BPのプロパティ
UPROPERTY(Transient, BlueprintReadWrite)
UMyGameInstanceSubsystemHelperBase* SubsystemHelper;
};
p84 C++側で生成と設定をする手も ( .h側 )
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"
UCLASS(Abstract, Blueprintable, MinimalAPI, meta = (ShowWorldContextPin))
class UMyGameInstanceSubsystemHelperBase : public UObject
{
GENERATED_BODY()
};
UCLASS()
class SUBSYSTEMBP_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UMyGameInstanceSubsystem();
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
UPROPERTY(Transient, BlueprintReadOnly)
UMyGameInstanceSubsystemHelperBase* SubsystemHelper;
private:
TSubclassOf< class UMyGameInstanceSubsystemHelperBase > SubsystemHelperClass;
};
p85,86 C++側で生成と設定をする手も ( .cpp側 )
#include "MyGameInstanceSubsystem.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
UMyGameInstanceSubsystem::UMyGameInstanceSubsystem()
{
// 拡張用BPのクラス情報を検索・取得。パスの指定には注意
// .ini や プロジェクト設定でBPアセットのパスを設定できるようにしておくと親切
static ConstructorHelpers::FClassFinder<UMyGameInstanceSubsystemHelperBase> BluePrintFile(TEXT("/Game/Subsystem/BP_MyGameInstanceSubsystemHelper"));
if (BluePrintFile.Class)
{
SubsystemHelperClass = (UClass*)BluePrintFile.Class;
}
}
void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
SubsystemHelper = nullptr;
if (SubsystemHelperClass)
{
// 拡張用BPを生成・設定
SubsystemHelper = NewObject<UMyGameInstanceSubsystemHelperBase>(GetTransientPackage(), SubsystemHelperClass);
}
}
void UMyGameInstanceSubsystem::Deinitialize()
{
SubsystemHelper = nullptr;
}
p88 C++側で関数の準備をする場合
UCLASS(Abstract, Blueprintable, MinimalAPI, meta = (ShowWorldContextPin))
class UMyGameInstanceSubsystemHelperBase : public UObject
{
GENERATED_BODY()
public:
// 処理の中身はBP側で書くことを宣言
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void TestFunc();
};
Gameplay Ability
p130 .h側
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AbilitySystemComponent.h"
#include "MyBlueprintFunctionLibrary.generated.h"
UCLASS()
class ACTIONRPG_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, meta = (DefaultToSelf = "Target"))
static void GiveAbilityToComponent(AActor* Target, UAbilitySystemComponent* AbilitySystem, TArray<TSubclassOf<class UGameplayAbility>> AbilityList);
};
p131 .cpp側
#include "MyBlueprintFunctionLibrary.h"
void UMyBlueprintFunctionLibrary::GiveAbilityToComponent(AActor* Target, UAbilitySystemComponent* AbilitySystem, TArray<TSubclassOf<class UGameplayAbility>> AbilityList)
{
if (AbilitySystem && Target)
{
int32 inputID(0);
if (AbilityList.Num() > 0)
{
for (auto Ability : AbilityList)
{
if (Ability)
{
AbilitySystem->GiveAbility(FGameplayAbilitySpec(Ability.GetDefaultObject(), 1, inputID++));
}
}
}
AbilitySystem->InitAbilityActorInfo(Target, Target);
}
}
p132 プロジェクト側の .Build.cs
PrivateDependencyModuleNames.AddRange(
new string[] {
"GameplayAbilities"
}
);
さいごに
DataAsset, Subystem, GameplayAbilityはいいぞ!
おしまい