今更触るSubSystem（ｃ＋＋初心者向け）

## はじめに

この記事は[Unreal Engine (UE) Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ue) 2日目の記事です。

https://www.docswell.com/s/historia_Inc/5WVYJK-ue4-dataasset-subsystem-gameplayability

[おかず様](https://www.docswell.com/s/historia_Inc/5WVYJK-ue4-dataasset-subsystem-gameplayability)の講演にでてくるSubSystemのBP拡張の作り方をC＋＋を使ったことがない人が作ってみる記事になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/ae149c20-f68e-7066-1043-b7cc1aec64d7.png)


環境
UE5.2
VisualStudio2022
必須プラグイン（？）：[VisualStudio Integration Tool](https://www.unrealengine.com/marketplace/en-US/product/visual-studio-integration-tool)

## 手順

プロジェクトを立て、ヘッダータブのツール＞新規C＋＋クラスからSubSystemを追加します。![スクリーンショット (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/e084f221-ded9-5ac2-f535-a5e35c80a908.png)
今回はGameInstanceSubSystemで作っていきますが、ほかのものでも手順は同じです。

VisualStudioが立ち上がったら、C＋＋で制作していない場合は一度ビルドをかけます。
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/d20f0b35-6bbe-ad57-3b0f-504620984237.png)

もしソリューションエクスプローラー（左か右にあるファイル構造が書いてあるタブ）にインストールが足りていない旨が出た場合はインストールを行ってください。

ヘッダータブの　ビルド＞（プロジェクト名）のビルド　を実行してビルドを行います。（ビルドする際はUEを落とした状態で行ってください）

ビルド完了後何かしらのBPを開くと、すでに生成時につけたクラス名で検索かけるだけでSubSystemが生成されているのを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/368ea57b-20cb-358e-036f-57b058cd85e4.png)

これで呼び出すイベントの内容をBPで設定できるようC＋＋側で書いていきます。
上の講演のスライドのコピペでほとんどいけます。
https://www.docswell.com/s/historia_Inc/5WVYJK-ue4-dataasset-subsystem-gameplayability/82
ほぼこのコードを張るだけ

先ほど制作したSubSystemのヘッダファイル（.hの方）を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/e64af055-1156-7ef5-f9e6-3b9a8ded398c.png)

もとから自動生成されているコードの＃IncloudeとUCLASSの間に貼り付けます。

``` c++:上の部分
UCLASS(Abstract, Blueprintable, MinimalAPI, meta = (ShowWorldContextPin))
class UMyGameInstanceSubsystemHelperBase : public UObject
{
	GENERATED_BODY()
};
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/96304558-7835-0e39-a3cd-e1d79cee5f1e.png)

次にもとからあったUCLASSの中のGENERATED_BODY()の下に

``` c++:下の部分
public:
// 拡張用BPのプロパティ
UPROPERTY(Transient, BlueprintReadWrite)
UMyGameInstanceSubsystemHelperBase* SubsystemHelper;

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/79a4da72-13fe-af87-351e-aa154da59caa.png)

貼り付けていきます。
.hの全体はこんな感じになっています。
```c++:全体
// Fill out your copyright notice in the Description page of Project Settings.

#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 SUBSYSTEM_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
public:
	// 拡張用BPのプロパティ
	UPROPERTY(Transient, BlueprintReadWrite)
	UMyGameInstanceSubsystemHelperBase* SubsystemHelper;

	
};

```
これはスライドにあるものを原文そのままもってきているだけですがもしコピペがダメな場合はスライドのPDFをダウンロードしてPDFからコピーしてください。

UMyGameInstanceSubsystemHelperBase(ハイライト部）は拡張用のBPのベースの名前となり、ハイライトの上下が同じ名前で[U + 好きな半角名]であれば自由に命名することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/859e0d36-81a3-9a6e-0a0d-fa5185fa9a3b.png)
こんな風に変えることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/f9c403b7-8a0b-2a51-cef7-6248200b925a.png)



続いてBPに書くイベントの関数を作っていきます。
先ほど追加した上側のUCLASSのGENERATED_BODY()下に関数を追加するコードを貼って行きます。
```c++:関数の追加
public:
// 処理の中身はBP側で書くことを宣言
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
void TestFunc();

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/90f30a35-dae7-d0eb-5e85-8e822abe4443.png)

文中のTestfuncはそのまま関数名となるため、自由に変更することができます。
また、複数宣言することで関数を増やすことができます

```c++:書き換え応用
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"

/**
 * 
 */
UCLASS(Abstract, Blueprintable, MinimalAPI, meta = (ShowWorldContextPin))
class UMyGISubsystemHelperBase : public UObject
{
	GENERATED_BODY()
public:
	// 処理の中身はBP側で書くことを宣言
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void First();
public:
	// 処理の中身はBP側で書くことを宣言
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void Second();
public:
	// 処理の中身はBP側で書くことを宣言
	UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
	void Third();
};

UCLASS()
class SUBSYSTEM_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
public:
	// 拡張用BPのプロパティ
	UPROPERTY(Transient, BlueprintReadWrite)
	UMyGISubsystemHelperBase* SubsystemHelper;

	
};
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/c794c47b-5dc6-3c0b-90ee-c4f8e66dacf2.png)

あとはビルドしてUEに戻ります。

UEに戻ると先ほど追加したMyGIsubsystemHelperBaseがアクターを制作の一覧に増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/fc64737a-f506-7f65-9d6b-34d4ade746e2.png)

Actorを作って開いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/27c2957f-d0b4-8bd5-f7c8-50599f1c0f6f.png)
左側のマイブループリントタブから関数をオーバーライドで先ほどコードで作った関数をオーバーライドして中身を設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/f4d7c387-c111-e3d8-714e-86590de815f7.png)

あとはレベルプリントやGameModeなどSubSystemの親に合わせてどこかしらに拡張BPの生成処理を書いてあげれば
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/ce1cb0f8-8510-9047-18b5-cd757c3bb98c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257391/7c8ab109-6004-ab09-a916-eee2698cee43.png)

どこからでも拡張BPの関数を呼び出せるようになりました！

## 終わりに
おそらく変数を格納したりするにはまたC＋＋で書く必要があると思いますが、どこでも使える関数と思うとめっちゃ便利ですね。
あと一日分の野菜＋一日分の鉄分調濃縮はまじめにおすすめです。PC大好きなエンジニアの皆さんはぜひ！アマゾンでまとめ買いすれば一本88円！