鈴木です。GameOfThronesが面白くて寝不足です。
#レプリケーションはアクター単位でサーバーから送信される
アクターのプロパティのレプリケートはTick毎に幾つかのアクターが指名されて送信されます。
SimulateProxyアクターを持つクライアント上での処理で、自分以外の複数のアクター内のレプリケート変数にアクセスするような処理がある場合、プロパティの更新タイミングのズレによって問題が出たりする事があります。
※根本的には次アクター外に強い依存関係があるのは好ましくありません
##図解
ThePawnとTheActorのそれぞれが持っているプロパティLastPowerとPowerがシンクロしているのを期待しているとした時の挙動です。
※悪い設計の例です
サーバー側ではThePawnとTheActorは連続して処理されていますが、
クライアント側ではレプリケートはアクター単位で行われるのでLastPowerとPowerプロパティがアクター間でシンクロしていないタイミングが生まれます。
複数のアクターにまたがるような変数アクセスを行う場合はこのようなタイミングのズレがあるので可能な限り避けるのが懸命です。
#サーバー上での処理順序とRepNotifyの処理順序は一致しない
RPCは処理順序が保証されますがRepNotifyは順序は保証されません
例としてサーバーとクライアントでの処理の流れを書いてみます。
-
サーバー
- Pawn::SetValueA(B)
- OnRep_ValueB() ※ローカルで呼び出し
- Pawn::SetValueA(10)
- OnRep_ValueA() ※ローカルで呼び出し
- PawnAのプロパティをレプリケート
- Pawn::SetValueA(B)
-
クライアント
- クライアントでパケット受信
- プロパティをPawnAにストア(ValueA:10 ValueB:5)
- PawnAに対してRepNotifyを呼び出す
- OnRep_ValueA
- OnRep_ValueB
クライアント側でサーバーRPCの順序でRepNotifyが起こることを期待するとバグの原因になります。
また値が全てストアされてからRepNotifyが呼ばれるため
それぞれのRepNotify中でトリガー対象となった対象の別の変数にアクセスする場合も注意が必要です。
RepNotiyの呼ばれる順序はUClass内のプロパティリストの並び順に依存する気がします。
#参考