Skip to main content

Manual Packet Networking

Documentation version: 0.3.6

:::caution Experimental [LCGPacket] / LCGNetworkZone networking is experimental — its wire protocol may change between versions (currently protocol v2). :::

[LCGPacket] does not use native Udon variable sync. It adds versioned frames, authority checks, replay protection, field coalescing, verified-sender callbacks, and targeted PlayerObject delivery.

Packet fields​

Coalesced field with callback:

[LCGPacket(
Authority = LCGPacketAuthority.ObjectOwner,
Callback = nameof(OnScoreChanged))]
[SerializeField] private int score;

public void OnScoreChanged(VRCPlayerApi sender) { /* verified sender */ }

// Repeated assignments in one frame send only the latest value:
score++; score++; score++; // → one packet with final value
ForceSendPacket(nameof(score)); // → bypass suppression, always send
  • Assigning a packet field queues a send — repeated assignments in one frame are coalesced to the latest value; unchanged values are skipped.
  • ForceSendPacket(nameof(field)) bypasses suppression.
  • Packet field writes require object ownership — call Networking.SetOwner(Networking.LocalPlayer, gameObject) first.

Packet methods​

Broadcast vs. targeted delivery:

// Broadcast to everyone else (lowered to mailbox delivery because of [LCGPacket])
SendCustomNetworkEvent(NetworkEventTarget.Others,
nameof(ReceiveAnnouncement), "Broadcast #1", transform.position);

// Targeted delivery to one player
SendLCGNetworkEvent(target, nameof(ReceiveAnnouncement),
"Targeted #1", transform.position);

// Direct call is always local — no packet created
ReceiveAnnouncement("Local-only #1", transform.position);

[LCGPacket(Authority = LCGPacketAuthority.Any)]
public void ReceiveAnnouncement(string message, Vector3 origin) { }

Public void methods support up to eight supported arguments.

Delivery internals​

  • Packet methods are delivered through a PlayerObject mailbox; SendCustomNetworkEvent(...) is lowered to packet delivery only when the target method has [LCGPacket].
  • Frames are versioned and validated with authority checks and replay protection.
  • Owners provide snapshots when players are restored; departing-player state is discarded.

Network zones​

Add LCGNetworkZone to a trigger collider to restrict descendant packet recipients and ownership to players inside the trigger. Inside zones, VRC_ObjectSync is replaced with a manual relay; script transforms sync on demand via LCGNetwork.RequestObjectSync(gameObject) (pickups sync automatically while held).

Snapshot and ownership recovery​

  • Entering a zone and OnPlayerRestored request current scene-field and object snapshots. Recovery makes up to five additional attempts with bounded backoff, stops on exit, and restarts after a relevant restore event.
  • When a player disconnects, ownership callbacks repair VRChat reassignment to an outside player during a finite recovery window. Valid ownership by an existing member is preserved; an empty zone keeps VRChat's fallback owner until a member enters.
  • Departing players are matched by identity before player ID, preventing invalid or reused ID collisions from removing the wrong member.

Object motion transport​

Object motion uses a latest-state queue separate from the gameplay RPC FIFO. An unsent sample for the same object and recipient replaces the older sample, while teleport and re-entry discontinuities are preserved. Batches carry up to 900 bytes for one recipient. The scene-wide motion scheduler sends at most 40 events per second and budgets approximately 6 KB per second; it backs off when networking is clogged or the SDK outgoing queue exceeds eight events.

These limits apply to LCG motion, not unrelated gameplay packets or native Udon traffic. More recipients share the same budget, so the delivered sample rate falls as a zone fills. Remote objects interpolate samples with bounded velocity prediction, and remote rigidbodies stay kinematic until local ownership begins.

LCGRuntime.PendingMotionCount, MotionBatchesSent, and LastMotionBatchBytes expose local transport diagnostics. They are implementation diagnostics, not delivery acknowledgements or a public throughput guarantee. Validate crowded-world FPS and latency with multiple VRChat clients.

Zone rules:

  • Zone colliders in separate hierarchies may overlap — each scene object belongs to its nearest ancestor zone.
  • Zone colliders in the same parent/child hierarchy may not overlap; that configuration fails the build before helpers are generated.

Third-party behaviours that use native [UdonSynced] fields remain fail-closed by default. For compatibility with an existing hierarchy, enable Allow Native Sync Passthrough (LCGNetworkZone.allowNativeSyncPassthrough). This preserves native VRChat synchronization while the zone still scopes LCG packets, ownership, and converted VRC_ObjectSync traffic. Those native fields remain instance-wide rather than zone-scoped, and the build emits a warning.

Continuous Udon behaviours with no synced fields are accepted automatically. Zones still fail closed on Udon Graph behaviours, native synced fields without the opt-in passthrough, overlapping parent/child zones, and PlayerObject templates sharing a hierarchy.

Diagnostics​

LCG network logging is off by default. Enable Edit > Project Settings > Udon Sharp > Debugging > LCG network diagnostics before compiling to include pickup and packet-delivery output, then recompile UdonSharp programs.

Upgrades​

The packet protocol is versioned (v2). After upgrading LCGUdonSharp, recompile all UdonSharp programs and rebuild the world. Builds older than 0.3.6 cannot decode the motion batch envelope.

See also​