Plug n' play components

Network Rigidbody

This component allows you to very easily utilize the Rigidbody over the network. It helps sync the actual forces of the Rigidbody, and utilizes physics to smoothly align it across the network.

If you need physics in multiplayer, you might want to read the Physics In Multiplayer page

Settings

It's a highly dynamic component, so although the default settings should work well for a lot of cases, it's recommended to familiarize yourself with what the various settings do.

A lot of values behind the scenes are modified dynamically, which is why so many settings are exposed. Things like a flat acceptable error threshold or hard correction threshold, yielded bad results during collision and faster movement, which is why the acceleration settings help to dynamically expand the acceptable ranges during big acceleration changes.

SettingEffect
Owner AuthDecides who holds the truth of the simulation. If true, the owning client calculates physics (Client Auth). If false, the server does (Server Auth).
Interpolation DelayHow far behind real-time (in seconds) the interpolation target sits. Higher values absorb more network jitter but add visual latency. Default: 0.05s.
Prediction FactorPushes the target position forward using velocity to compensate for interpolation delay. 0 = no prediction, 1 = compensate for the full interpolation delay, >1 = predict further ahead. The offset is deterministic and identical on all machines.
Position StrengthHow aggressively the rigidbody chases the target position. Acts as the natural frequency of a critically-damped spring. Higher values = tighter tracking but stiffer feel. The steady-state tracking lag is approximately velocity / strength.
Correction RangeThe distance over which position correction ramps from zero to full strength. Larger values give softer correction, letting local collisions play out naturally before being pulled back. Smaller values give tighter snapping.
Rotation StrengthHow aggressively the rigidbody corrects rotation errors. Works the same way as position strength but for angular correction.
Hard Snap DistanceIf the position error exceeds this distance, the rigidbody teleports to the target instead of using forces. Acts as a safety net for large desync.
Hard Snap AngleIf the rotation error (degrees) exceeds this threshold, the rotation snaps instantly instead of using torque. Set to a negative value to disable rotation snapping entirely.
Acceptable Rotation ErrorRotation error (degrees) below which rotation correction stops, preventing micro-jitter at rest. Set to a negative value to disable rotation correction entirely.
Position Change ThresholdMinimum distance the rigidbody must move before triggering a network update. Prevents unnecessary updates while stationary.
Rotation Change ThresholdMinimum angle the rigidbody must rotate before triggering a network update.
Velocity Stop ThresholdIf both linear and angular velocities are below this value, the object is considered stopped and will cease sending updates.

Teleporting

Regular physics operations (position, rotation, MovePosition, MoveRotation, AddForce, etc.) are synced automatically through the normal state sync and should be used for all regular gameplay movement. For instant repositioning like respawns or portals, use the explicit TeleportTo method:

// Teleport to a new position and rotation (clears buffer, syncs instantly)
networkRb.TeleportTo(spawnPoint.position, spawnPoint.rotation);

// Teleport to just a new position (keeps current rotation)
networkRb.TeleportTo(respawnPosition);

TeleportTo differs from setting position/rotation directly in that it:

  • Zeros out linear and angular velocity
  • Clears the interpolation buffer on all observers
  • Sends a reliable RPC so the teleport is never missed
  • Prevents the spring from trying to smoothly chase a position that was meant to be instant

If you're replacing a Rigidbody reference with NetworkRigidbody, you do not need to change any of your existing MovePosition, MoveRotation, or AddForce calls — they work identically. Only use TeleportTo when you specifically need an instant, non-physical reposition.

Position transforms (origin-shifted / large worlds)

By default, an unparented NetworkRigidbody puts its raw Unity world-space position on the wire. That is fine for ordinary scenes, but it breaks down in two cases:

  • Origin-shifted worlds — each peer runs with a different local Unity origin (a common technique for large or streaming worlds), so a raw Vector3 from one peer is meaningless on another.
  • Very large coordinates — a 32-bit float loses precision long before a large world reaches the limits of double precision.

A position transform solves both. It is a pluggable converter, invoked only at the wire boundary, that maps outgoing positions into a shared, peer-agnostic absolute frame (a double3) and maps incoming absolute positions back into the receiving peer's Unity world space. The absolute double3 is what travels on the wire and what the interpolation buffer stores, so a local origin shift needs no extra bookkeeping — the next conversion simply reflects the new offset and every buffered snapshot stays correct.

Only translation is converted; rotation and velocity are already origin-invariant. Parented rigidbodies are also unaffected — parent-local coordinates are origin-invariant, so they keep using the legacy path regardless.

Implement INetworkRigidbodyPositionTransform:

using PurrNet;
using Unity.Mathematics;
using UnityEngine;

public class OriginShiftTransform : MonoBehaviour, INetworkRigidbodyPositionTransform
{
    // Sender side: this peer's Unity world space -> shared absolute frame.
    public double3 ToAbsolute(NetworkRigidbody self, Vector3 localWorldPos)
    {
        var origin = WorldOrigin.Current; // your peer's double3 origin offset
        return new double3(localWorldPos.x, localWorldPos.y, localWorldPos.z) + origin;
    }

    // Receiver side: shared absolute frame -> this peer's Unity world space.
    // Must be the exact inverse of ToAbsolute for the current origin.
    public Vector3 ToLocal(NetworkRigidbody self, double3 absolutePosition)
    {
        var local = absolutePosition - WorldOrigin.Current;
        return new Vector3((float)local.x, (float)local.y, (float)local.z);
    }
}

A transform is resolved on spawn, first non-null wins:

  1. A runtime override set via networkRb.SetPositionTransform(transform).
  2. A sibling component implementing INetworkRigidbodyPositionTransform on the same GameObject.
  3. The process-wide static fallback NetworkRigidbody.defaultPositionTransform.
// Apply to every NetworkRigidbody in the process (set this once at startup).
NetworkRigidbody.defaultPositionTransform = new OriginShiftTransform();

// Or override a single instance at runtime; pass null to fall back to the chain.
networkRb.SetPositionTransform(myTransform);

The transform must be configured consistently across all peersToAbsolute/ToLocal must agree on the absolute frame, and ToLocal must be the exact inverse of ToAbsolute for the current origin. A sibling component on a shared prefab or the static default both satisfy this; setting it asymmetrically (on some peers only) will make objects snap to the origin.

A runtime override set with SetPositionTransform is not retained across a despawn/respawn — pooled objects re-run the resolution chain. Prefer a sibling component or the static default if you need it to persist.

When no transform is installed, positions travel on the wire exactly as in previous versions (a quantized CompressedVector3 in the peer's own world space) — the feature is fully opt-in and the legacy path is byte-identical to prior behaviour.