Networked Objects

Networked objects (alongside RPCs) make up the bulk of what the networking library supports. Most games are built from a combination of networked objects for continuous synchronization (like positions and states) and RPCs for discrete events (like opening a door or firing a weapon).

In general, a networked object is a GameObject that exists on all clients connected to the server. When the object’s state changes on its owning machine, that information is sent through the server and broadcast to the other clients. This ensures all connected players see the same simulation.

A simple example is a player’s character: - When a character is instantiated on one client, it is also created on all other clients. - As the player moves, their character’s transform is synced across the network. - All other players see the character move smoothly in real time.

Instantiating

Instantiating a network object is similar to Unity’s built-in Instantiate(), but you must use ClientNetwork.Instantiate:

// Example: Instantiate a networked player object
GameObject player = clientNetwork.Instantiate(
    "PlayerPrefab",             // prefab name (must be in Resources/)
    spawnPosition,
    Quaternion.identity
);

Key differences from Unity’s Instantiate: - The first parameter is a string name of the prefab. - The prefab must be located in a Resources/ folder

(required for dynamic loading by name).

  • The networking system assigns a unique network ID for this object and registers it with the server and other clients.

Note

Unity discourages using Resources for modern projects. This system still works, but you may want to adapt it later to use Addressables or Asset Bundles for dynamic loading.

Server-instantiated objects

The server can also create objects. These objects are owned by the server by default and synchronized to clients. For more details, see the Ownership page.

Unique IDs and ID Pools

Every networked object has a unique network ID. To make this possible:

  • The server issues each client a pool of IDs (default size: 500).

  • When a client instantiates an object, it picks the next free ID from its pool.

  • The server keeps track of ID pools and replenishes them as needed.

This ensures immediate local instantiation (so players see their objects instantly) while still guaranteeing global uniqueness.

Destroying

Destroying a networked object must go through the networking layer, not Unity’s Destroy.

// Client destroys their own object
clientNetwork.Destroy(objectId);

This sends a Destroy message to the server, which in turn informs all other clients to remove the object.

If a client tries to destroy an object they don’t own: - The server checks ownership. - If the client is not the owner, the server may ignore the request

or send an OwnershipLost message back to the client.

This ensures only the authoritative machine can remove objects.

NetworkSync Component

All networked objects must include a NetworkSync component. This script provides:

  • Unique ID management – each object is tied to a global network ID.

  • Synchronization – sends position, rotation, and custom data to the server.

  • RPC routing – allows RPCs to target this object specifically.

  • Callbacks – methods invoked when the object is created, initialized, or destroyed.

Typical setup:

public class PlayerSync : MonoBehaviour
{
    NetworkSync sync;

    void Start()
    {
        sync = GetComponent<NetworkSync>();
    }

    void NetworkInitialized()
    {
        Debug.Log("NetworkSync ready with ID: " + sync.GetId());
    }

    void OnGainOwnership()
    {
        Debug.Log("Now controlling this object.");
    }

    void OnLoseOwnership()
    {
        Debug.Log("No longer controlling this object.");
    }
}

LiteSync

Sometimes you want to sync custom data without transform updates. For example, ammo count or animation state.

  • SyncUpdate – sends full transform + data.

  • LiteSyncUpdate – sends only the custom data payload.

This reduces bandwidth when positions/rotations are unchanged.

Extending Sync Data

NetworkSync lets you send extra byte data during sync messages:

byte[] extraData = BitConverter.GetBytes(currentHealth);
sync.SendSyncData(extraData);

On the receiving end:

void ReceiveSyncData(byte[] data, Vector3 pos, Quaternion rot)
{
    int health = BitConverter.ToInt32(data, 0);
    UpdateHealth(health);
}

Remote Procedure Calls on Objects

RPCs can be targeted at specific networked objects. This is useful when the event only relates to that object.

Example: making a chest open:

// Call RPC on a specific chest
chestSync.CallRPC("OpenChest", MessageReceiver.AllClients);

On each client, the chest GameObject must implement:

public void OpenChest()
{
    // Play animation, enable loot, etc.
}

Smooth Movement

Synchronization messages are sent periodically, not every frame. If you apply updates immediately, objects may appear to “teleport” or jitter due to latency.

Interpolation and extrapolation smooth out movement:

  • Interpolation: Render objects between the last two known positions.

  • Extrapolation: Predict the next position based on velocity if new data hasn’t arrived yet.

Example interpolation approach:

void Update()
{
    float t = (Time.time - lastUpdateTime) / updateInterval;
    transform.position = Vector3.Lerp(oldPos, newPos, t);
    transform.rotation = Quaternion.Slerp(oldRot, newRot, t);
}

Considerations: - Fast-paced games may need higher update rates. - Physics objects should be driven by the owner,

with remote clients only interpolating replicas.

  • Keep bandwidth in mind: syncing fewer objects at lower rates saves performance.

Summary

  • Networked objects are created with ClientNetwork.Instantiate.

  • Each object has a unique ID assigned from the server.

  • NetworkSync is required for tracking, syncing, and RPC routing.

  • Objects are destroyed through the networking system, not Unity’s Destroy.

  • LiteSync messages allow efficient custom data updates.

  • Smooth movement requires interpolation/extrapolation to hide latency.

  • Use RPCs for discrete events; use network sync for continuous state.