for (auto* ele : DataLayerSubsystem->GetDataLayerInstances())
上記の処理でパーシスタントレベルのデータレイヤーサブシステムからサブレベルBのレベルインスタンスを
取得したかったが、取得できなかった。
取得して値を変更する場合はどのようなAPIを使用すればよいか教えてほしい
[Attachment Removed]
for (auto* ele : DataLayerSubsystem->GetDataLayerInstances())
上記の処理でパーシスタントレベルのデータレイヤーサブシステムからサブレベルBのレベルインスタンスを
取得したかったが、取得できなかった。
取得して値を変更する場合はどのようなAPIを使用すればよいか教えてほしい
[Attachment Removed]
再現手順
【状況】
下記の2つのレベルを作成した。
レベルA : ワールドパーティションの設定されたレベル
レベルB : オブジェクト等が配置されているレベル、オブジェクトの表示/非表示はデータレイヤーで管理している
ゲームを開始してレベルAをパーシスタントレベルとしてレベルBを動的にロードするようなプログラムを作成して
ロード後にレベルBに存在するオブジェクトをレベルBに設定されているデータレイヤーの値を編集して
非表示にする処理をかいた
実際の処理
//パーシスタントレベルAにレベルBをロード
auto* loaded_levelB = ULevelStreamingDynamic::LoadLevelInstance(GetWorld(), _level_b_name, FVector::Zero(), FRotator::ZeroRotator, result);
//ロード後にレベルBに設定されている特定の名前のデータレイヤーの値を編集
if (auto* DataLayerSubsystem = GetWorld()->GetDataLayerManager())
{
// データレイヤーの配列から特定の名前のものをActiveに
for (auto* ele : DataLayerSubsystem->GetDataLayerInstances())
{
// 名前を取得
FString LayerName = ele->GetDataLayerShortName();
if (ele->GetDataLayerShortName().Contains(_name.ToString()))
{
// 状態を有効化(Loaded + Visible)
DataLayerSubsystem->SetDataLayerInstanceRuntimeState(ele,EDataLayerRuntimeState::Activated);
}
}
[Attachment Removed]
お世話になっております。
ランタイムで動的にストリームインされたレベルインスタンスは、メインレベルのワールドとは別の独立したワールドパーティションとなり、独自のセルやストリーミングポリシーを保持します。そのため、たとえ同じデータレイヤーアセットを使用してレイヤー分けを行っていたとしても、内部的には別空間のレイヤーとして扱われ、メインワールドのデータレイヤーマネージャからは直接参照・操作ができない仕様となっております。
[Image Removed]
今回の場合、「ロードされたレベルインスタンスが属するワールド」のDataLayerManagerを取得する形に冒頭を書き換えていただければ、ご要件を満たせるかと存じます。
// ここだけ変更
- if (auto* DataLayerSubsystem = GetWorld()->GetDataLayerManager())
+ if (auto* DataLayerSubsystem = UDataLayerManager::GetDataLayerManager(loaded_levelB->GetLoadedLevel()))
{
// データレイヤーの配列から特定の名前のものをActiveに
for (auto* ele : DataLayerSubsystem->GetDataLayerInstances())
{
// 名前を取得
FString LayerName = ele->GetDataLayerShortName();
if (ele->GetDataLayerShortName().Contains(_name.ToString()))
{
// 状態を有効化(Loaded + Visible)
DataLayerSubsystem->SetDataLayerInstanceRuntimeState(ele,EDataLayerRuntimeState::Activated);
}
}
以下、補足事項となります。参考までにご覧ください。
・メインレベルに「埋め込み(Embeded)」で配置したレベルインスタンス(ドラッグ&ドロップで配置したもの)は、メインワールドに統合されるため、メインワールドのデータレイヤー体系でそのまま制御が可能です。
・動的にロードされたレベルインスタンスのレイヤー操作に関する議論が以下のスレッドで行われております。
[Content removed]
・任意のワールドコンテキストからDataLayerManagerを取得する処理をブループリントでも行えるようBPライブラリの整備が継続的に行われております。CL49765264で、指定オブジェクトのワールドコンテキストのDataLayerManagerが取得可能なノードが追加されましたので、今回ご提示いただいた要件をブループリントのみで実装すること可能になりました。
以上、よろしくお願いいたします。
[Attachment Removed]
ありがとうございます。
やりたいことができました。
関連して最後に一点質問させて下さい、サブレベルのデータレイヤーを動的に編集できるようになるタイミングですが
下記のようにロード完了後に登録したデリゲート以降であれば
問題ないという認識でよろしいでしょうか、それとも何らかのシステムフラグをみてから編集するのがよいのでしょうか?
loaded_levelB ->OnLevelLoaded.AddUniqueDynamic(this, &ThisClass::OnInstanceLoaded);
[Attachment Removed]
ありがとうございます。
助かりました。本件クローズでおねがいします。
[Attachment Removed]
お世話になっております。
最終的にはケース・バイ・ケースになるかと存じますが、OnLevelShownをお使いいただいたほうが、より完全に準備の整った状態の(データレイヤーを含む)レベルインスタンスにアクセス可能になるかと思います。
ただし、こちらのデリゲートではレベルに対するHidden→Show操作にも反応して呼び出される(複数回呼び出される可能性がある)点にご注意ください。
以上、よろしくお願いいたします。
[Attachment Removed]
回答のご確認ありがとうございます。
それでは本件は回答済みとしてCloseさせていただきます。
以上、よろしくお願いいたします。
[Attachment Removed]