docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Netcode for Entities multi-driver architecture

    Netcode for Entities has a multi-driver architecture, allowing you to use multiple NetworkDrivers, stored in the NetworkDriverStore, at the same time.

    NetworkDriver configuration is designed to be customizable and is implemented using a delegate/strategy pattern. Netcode for Entities provides a default strategy implementation that can be changed by creating your own custom strategy class that implements the INetworkStreamDriverConstructor interface.

    The most common use cases for implementing a custom initialization strategy, or resetting the NetworkDriverStore, are usually:

    • Using Unity Relay for self-hosting and letting remote players connect to a local machine.
    • Listening to all interfaces on the server-side (to support connecting web and standalone).
    • Configuring the driver to use DTLS, as shown in the secure connection sample.
    Note

    When using web as a platform, Relay must be used to start listening for incoming connections. Relay is not required to connect your game to a deployed server using WebSocket.

    NetworkDriverStore

    The NetworkDriverStore struct stores NetworkDriver instances and, by default, is automatically configured by NetworkStreamReceiveSystem at world creation time.

    NetworkDriverStore allows up to three drivers to be used, each using a different INetworkInterface. While it's possible to listen or connect to different addresses at the same time, the NetworkDriverStore interface limits the options to the most common use cases that Netcode for Entities is designed for:

    • The server can listen from multiple NetworkDrivers, commonly listening to the same server port.
    • The client is primarily designed to use only a single NetworkDriver and connection.

    Default driver setup

    Netcode for Entities provides a default NetworkDriver setup, implemented by the IPCAndSocketDriverConstructor. The driver setup is different for each world type and depends on the PlayMode Tool settings.

    Default server configuration

    For the server world, the NetworkDriverStore contains multiple drivers to listen for incoming connections:

    Slot Interface Description
    Slot 1 IPCNetworkInterface Used to connect local client instances directly to the server for self-hosting.
    Slot 2 UDPNetworkInterface (standalone)
    WebsocketNetworkInterface (web)
    For accepting external connections.

    Default client configuration

    For the client world, the NetworkDriverStore always uses a single NetworkDriver, but the interface used depends on the PlayMode Tool settings.

    Mode Network Emulator
    Client On/Off UDPNetworkInterface (standalone)
    WebsocketNetworkInterface (web)
    Client/Server Off IPCNetworkInterface
    Client/Server On UDPNetworkInterface (standalone)
    WebsocketNetworkInterface (web)

    When a game runs in Client/Server mode, the client can connect to the local server in two different ways, depending on whether the Network Emulator is turned on or off.

    Self-hosting scenario

    When the Network Emulator is turned off, Netcode for Entities assumes a self-hosting scenario and the IPCNetworkInteface is used to connect to the server. When using this interface, the client optimizes its prediction loop to ensure that:

    • At most one prediction tick is done every frame.
    • Packet loss, jitter, and round trip time (RTT) are assumed to be 0 (for time synchronization purposes).

    Client connection emulation

    When the Network Emulator is turned on, Netcode for Entities sets up the client driver to use the WebsocketNetworkInterface, to simulate a client connecting to a remote server (even though the server is locally located on the same machine). This modality is used mostly for testing network conditions.

    Customize network driver creation

    You can customize how the NetworkDriverStore is set up at world creation by creating a class implementing the INetworkStreamDriverConstructor.

    The DefaultDriverBuilder class provides a set of utility methods that can be used to help create and initialize the drivers required by Netcode for Entities.

    
    public class MyCustomDriverConstructor : INetworkStreamDriverConstructor
    
        public void CreateClientDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug)
        {
            var settings = DefaultDriverBuilder.GetClientNetworkSettings();
            #if !UNITY_WEBGL
            DefaultDriverBuilder.RegisterClientUdpDriver(world, ref driverStore, netDebug, settings);
            #else
            DefaultDriverBuilder.RegisterClientWebSocketDriver(world, ref driverStore, netDebug, settings);
            #endif
        }
    
            public void CreateServerDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug)
            {
                var settings = DefaultDriverBuilder.GetNetworkServerSettings();
    #if !UNITY_WEBGL
                DefaultDriverBuilder.RegisterServerUdpDriver(world, ref driverStore, netDebug, relaySettings);
    #else
                DefaultDriverBuilder.RegisterServerWebSocketDriver(world, ref driverStore, netDebug, relaySettings);
    #endif
            }
        }
    }
    

    To use a custom strategy, you need to assign a new instance of your class to the NetworkStreamReceiveSystem.DriverConstructor static property before the worlds are created.

    var oldConstructor = NetworkStreamReceiveSystem.DriverConstructor;
    //The try/finally pattern can be used to avoid any exceptions resetting back to the old default.
    try
    {
        NetworkStreamReceiveSystem.DriverConstructor = new MyCustomDriverConstructor();
        var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
        var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
    }
    finally
    {
        NetworkStreamReceiveSystem.DriverConstructor = oldConstructor;
    }
    
    Note

    The DefaultDriverConstructor.RegisterServerDriver and DefaultDriverConstructor.RegisterClientDriver methods implement the default strategy for both server and client. For the latter in particular, the Network Emulator used has can connect via IPC or Socket. When creating a custom driver constructor, it's recommended to always use the interface-specific builder methods (i.e. RegisterServerUdpDriver) to control exactly the interfaces you want.

    Reset the NetworkDriverStore setup

    You can change the current NetworkDriverStore drivers setup after world creation using the NetworkStreamDriver.ResetDriverStore method.

    A new NetworkDriverStore instance must be created, manually configured, and passed as an argument to the reset method.

    Note

    Resetting can't be done if there are live connections. Drivers can be reset only when no NetworkStreamConnection exists in the world.

    Resetting the NetworkDriverStore instead of using a custom driver constructor can be useful or preferred in some cases. One of the most common use cases is when connecting or listening requires an asynchronous setup, such as when using relay.

    Another common scenario is when using thin clients, if asynchronous connection logic is required and thus not supported natively by the Play Mode Tool (because it requires a synchronous connection setup).

    Reset the driver store

    There are multiple ways to reset the driver store:

    • You can use an INetworkDriverConstructor instance to delegate the creation of the drivers.
    var driverStore = new NetworkDriverStore();
    var clientWorld = ClientServerBootstrap.ClientWorld;
    var netDebug = ClientServerBootstrap.ClientWorld.EntityManager.CreateEntityQuery(typeof(NetDebug)).GetSingleton<NetDebug>();
    // you can use any constructor to initialize the store
    NetworkStreamReceiveSystem.DriverConstructor.CreateClientDriver(m_ClientWorld, ref driverStore, netDebug);
    var networkStreamDriver = ClientServerBootstrap.ClientWorld.EntityManager.CreateEntityQuery(typeof(NetworkStreamDriver)).GetSingleton<NetworkStreamDriver>();
    networkStreamDriver.ResetDriverStore(ClientServerBootstrap.ServerWorld, ref driverStore);
    
    • You can manually populate them directly.
    var driverStore = new NetworkDriverStore();
    var netDebug = SystemAPI.Query<NetDebug>();
    var settings = DefaultDriverBuilder.GetServerNetworkSettings();
    var netDebug = ClientServerBootstrap.ServerWorld.EntityManager.CreateEntityQuery(typeof(NetDebug)).GetSingleton<NetDebug>();
    //register some drivers
    DefaultDriverBuilder.RegisterServerIpcDriver(ClientServerBootstrap.ServerWorld, ref driverStore, netDebug, settings);
    DefaultDriverBuilder.RegisterServerUpdDriver(ClientServerBootstrap.ServerWorld, ref driverStore, netDebug, settings);
    //reset
    var networkStreamDriver = ClientServerBootstrap.ServerWorld.EntityManager.CreateEntityQuery(typeof(NetworkStreamDriver)).GetSingleton<NetworkStreamDriver>();
    networkStreamDriver.ResetDriverStore(ClientServerBootstrap.ServerWorld, ref driverStore);
    

    Additional resources

    • Use Unity Relay with Netcode for Entities
    In This Article
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)