Unreal C++/Blueprint の UE4 にあった制約が UE5 でどうなったメモ (Unreal Engine 5.0.0)

以下は　Unreal Engine 5.0.0 + Visual Studio 2019 で確認。下の記事に書いてある UE4 にあった制約がどうなっているかを UE5 で調べたものです。

- [Unreal C++/Blueprint 雑多なメモ (Unreal Engine 4.26.1)](https://qiita.com/mml/items/128b725032276c79e728)

## Visual Studio 側のコードの UE5 Editor 側への反映

Visual Studio 側で明示的に「ソリューションをビルド」としないと、VS側の変更がUE5エディタ側に反映されないぽい？ UE5 側の操作だけで反映する方法がわからない。

## Unreal C++ 特有の制限とか罠とか（UE4から変わらず）

- 自作した Blueprint クラスを C++ クラスの親にできない（少なくともUEのエディタ上では）。（UE5でも同様）

- C++クラスの親クラスを「なし」にすると、Blueprint 側からは参照できないクラスになる。Blueprint 側から参照したい場合でActorなどの子にしたくないときでも、親のクラスを Object クラス（C++側では UObject クラスに相当）にする必要がある。（UE5でも同様）

- .h ファイルで　`#include "Classname.generated.h"` よりも後ろに他の `#include` を書くとエラーになる。（UE5でも同様）

- ~~public:` などの後に、メソッドの宣言を書いた後に　Blueprint 側に公開しない変数の宣言を書くと、エディタが落ちることがある（ぽい）。`UPROPERTY`　を書いた後に変数を書くのは（つまり公開する設定にすれば）大丈夫らしい。また、変数を先に書いて、関数を後に書くのは大丈夫（多分）。~~ これは UE5 では大丈夫になったぽい。

- C++ のコンストラクタで下記のように、関数の本体の中でスーパークラスのコンストラクタを呼ぶコードを書いてビルドするとUEエディタが落ちる。UE5でも余裕で落ちた。

```.cpp
ClassName::ClassName()
{
    Super();
}
```

下記のようにすれば問題ない。

```.cpp
ClassName::ClassName() : Super()
{
}
```

そもそも`Super()` は UE の中でマクロ的な何かとして扱われているぽいので、普通の関数のように扱おとしてはいけないぽい。[アンリアルでのオブジェクト処理](https://docs.unrealengine.com/4.26/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Objects/Optimizations/#%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E6%99%82%E3%81%AE%E5%9E%8B%E6%83%85%E5%A0%B1)

- C++ 側のコードを変更したことが原因で UE エディタが落ちてしまうと、そのままの状態では何度UEエディタを起動しなおしても落ちてしまう（というか起動しない）。その場合は、C++のコードを元に戻して Visual Studio  側でビルドしなおし、Visual Studio と UE5 のエディタを両方落としてから、UE5 で改めてプロジェクトを開きなおすと開ける（ことがある）。

## 関数（メソッド）関連

- [UFUNCTION について](https://docs.unrealengine.com/ja/ProgrammingAndScripting/GameplayArchitecture/Functions/index.html)：基本、下記のいずれかでいいはず：参考：[UE4 UFUNCTIONの種類について](https://papersloth.hatenablog.com/entry/2018/09/19/195013#BlueprintPure)

```.cpp
UFUNCTION(BlueprintCallable, Category="MyFunc")
    int32 BPCallable(); 
　　// ブループリント側から呼び出せる関数
//UFUNCTION(BlueprintCallableEvent, Category="MyFunc")
//    void  BPCallableEvent();　
　　// BlueprintCallableEvent は使えなくなったぽい？
UFUNCTION(BlueprintImplementableEvent, Category="MyFunc")
    void  BPImplementableEvent();  
　　// C++クラス側の実装はなく、BP側で赤いイベントのノードとして表示される。
UFUNCTION(BlueprintPure, Category="MyFunc")
    int32 BPPure();  // 実行ピンを持たないノードとして表示される。
```

C++ クラスのサブクラスを Blueprint で作って、親のC++クラスに定義されているメソッドを上書きできるようにしたい場合は、BlueprintNativeEvent を使う。このとき、C++ 側にも実装したい場合は `_Implementation` という関数に実装する。 

```.cpp
UFUNCTION(BlueprintNativeEvent, Category="MyFunc")
    int32 BPNativeEvent();
    virtual int32 BPNativeEvent_Implementation();
```

こうしといて、cpp 側のファイルに実装を書く。

```
int32 SomeClass::BPNativeEvent_Implementation()
{
    return 0;
}
```

こうしておくと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/b0b81a04-4f76-7701-5b9e-d0fe19cede17.png)

上のような感じでオーバーライドできる。日本語のコメントは化け化けになるみたい。

UE5のイベントエディタ上でノードを配置すると下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/d326ff45-b0ee-8c1f-515a-19ef85c3d408.png)

## プロパティ（インスタンス変数）関連

[UE4 よく使うUPROPERTYメモ](https://qiita.com/bigengelt/items/b17545fffe7b8d69e5e8)　から一部だけ抜粋。基本　EditAnywhere　でよい。

```.cpp
UPROPERTY(EditAnywhere, Category="MyFunc")
    int32 EAnywhere; 
　　// 常にUEのエディタ側で値を編集できる
//UFUNCTION(EditDefaultsOnly, Category="MyFunc")
    // int32 EDefaultsOnly; 
　　// UE5 では使えないぽい？
//UFUNCTION(EditInstanceOnly, Category="MyFunc")
//    int32 EInstanceOnly; 
　　// UE5 では使えないぽい？
UPROPERTY(VisibleAnywhere, Category="MyFunc")
    int32 EAnywhere; 
　　// 常にUEのエディタ側で値を見ることだけができる。編集はできない。
UPROPERTY(BlueprintReadWrite, Category="MyFunc")
    int32 BPintReadWrite; 
　　// ブループリント側で読み書きできる
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MyFunc")
    int32 EAnywhereBPintReadWrite; 
　　// 常にUEのエディタ側で値を編集でき、
　　// なおかつブループリント側で読み書きできる。
```