概要
Client 側で Network Rigidbody などの Interpolation Data Source を Snapshots にすると、Interpolation Target は Collider の後ろをなぞるような挙動になります。
その状態で衝突音を実装すると、見た目より早く音が鳴ってしまいます。
この問題を解決するために、イベントの発行を Interpolation にかかる時間だけ遅らせるクラス InterpObservableQueue を作りました。UniRx を使っています。
不具合や改善案、「その機能もうあるよ」といったコメントをいただけると助かります。
コード
関数説明
関数/プロパティ | 説明 |
---|---|
InterpObservableQueue<T>() | コンストラクタです。 Spawned() 上で初期化してください。 第二引数でイベント発行の条件を決められます。 |
Enqueue() | イベントの発行で使う引数の情報を追加します。 本来呼びたかった関数を実行するタイミングでこの関数を呼んでください。 |
UpdateQueues() | 保持している引数情報のうち、実行可能なイベント FixedUpdateNetwork() で呼んでください。 |
Observable | 購読先になる Observable です。 Spawned() で購読し、本来呼びたかった関数を実行するなどしてください。 |
ClearQueue() | 保持している引数情報を空にします。 |
Kill() | 全ての変数を null または空にして、利用不能にします。 |
利用例
衝突したコライダーの名前をログに出す例です。
using Fusion;
using UniRx;
using UnityEngine;
using Yamara;
public class InterpObservableQueueSample : NetworkBehaviour
{
InterpObservableQueue<Collision> onCollisionEnterQueue;
public override void Spawned()
{
base.Spawned();
var isPredicted = InterpolationDataSource == InterpolationDataSources.Predicted;
onCollisionEnterQueue = new(Runner, isPredicted, collision => collision != null);
onCollisionEnterQueue.Observable.Subscribe(collision => Debug.Log(collision.gameObject.name)).AddTo(this);
}
public override void FixedUpdateNetwork()
{
base.FixedUpdateNetwork();
if (Runner.IsForward) onCollisionEnterQueue.UpdateQueues();
}
private void OnCollisionEnter(Collision collision)
{
if (Runner.IsForward) onCollisionEnterQueue.Enqueue(collision);
}
}
if (Runner.IsForward)
は無くても一応同じように動きますが、ぱっと見で実行タイミングが分かりやすくなるので加える事を推奨します。