the symptom, in your words

"Rpc.Broadcast on a non-networked GameObject runs locally only -- no warning"

✓ verified on engine 26.07.08elane: Writing gameplayposted

▸ SYMPTOM

An [Rpc.Broadcast] (or any instance RPC) fires on the host and the effect appears locally, but the connected client receives nothing. No warning, no error -- the RPC silently never crosses the wire. The same RPC on a snapshot-networked object works fine in the same session.

▸ CAUSE

The GameObject is not networked. A bare scene.CreateObject() without a NetworkSpawn call creates a host-local object. RPCs on a non-networked component execute on the caller and silently skip the network hop -- the engine does not log a warning at Info or Warn level.

The false-confidence trap: because the RPC runs locally on the host, you see the expected effect on the host side and may assume it reached all peers. Without a dedicated receipt log on the receiving client, the failure is invisible.

▸ FIX

Network the object before calling any cross-peer RPC on it:

snippet
var go = scene.CreateObject();
go.Components.Create<MyComponent>();

if (Networking.IsActive)
    go.NetworkSpawn(); // host-owned; now exists as a proxy on every client

// [Rpc.Broadcast] calls on MyComponent now cross the wire

Guard NetworkSpawn behind Networking.IsActive so the solo (non-networked) path stays byte-identical -- !IsActive skips the spawn, the RPC runs locally as before.

To verify a cross-wire RPC is actually received, add a deliberate log line on the receiving side and grep the client's log:

snippet
[Rpc.Broadcast]
void ApplyImpactNet(Vector3 impulse)
{
    Log.Info($"[mp] impact RECV proxy id={GameObject.Id} impulse={impulse.Length:F1}");
    // apply effect...
}

The absence of a network-hop warning on the host is NOT evidence the RPC crossed. Only a receipt on the other peer proves it.

▸ WHY IT WORKS

NetworkSpawn registers the object with the networking system so it exists as a proxy on every connected peer. RPCs are dispatched through the network layer's object table -- an unregistered object has no entry, so the dispatch silently returns after running the local call. Once the object is network-spawned, its RPCs route through the wire to every peer's proxy copy.

Verified on engine 26.07.08e: seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?

Want to know when new guides or fixes drop? Join the community to help build this out. Report gotchas, flag outdated fixes, or just lurk.

Join the Discord