Yes, there are different bootstrapping scripts but with the same implementation, because I’m separating Client, Server and Editor using assemblies, maybe am I setting up them wrong from beginning? But other systems that use RPCs work well on both editor client and prebuild client (requesting the server to send to the client itself back RPC i.e. pick an item).
I checked the player.log and I found the clients get continuous large server tick exceptions (Large serverTick prediction error. Server tick rollback to Unity.NetCode.NetworkTick delta).
Editor Bootstrap
[UnityEngine.Scripting.Preserve]
public class BootstrapEditor : ClientServerBootstrap
{
public override bool Initialize(string defaultWorldName)
{
#if UNITY_EDITOR
AutoConnectPort = 0;
NetworkStreamReceiveSystem.DriverConstructor = new SecureDriverConstructorEditor();
CreateLocalWorld(defaultWorldName);
#endif
return true;
}
}
Client Bootstrap
Manual connect using UI.
#if CLIENT_BUILD
[UnityEngine.Scripting.Preserve]
public class BootstrapClient : ClientServerBootstrap
{
public override bool Initialize(string defaultWorldName)
{
NetworkStreamReceiveSystem.DriverConstructor = new SecureDriverConstructorClientSide();
CreateLocalWorld(defaultWorldName);
return true;
}
}
#endif
Server Bootstrap
#if UNITY_SERVER
[UnityEngine.Scripting.Preserve]
public class BootstrapServer : ClientServerBootstrap
{
const ushort NetworkPort = 7979;
internal static string OldFrontendWorldName = string.Empty;
public override bool Initialize(string defaultWorldName)
{
StartServer();
return true;
}
private void StartServer()
{
if (RequestedPlayType != PlayType.Server)
{
Debug.LogError($"Creating server worlds is not allowed if playmode is set to {RequestedPlayType}");
return;
}
NetworkStreamReceiveSystem.DriverConstructor = new SecureDriverConstructorServerSide();
var server = CreateServerWorld("ServerWorld");
SceneManager.LoadScene("World");
//Destroy the local simulation world to avoid the game scene to be loaded into it
//This prevent rendering (rendering from multiple world with presentation is not greatly supported)
//and other issues.
DestroyLocalSimulationWorld();
if (World.DefaultGameObjectInjectionWorld == null)
World.DefaultGameObjectInjectionWorld = server;
var port = ParsePortOrDefault(NetworkPort.ToString());
NetworkEndpoint Ep = NetworkEndpoint.AnyIpv4.WithPort(port);
{
using var drvQuery = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
drvQuery.GetSingletonRW<NetworkStreamDriver>().ValueRW.Listen(Ep);
}
}
private void DestroyLocalSimulationWorld()
{
foreach (var world in World.All)
{
if (world.Flags == WorldFlags.Game)
{
OldFrontendWorldName = world.Name;
world.Dispose();
break;
}
}
}
private UInt16 ParsePortOrDefault(string s)
{
if (!UInt16.TryParse(s, out var port))
{
Debug.LogWarning($"Unable to parse port, using default port {NetworkPort}");
return NetworkPort;
}
return port;
}
}
#endif
ForntEnd UI Bootstrap
public class BootstrapFrontend : MonoBehaviour
{
const ushort NetworkPort = 7979;
const string NetworkIPAddress = "127.0.0.1";
/// <summary>
/// Stores the old name of the local world (create by initial bootstrap).
/// It is reused later when the local world is created when coming back from game to the menu.
/// </summary>
internal static string OldFrontendWorldName = string.Empty;
#if UNITY_EDITOR || CLIENT_BUILD
public void ConnectToServer()
{
if (SceneManager.GetActiveScene().name == "Login")
{
InstantiateClientWorld();
}
}
#endif
#if UNITY_EDITOR
public void StartClientAndServer()
{
if (ClientServerBootstrap.RequestedPlayType != ClientServerBootstrap.PlayType.ClientAndServer)
{
Debug.LogError($"Creating client/server worlds is not allowed if playmode is set to {ClientServerBootstrap.RequestedPlayType}");
return;
}
var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
SceneManager.LoadScene("World");
//Destroy the local simulation world to avoid the game scene to be loaded into it
//This prevent rendering (rendering from multiple world with presentation is not greatly supported)
//and other issues.
DestroyLocalSimulationWorld();
if (World.DefaultGameObjectInjectionWorld == null)
World.DefaultGameObjectInjectionWorld = server;
var port = ParsePortOrDefault(NetworkPort.ToString());
NetworkEndpoint Ep = NetworkEndpoint.AnyIpv4.WithPort(port);
{
using var drvQuery = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
drvQuery.GetSingletonRW<NetworkStreamDriver>().ValueRW.Listen(Ep);
}
Ep = NetworkEndpoint.LoopbackIpv4.WithPort(port);
{
using var drvQuery = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
drvQuery.GetSingletonRW<NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, Ep);
}
}
#endif
#if UNITY_EDITOR
public void StartServer()
{
if (ClientServerBootstrap.RequestedPlayType != ClientServerBootstrap.PlayType.Server)
{
Debug.LogError($"Creating server worlds is not allowed if playmode is set to {ClientServerBootstrap.RequestedPlayType}");
return;
}
var server = ClientServerBootstrap.CreateServerWorld("ServerWorld");
SceneManager.LoadScene("World");
//Destroy the local simulation world to avoid the game scene to be loaded into it
//This prevent rendering (rendering from multiple world with presentation is not greatly supported)
//and other issues.
DestroyLocalSimulationWorld();
if (World.DefaultGameObjectInjectionWorld == null)
World.DefaultGameObjectInjectionWorld = server;
var port = ParsePortOrDefault(NetworkPort.ToString());
NetworkEndpoint Ep = NetworkEndpoint.AnyIpv4.WithPort(port);
{
using var drvQuery = server.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
drvQuery.GetSingletonRW<NetworkStreamDriver>().ValueRW.Listen(Ep);
}
}
#endif
private void InstantiateClientWorld()
{
if (ClientServerBootstrap.RequestedPlayType != ClientServerBootstrap.PlayType.Client)
{
Debug.LogError($"Creating client worlds is not allowed if playmode is set to {ClientServerBootstrap.RequestedPlayType}");
return;
}
var client = ClientServerBootstrap.CreateClientWorld("ClientWorld");
//Destroy the local simulation world to avoid the game scene to be loaded into it
//This prevent rendering (rendering from multiple world with presentation is not greatly supported)
//and other issues.
DestroyLocalSimulationWorld();
if (World.DefaultGameObjectInjectionWorld == null)
World.DefaultGameObjectInjectionWorld = client;
var Ep = NetworkEndpoint.Parse(NetworkIPAddress, ParsePortOrDefault(NetworkPort.ToString()));
{
using var drvQuery = client.EntityManager.CreateEntityQuery(ComponentType.ReadWrite<NetworkStreamDriver>());
drvQuery.GetSingletonRW<NetworkStreamDriver>().ValueRW.Connect(client.EntityManager, Ep);
}
SceneManager.LoadScene("World");
}
private void DestroyLocalSimulationWorld()
{
foreach (var world in World.All)
{
if (world.Flags == WorldFlags.Game)
{
OldFrontendWorldName = world.Name;
world.Dispose();
break;
}
}
}
private UInt16 ParsePortOrDefault(string s)
{
if (!UInt16.TryParse(s, out var port))
{
Debug.LogWarning($"Unable to parse port, using default port {NetworkPort}");
return NetworkPort;
}
return port;
}
}
The following images will illustrate the connection Id on both client and server:
Clients Ids on server side
Clients Ids on client side 'Player Log'

The Player.log below indicates that the RPC message is received, but it doesn’t invoke the UI window:
When Sending RPC request
I changed the server code to be able to send team request to myself and surprisingly the Team Invitation UI window generated correctly, why only generated on same client and not others and both messages come from same server?
Thanks in advance.