LoginSignup
10
8

More than 1 year has passed since last update.

[UE4] Subsystem, GameplayAbilityに関する講演で使用したC++コードについて

Last updated at Posted at 2021-10-05

はじめに

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はいいぞ!

おしまい

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8