ワールドパーティションでワープするときに表示されるローディング画面について

ワールドパーティションで遠くへワープをするとき、地形の読み込み待ちが発生し、​FDefaultGameMoviePlayerでローディング画面が表示されると思います。

このローディング画面が2回も呼ばれてしまうので、ワープ開始から終了まで1回だけ表示されるようにしたいです。

ワープするときの処理が良くないのか、ローディング画面を表示するタイミングや処理が良くないのか、判断が付かない状況でした。

正しい実装方法があれば教えていただくことは可能でしょうか。

ワープする時の処理は以下のように行っています。

```

​ACharacter* const Character = 操作しているキャラクターを取得;

TObjectPtr<UWorldPartitionStreamingSourceComponent> StreamingSourceComponent; // 外部から設定される

FVector WarpLocation; // ワープ先の座標​

GetMoviePlayer()->PlayMovie();

Character->SetActorTransform(WarpLocation, false, nullptr, ETeleportType::TeleportPhysics);

AActor* StreamingSourceActor = StreamingSourceComponent ? StreamingSourceComponent->GetOwner() : nullptr;

if(IsValid(StreamingSourceActor) && IsValid(StreamingSourceComponent))

{

StreamingSourceActor\-\>SetActorLocation(CharacterCenterLocation);



StreamingSourceComponent\-\>EnableStreamingSource();

}

TArray<FWorldPartitionStreamingQuerySource> WorldPartitionStreamingQuerySources = GetWorldPartitionStreamingQuerySource(WarpLocation);

auto TickTimer = [this, WorldPartitionStreamingQuerySources, Character]()

{

if (移動先で必要なアセットなどの読み込み完了か)

{



    // 弊社で必要なアセットなどの読み込み待ちをしている

    return;



}



GetWorld()\-\>BlockTillLevelStreamingCompleted();

const TObjectPtr\<UWorldPartitionSubsystem\> WorldPartitionSubsystem \= GetWorld()\-\>GetSubsystem\<UWorldPartitionSubsystem\>();

if (WorldPartitionSubsystem\-\>IsStreamingCompleted(EWorldPartitionRuntimeCellState::Activated,WorldPartitionStreamingQuerySources, false))

{



    GetMoviePlayer()\-\>StopMovie();

    // 読み込み完了後の処理

}

};

GetWorld()->GetTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateWeakLambda(this, TickTimer), 0.2f, true);

```

PlayMovieを用いてブロッキング処理にロード画面を表示するケースではタイマーなどを使わず直列に必要なロード処理をかくことになるはずです。上のコードではロード画面が開始された後、一旦関数を抜け1度目のロード画面が終了します。そのあとタイマーイベントが発火してBlockTillLevelStreamingCompletedから暗黙的に呼び出されるロード画面が表示されていると思われます。

暗黙的に呼び出されるロード画面はFStreamingPauseRenderingModuleにありますのでご参照ください。

なおFStreamingPauseRenderingModuleで登録されているロード画面をオーバーライドするにはGEngine->RegisterBeginStreamingPauseRenderingDelegateなどを上書きする必要があります。

またコード中にストリーミングソースの操作がなされていますが、プレイヤーコントローラーの持つストリーミングソースとほぼ同じ位置に配置されることになり特に意味を成さないと思われます。もしワープ前に先読みを行いたい場合ストリーミングソースを予め移動先に置いておく必要があります。

一般的なワールドパーティションマップでのワープのフローをブロッキングとシームレスのそれぞれのケースで示すと以下の様になります。

独自のローディング画面を表示しつつブロッキングでワープを行う

  1. ローディング画面表示開始
  2. (オプション)メモリ予算に余裕が無い場合
    1. ストリーミングソースを無効化
    2. BlockTillLevelStreamingCompleted内で実行されているようなストリーミング更新関数を必要に応じて呼び出し、更新を行う
    3. セルのアンロードが終わったらGCを実行する
  3. テレポートを行う(無効化されていたならストリーミングソースを有効化する)
  4. BlockTillLevelStreamingCompleted関数と同等の処理を含む関数を実行しストリーミング完了を待つ
  5. ローディング画面を削除する

シームレスでワープを行う場合には

  1. 移動演出を開始する(ブロッキング処理ではないのでPlayMovieは利用できません)
  2. プレイヤーコントローラーを含むストリーミングソースを無効化または縮小する
  3. 移動先に適切な範囲を持つストリーミングソースを配置する
  4. 移動先のストリーミングが完了するまで待機
  5. プレイヤーをテレポートさせる
  6. プレイヤーコントローラーのストリーミングソースを有効化または段階的に拡大する
  7. 移動先に追加したストリーミングソースを削除する
  8. 任意のタイミングで移動演出を終了する

ありがとうございます。

いただいた回答を元に試してみたいと思います。