LoginSignup
1

More than 5 years have passed since last update.

ネットワーククライアント上でのRepnotifyとBeginPlayのタイミング

Last updated at Posted at 2018-07-06

鈴木です。
マルチプレイクライアント上でのBeginPlayやPostInitComponentの呼び出しタイミングはシングルプレイ時と差があり
マルチプレイを考慮していないといろいろな問題が出たり出なかったりします。

シングルプレイ時の処理順序

  • アクターのSpawnリクエスト
  • SpawnActor
  • (DeferConstruction)
    • ユーザー初期化コード
  • PostActorConstruction
  • PreInitComponent
  • PostInitComponent
  • BeginPlay

マルチプレイ時の処理順序

マルチプレイ時はパケット受信後にそのオーダーに合わせて初期化が行われます。
DeferConstructionは処理できません
注目すべきはプロパティのストア位置とRepNotifyがBeginPlayの前に呼ばれることと、SpawnParamterなどのプロパティ適用がPostInitComponentなどの後に行われうことです。

  • パケット受信
  • SpawnActor
  • PostActorConstruction
  • PreInitComponent
  • PostInitComponent
  • ReceiveBunch
    • プロパティをアクターにストア
    • RepNotifyを処理
  • PostNetInit
    • BeginPlay

このような流れになっています。シングルプレイやAuthorityを持っているプロセス上では初期化処理はストレートに行われますが、
クライアントではBeginPlayの前にさまざまなユーザーコードが実行される余地があるため問題が発生しやすいです。
この流れを考慮してあるとスムーズにマルチプレイゲームが構築できるかもしれません。

BeginPlay前のRepNotifyについて

RepNotifyがBeginPlayなどに依存する場合、正しく処理できない可能性があります。
コールバック関数が呼び出される前にユーザーコードを挟む余地があれば初期化等をおこなって正しく処理出来そうです。
RepNotifies処理部近辺を探してみるといいのがありました


void FObjectReplicator::PostReceivedBunch()
{
...
    if (!bIsServer && bHasReplicatedProperties)
    {
        PostNetReceive();  <----------------------------
        bHasReplicatedProperties = false;
    }
...
    // Call RepNotifies
    CallRepNotifies(true);

これだよこれ。
virtual void UObject::PostNetReceive()

こいつで初期化コードを処理すればいい感じ。

ただしAutorityやシングルプレイ時には呼び出され無いので注意が必要です

このあたりはBlueprintだと対処しにくいかもしれません。

糸冬

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1