Physicsアドオン(Fusion 2.1用)
このアドオンはFusion 2.1.x用です。Fusion 2.0.xではサポートされません。(2.0用のアドオン)
これはホスト/サーバーモード専用です。共有モードについては、物理をご覧ください。
概要
Physicsアドオンは、Rigidbodyのクライアントサイド予測に必須のコンポーネントが含まれています。
Fusion 2.1は、NetworkTransformで物理を同期する方法が2つ組み込まれています。詳細な情報は物理をご覧ください。
大抵のケースでは、組み込みのモードで十分です。アドオンのクライアントサイド予測モードは、高精度のリアルタイム物理インタラクションをサポートしますが、物理ステップの再シミュレーションは非常にCPU負荷が高くなります。
ダウンロード
| Version | Release Date | Download |
|---|---|---|
| 2.1.0 | 11月 13, 2025 | Fusion Physics 2.1.0 |
物理シミュレーション
物理シミュレーションは、FixedUpdateNetwork()中に再シミュレーションティックとフォワードティックの両方で実行され、オブジェクトをローカル時間で予測します。これによって、ローカルのプレイヤーと物理オブジェクト間のインタラクション精度は非常に高くなりますが、複数の物理ステップをシミュレートする分だけCPU負荷も高くなります。
主要コンポーネント
NetworkRigidbody:状態権限者のRigidbody/Rigidbody2Dの状態を、他のピアに同期します。RunnerPhysicsSimulate:NetworkRunnerゲームオブジェクトに追加するコンポーネントで、Fusionの物理シミュレーションを処理します。
Usage
NetworkRigidbodyコンポーネントを使用するには、以下の手順に従ってください。
Rigidbody/Rigidbody2Dが付いたプレハブまたはシーンオブジェクトに、NetworkRigidbodyを追加してください。このコンポーネントは、状態権限者のRigidbodyの状態を他のピアへ複製したり、Rigidbodyに対するクライアントサイド予測・ロールバック・再シミュレーションを処理します。NetworkRunnerプレハブに、RunnerSimulatePhysicsを追加してください。このコンポーネントが、UnityのPhysics.Simulate()を引き継ぐようになります。実行時にNetworkRigidbodyが付いたプレハブをスポーンすると、NetworkRunnerにインスタンスが自動的に追加されます。- すべてのシミュレーションコードが、
FixedUpdateNetwork()内で実行されていることを確認してください。
NetworkRigidbody
状態権限者のRigidbody/Rigidbody2Dの状態を、他のピアに同期するコンポーネントです。Rigidbodyと同じゲームオブジェクトに追加する必要があります。NetworkTransformなどの他のNetworkTRSPコンポーネントとは共存できません。テレポート操作を除き、「力を加える」「速度を設定する」などの操作は、状態権限者のRigidbodyに対して直接行う必要があります。このコンポーネントが追加されたネットワークオブジェクトは、Fusionで予測されたローカル時間で常にシミュレートする必要があり、これはSpawned()で強制されます。
同期されるプロパティは以下の通りです。
- Linear Velocity
- Angular Velocity
- Kinematic
- Constraints
他の値を同期したい場合は、独自のNetworkBehaviourを使用して手動で同期してください。
Area of Interest(関心領域)
NetworkRigidbodyはNetworkTRSPクラスを継承しているため、すべての関心領域(AOI)処理が有効です。関心領域の仕様については、マニュアルのNetworkTRSPをご覧ください。
スケールの同期
有効にすると、transform.localScaleが同期されます。
親子関係の同期
有効にすると、transform.parentが同期されます。Rigidbodyの親を持つRigidbodyは、キネマティックに設定されます。親子関係を設定したRigidbodyのAreaOfInterestOverrideは、自動的に親のネットワークオブジェクトに設定されます。
親子関係の同期には、いくつかの注意点があります。
- 親の
transformには、必ずNetworkBehaviourコンポーネントが必要です。親を見つけるために、NetworkBehaviourIdが使用されるからです。 NetworkRigidbodyは、ルートのネットワークオブジェクトにあることが必須です。(通常はそうなります)- 親の
transformを、ネットワークオブジェクトの子のtransformにすることができます。プレイヤーの手などが例です。
Interpolation Target
指定したtransformが、Render()間の補間に使用されます。これは通常、Rigidbodyの、Colliderを持たない子要素のtransformになります。
値をnullにすると、ルートのNetworkRigidbodyが補間に使用され、シミュレーションループ開始時にティック精度の位置が返るようになります。InterpolationTargetの値は、実行時にコードから変更することもできます。
子要素に対してInterpolationTargetを使用する利点は、補間によって物理演算のキャッシュがクリアされないことです。ただし、子要素のRigidbodyのスケールの同期が無効になります。
Rigidbodyで予期しない(摩擦や積み重ねの)挙動が発生することを避けるため、InterpolationTargetはnullにしておくことを推奨します。
InterpolationTargetが必要なケースは、以下の通りです。
MovePosition()を使用してキネマティックRigidbodyを動かす場合:InterpolationTargetを使用しない場合、transform.positionとtransform.rotationの更新によって補間が行われます。transformを直接変更すると、RigidbodyのMovePosition()の呼び出しが上書きされてしまいます。- 補間の影響を受けずに物理演算を行う必要がある場合:
Transformを直接移動させる補間は、Rigidbodyの静止摩擦やスリープモードなどに副作用を及ぼします。これはRender Sleep Thresholdsで軽減できますが、それでも許容できない干渉が発生することがあります。
InterpolationTargetを使用する場合は、Rigidbodyに干渉しないように、指定するオブジェクトにはColliderが含まれないことを確認してください(干渉を避けるためのInterpolationTargetだからです)。すべてのビジュアルエフェクトは、InterpolationTargetの方に合わせてください。
備考: スケールと親子関係の同期を同時に使用している場合、InterpolationTargetを使用すると正しい結果になりません。ゲームオブジェクトのスケールは、その親のスケールに影響を受けるため、コードで正しく複製することはほぼ不可能です。スケールの結果を正確に得るため、InterpolationTargetはnullのままにしておくことを推奨します。
備考: カメラをInterpolationTargetに追従させていないのは、よくある間違いです。カメラをInterpolationTargetに追従させることで、カメラの移動を補間できます。
Teleport()
NetworkTransform.Teleportをご覧ください。
RunnerSimulatePhysics
このコンポーネントをNetworkRunnerプレハブに追加して、Fusionの物理シミュレーションを処理できるようにします。
ヒエラルキー上でこのコンポーネントを持つ最初のNetworkRunnerが初期化されると、Unityプロジェクトの物理のautoSimulationが上書きされ、Fusionが物理シミュレーションを処理するようになります。最後のNetworkRunnerがシャットダウンされると、autoSimulationは元の値に復元されます。
NetworkRigidbodyがスポーンすると、NetworkRunnerにRunnerSimulatePhysicsインスタンスが(まだ追加されていない場合は)自動的に追加されます。
Time Scale
物理のSimulate()に渡される値の乗数です。1より大きい値で時間の経過が加速し、0~1で時間が遅くなります。
コールバック
OnBeforeSimulate / OnAfterSimulate
登録されたこれらのメソッドは、RunnerSimulatePhysicsがシミュレーションを行うたびに呼び出されます。
C#
using Fusion;
using Fusion.Addons.Physics;
using UnityEngine;
public class FusionPhysicsAddonExample : NetworkBehaviour
{
private RunnerSimulatePhysics _physicsSimulator;
public override void Spawned()
{
// Get our RunnerSimulatorPhysics instance (this needs to be added to the Runner)
_physicsSimulator = Runner.GetComponent<RunnerSimulatePhysics>();
// Register callback for EVERY simulation tick, be careful as these can be called quite frequently.
_physicsSimulator.OnBeforeSimulate += OnBeforeEverySimulate;
_physicsSimulator.OnAfterSimulate += OnAfterEverySimulate;
}
public override void Despawned(NetworkRunner runner, bool hasState)
{
// Unregister (a good practice)
_physicsSimulator.OnBeforeSimulate -= OnBeforeEverySimulate;
_physicsSimulator.OnAfterSimulate -= OnAfterEverySimulate;
}
private void OnAfterEverySimulate(NetworkRunner runner) {
// Implement code to execute after every Physics.Simulate
}
private void OnBeforeEverySimulate(NetworkRunner runner) {
// Implement code to execute before every Physics.Simulate
}
}
Fusion 2.0.X から Fusion 2.1.X への移行
NetworkRigidbody3D/NetworkRigidbody2DをNetworkRigidbodyコンポーネントに置換します。RunnerSimulatePhysics3D/RunnerSimulatePhysics2DをRunnerSimulatePhysicsに置換します。
既知の問題
- 子
Rigidbodyの物理挙動は(キネマティックに設定されていても)予測困難で、Rigidbodyがシミュレーション前の位置にあったかのような形で、オブジェクトと衝突することがあります。そのため子要素は、Colliderを無効にし、コリジョンには依存させないことを推奨します。 - 子要素のスケールは、
InterpolationTargetを持たないすべての親要素に依存します。子要素のスケーリングとInterpolationTargetを組み合わせて使用したい場合は、InterpolationTargetをルートから切り離し、親子関係を再設定する独自のコードを記述する必要があります。基本的には、すべてのRigidbodyのCollider/Transform階層(InterpolationTargetを含む)のコピーを作成します。 MovePosition()とMoveRotation()は、InterpolationTargetを使用する必要があります。ただし、transform.position/transform.rotationの値を直接設定して、キネマティックRigidbodyを動かすなら、その必要はありません。