Category Archives: UnrealEngine

UE5 Editorからアセットを選択する際にインターフェイスでフィルタリングする

DataAssetなどでEditorから参照する際に
このようなコードを作成すると

UPROPERTY(EditDefaultsOnly, DisplayName = "敵のアセット")
TSubclassOf<AActor> EnemyAsset;

プロジェクト内すべてのActorがリストアップされてしまい、
検索が大変
設定するアセットを間違える等のミスが考えられます。

これを解消するために
特定のインターフェイスを継承しているクラスのみがリストアップされるようにしたいと思います。

調べると以下のAllowedClasses metaが候補に上がりますがこちらは自作のC++のクラスなどは検知されないようです。(UE5.3)
Unreal側で用意されているクラスをフィルタリングしたいのならこちらを使えば良さそうですね。

meta = (AllowedClasses = "MyClass")

Widget内のListViewなどEntryWidgetClassはUserObjectListEntryを継承した
Widgetのみしか選択できないですね

こちらのソースコードを確認したところ
MustImplement metaが使用されていました。

これを使用して書くと以下のようになりました。
そのままインターフェイスを指定すると
フルパスを指定するように警告ログがでて正常にフィルターされません。
インターフェイスがあるクラスまでのパスを記述する必要があるようです。

UPROPERTY(EditDefaultsOnly, meta = (DisplayName = "敵のアセット", MustImplement = "/Script/TESTProject.MyTest"))
TSubclassOf<AActor> EnemyAsset;

これで結果がフィルタリングされて
見やすくなりますね。
積極的に活用していきたいところです。

UE5.3.2 Cook時に Profile (OverlapAll) – Custom Channel Name = ‘GameTraceChannelN’ hasn’t been found ログが出る

Cookした際に

以下の警告が出たときの対応
PackagingResults: Warning: Profile (OverlapAll) - Custom Channel Name = 'GameTraceChannelN' hasn't been found
(Nには6~18の数字が入る可能性がある?)

Config/DefaultEngine.iniを開いて
以下の部分を編集する

+EditProfiles=(Name="OverlapAll"~
から始まる行の警告ログに出ている
Channel="GameTraceChannelN" になっている部分を
Channel="HOGEHOGE" のように自分で設定した名前に変更
OverlapAll以外もログが出ていたら同様に変更する。

本来ならばProjectSettingで設定したときに自動で正しいものに変更されるはずだが何らかの原因でうまく動作しなくなってしまっている。
原因不明
Engine側が管理しているDefaultEngine.iniの部分を直接書き換えるのはあんまり良くなさそう

UE5 Unload Stream Level の完了が呼ばれなかった問題

※この記事はUE5.3.2で確認しています。

動的にLevelを切り替える際に使用するLoadStreamLevel,UnloadStreamLevelノードですが
UnloadStreamLevelノードのCompleteまで処理が走らない問題に遭遇したので原因をメモ。

症状

以下のようにノードを組んだ際に
Unload Stream Levelノードまでは実行されるがCompleteが呼ばれない状態。

この質問と同じ状態ですが解決策がない
https://forums.unrealengine.com/t/unload-stream-level-does-not-continue-and-hangs-on-streaming-level/405656

解決策

この記事に解決策が書いてありました。
https://forums.unrealengine.com/t/bug-unload-stream-level-node-never-completes/373379/4

このノードを組んでいるActorがUnloadするLevelに含まれているためにCompleteまで呼ばれないのが原因でした。
他のLevelに移動したり、PersistantLevelにいれると問題が解消しました。

UE5 SceneCapture2Dのハマった仕様

※この記事はUE5.3.2で確認しています。

RenderTargetにレンダリング結果を渡せるSceneCapture2D
これを使っていて気がついたことがあったのでメモ

シーン内にSceneCapture2Dが複数あり、RenderTargetに同じものが指定されている場合
CaptureSortPriorityが小さいものが優先して適用されます。
このとき、CaptureSortPriorityが高く使用されていないSceneCapture2Dは
全く動いていないものだと思いましたが

StatRHIでTriangleDrawnを確認してみたところ
レンダリングされているようでした。

DrawnTris_Normal
カメラ一つのみ
6万5千程度

DrawnTris_Camera1
SceneCaptureを一つ追加
12万1千
大体二倍ですね

DrawnTris_Camera10
カメラ一つ
SceneCaptureを11個
CaptureSortPriorityは-1が一つ100が10個です。
驚きの66万!?

SceneCaptureはRenderTargetに反映されていなくても描画処理が走っているようです。

これを避けるにはOptionにあるCaptureEveryFrameをOffにして
必要に応じてCaptureonMovementを切り替えれば大丈夫なようです。
Option menu

追記
BluePrintノードのDeactivateを呼んでもレンダリングの更新を止めることができるのを確認しました。

SceneCaptureの意外な落とし穴でした。

SpawnActor failed because no class was specifiedが発生したときの対応

問題

ABulletClass型の変数を定義して
BluePrintからアセットを指定した状態で

// header
UPROPERTY(EditDefaultsOnly)
TSoftClassPtr<ABulletClass> BulletAsset;

CPPのBeginPlayなどで以下のように呼び出す

// cpp
ABulletClass* bullet = GetWorld()->SpawnActor<ABulletClass>(BulletAsset.Get());

すると
LogSpawn: Warning: SpawnActor failed because no class was specified
エラーが発生する。

解決法

softrefで参照しているクラスを一度でもloadすると解消する問題のようです。
事前にLoadする処理を挟むか

// cpp
ABulletClass* bullet = GetWorld()->SpawnActor<ABulletClass>(BulletAsset.LoadSynchronous());

のように記述すれば解決。
事前にロードした場合UPROPERTYのついた変数にキャッシュしないとGCが走ったときにNullになる可能性があるので注意が必要そう。

Editorだと一度でもBPを開いたりしているとloadしなくても動作するので再起動したときに気がついて困ったりする。