Photon Fusion's [Networked] Attribute: What It Actually Buys You (and What It Costs)
Photon Fusion's [Networked] attribute replaces manual snapshot serialization with tick-aligned, delta-compressed state sync — but only if you respect state authority and watch the per-tick bandwidth cost.
13 Jan 2026, 04:10 UTC
![Photon Fusion's [Networked] Attribute: What It Actually Buys You (and What It Costs)](/_next/image?url=%2Fmedia%2Fgenerated%2F1355f972-05a6-40d6-8b73-6faab769df86.webp&w=3840&q=75)
If you've ever hand-rolled multiplayer state sync over raw sockets, you know the drill: serialize a struct, diff it against the last snapshot, pack it into a packet, handle ordering, handle loss, repeat for every entity type. Photon Fusion's pitch is that you stop doing that. Mark a C# field with [Networked] inside a NetworkBehaviour, and the engine tracks changes, delta-compresses them, and delivers them to every peer tied to a simulation tick. This post looks at what that abstraction really does, where state authority fits in, and where the convenience starts costing you bandwidth.
What [Networked] actually does
A field decorated with [Networked] is not a normal field. Fusion's IL weaving step rewrites it into a property backed by the object's networked state buffer. Every write goes into that buffer, and every tick Fusion compares the buffer against the previous snapshot. Only the changed portions are transmitted — that's the delta compression — so a 200-byte state struct that had one integer change doesn't cost you 200 bytes on the wire.
The second thing it buys you is tick alignment. Networked state is versioned by simulation tick, not wall-clock time. That's what makes client-side prediction and interpolation coherent: when a client renders a remote player, it can blend between two authoritative snapshots at known ticks instead of guessing when a packet arrived.
A minimal worked example
Here's the smallest useful case: a health value on a spawned entity. The script lives on a prefab that also has a NetworkObject component, and the prefab is registered in Fusion's Network Project Config so it can be spawned across the session.
using Fusion;
public class Health : NetworkBehaviour
{
[Networked] public int Current { get; set; }
public override void Spawned()
{
if (Object.HasStateAuthority)
Current = 100; // only the authority initializes state
}
public void ApplyDamage(int amount)
{
// Gate writes behind authority. Without this check,
// a client's local write is just a local lie.
if (!Object.HasStateAuthority) return;
Current = UnityEngine.Mathf.Max(0, Current - amount);
}
}Run this in the Unity Editor with a second client (a standalone build or Fusion's multiplayer peer mode). Spawn the prefab from the host, call ApplyDamage(25) on the host, and confirm the remote client's Current reads 75 within a tick or two. The check that matters: Object.HasStateAuthority must be true on exactly one peer for that object. If two peers think they hold authority, your spawn/topology setup is wrong, not the attribute.
State authority is the part people skip
In Fusion's Host/Server mode, one peer holds state authority over each NetworkObject. Everyone else receives the state as input or as interpolated snapshots. This is the security boundary: the authority's version of Current is the truth, and client writes to networked properties don't propagate to others by default.
The practical rule: anything a cheater would want to modify — health, ammo, currency, hit validation — must only be written by the authority, derived from client input (via GetInput/NetworkInput) rather than client state. The moment you let a client directly write a networked field that others trust, you've handed the game to anyone with a memory editor. Input is the only thing clients should own.
The bandwidth trade-off
The attribute is cheap to add, which is exactly the problem. Every networked property adds per-tick tracking overhead, and high-frequency fields (a float updated every tick on fifty objects) add up fast even with delta compression. A few guidelines that hold up in practice:
- Network outcomes, not intermediates. Sync the resulting position or the final score, not every scratch variable used to compute them.
- Prefer smaller types. A
byteor a quantized float costs less than a fullfloatwhen it changes every tick. - Measure before optimizing. Fusion's Network Profiler shows bytes per tick per object — add one property at a time and watch the delta rather than guessing.
The other cost is rubber-banding. Predicted clients simulate locally and reconcile against authoritative snapshots; if your prediction logic diverges from the authority's simulation (different physics settings, authority-only branches), players see their character snap back. Keep the predicted code path identical on both sides, and test under artificial latency — a tool like Clumsy on Windows, or your OS equivalent — because a LAN test will hide every reconciliation bug you have.
Limitations worth knowing up front
Networked properties must live in a NetworkBehaviour and be auto-implemented properties ({ get; set; }) — the weaver can't intercept a plain field with custom logic. Complex types need to be blittable or explicitly supported; arbitrary reference types won't serialize. And none of this removes the authority design work: Fusion transports state faithfully, but deciding who is allowed to change it is still your job.
Closing
Start with one prefab, one [Networked] integer, and two peers. Verify sync, then open the Network Profiler and add properties one at a time while watching bytes per tick. That feedback loop — attribute, profile, decide — is the real workflow, and it will teach you more about Fusion's cost model than any amount of upfront architecture. Note that APIs shown here reflect Fusion's current 2.x conventions; check the changelog if you're on an older SDK, since attribute behavior and authority APIs have shifted between major versions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.