【UE5】他のレベルに配置されたActorの参照を取得するにはSoftObjectReferenceを用いる

# 概要
他のレベルに配置されたActorの参照を取得するにはSoftObjectReferenceを用います。

と、ネットで調べると出てくるのですが、例えばActorが属するSubLevelのSteaming MethodがBlueprintで且つロードしていない場合だとどうなる？や具体的にどう参照を取得するか等を記載している文献が見当たらなかったので、調査いたしました。

※また、10年ほど前でまだSoftObjectReferenceがなかった？時代のネットの記事の場合はGetAllActorsofClassノードを用いている例もあります。それでも実装自体は可能です
※SoftObjectReferenceはC++的にはTSoftObjectPtrのことです

調査で用いたプロジェクトは↓にアップロードしてあります。

https://github.com/ogamita777/SubLevelTest

■環境
UnrealEngine：5.5.4
ビルド構成：DebugGame Editor

# 結論
- SoftObjectReferenceから参照の取得を試みるには Resolve Soft Reference ノードを用いる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/a438bcfd-ca0c-4c22-8a70-9f47809f0cb2.png)
- Actorが属するSubLevelのSteaming Methodが「Always Loaded」の場合：参照が**取れる** (※アクターが存在するので)
- Actorが属するSubLevelのSteaming Methodが「Blueprint」の場合
    - SubLevelがロードされていない場合：参照が**取れない** (※アクターが存在しないので)
    - SubLevelがロードされている場合：参照が**取れる** (※アクターが存在するので)

# 調査
SubLevelに配置したActorをPersistentLevelのレベルブループリントから参照を取得する実験を行います。

PersistentLevel(TestPersistentLevel)を作成しSubLevel(TestSubLevel)をくっつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/827776d6-95f4-49dc-bf72-464280f900a4.png)

まず最初はTestSubLevelのSteaming Method は Always Loadedとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/42ab47d4-670f-4d52-9424-fafbf30c439e.png)


TestSubLevelにTestActor_TestSubLevelアクターを配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/66eef3a6-7b39-41ff-9462-2d41fe879489.png)

TestPersistentLevelのレベルブループリントにSoftObjectReference_TestActor_TestSubLevelという名前のActorのSoftObjectReference型の変数を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/371e8a91-ff86-4040-9231-a3e9e6c0d837.png)

コンパイル後、SoftObjectReference_TestActor_TestSubLevel変数のDetailからSubLevel(TestSubLevel)のアクターを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/96f80e37-218e-4379-8e1d-0e9679b7224c.png)

SoftObjectReference_TestActor_TestSubLevel変数のResolve Soft Reference から参照の取得を試みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/603eca2b-ed7b-48c0-8bfb-c061fa8d22cf.png)

BeginPlayからノードをつなぎ、下記のようなロジックを組み込ます。
TestActor_TestSubLevelのアクターの参照が取れれば「TestActor_TestSubLevelは存在する：アクター名」をデバッグ表示します。
参照が取れなければ「TestActor_TestSubLevelは存在しない」をデバッグ表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/915a4a89-59ee-405a-b1b9-146116d54469.png)

ゲームをプレイします。

「TestActor_TestSubLevelは存在する：TestActor_TestSubLevel」とデバッグ表示されます。
**他のレベルに配置されたActorの参照が取得できている**ことがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/f8656dc4-382d-49be-a5a0-df672fd19212.png)


次に、TestSubLevelのSteaming Methodを「Blueprint」に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/975591a8-48e3-48f3-b5b1-89ea63514155.png)

再度ゲームをプレイします。

「TestActor_TestSubLevelは存在しない」がデバッグ表示されます。Steaming Methodが「Blueprint」でロードがされていない場合は参照が取得できていないことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/24172630-0ae7-4db7-bef6-7b158b94a91c.png)

最後に、TestPersistentLevelのレベルブループリントのロジックを修正し、BeginPlayの直後にTestSubLevelのロードを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/adc1e4c5-182d-4745-b12e-6787e300a4b7.png)

再度ゲームをプレイします。

「TestActor_TestSubLevelは存在する：TestActor_TestSubLevel」とデバッグ表示されます。
Steaming Methodが「Blueprint」の場合でもSubLevelのロードが行われればActorの参照が取得できるようになっていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29542/ef624dd6-144d-4328-a19a-a91374a0e233.png)

# 参考文献
- [Reference objects in persistent level from objects in sub level - Development / World Creation - Epic Developer Community Forums](https://forums.unrealengine.com/t/reference-objects-in-persistent-level-from-objects-in-sub-level/353361/2)
- [【UE4】メモ：レベル間をまたいだアクターの参照方法【★★】](https://kinnaji.com/2020/12/22/differentlevelactorreference/)