WebGL Build bootstraps Server Systems?

Just starting to experiment with NetCode for ECS, which means I have an almost empty project, and just wanted to create a WebGL build and a Dedicated Linux Server build and see if I can get the two connecting.

But when I open up the WebGL build in a browser, it fails to load and I get this error in the console:

NotSupportedException: Creating a server driver for a WebGL build is not supported. You can’t listen on a WebSocket in the browser. WebGL builds should be ideally client-only (has UNITY_CLIENT define) and in case a Client/Server build is made, only client worlds should be created.
at Unity.NetCode.IPCAndSocketDriverConstructor.CreateServerDriver (Unity.Entities.World world, Unity.NetCode.NetworkDriverStore& driverStore, Unity.NetCode.NetDebug netDebug) [0x00000] in <00000000000000000000000000000000>:0

And a print screen of the browser console that shows my custom server bootstrap is getting initialised:

Of course, a WebGL build should only have client systems running, and no attempts to listen should be made, but how do I ensure that?

As per the error message, I’ve added UNITY_CLIENT to the scripting defines for the WebGL build, just in case Unity doesn’t do that for me:
9881568--1425549--upload_2024-6-9_20-47-3.png

I’ve also got the NetCode Client Target set to ‘Client’, not ‘ClientAndServer’:
9881568--1425552--upload_2024-6-9_20-48-26.png

Getting a bit desperate I went and wrapped my custom bootstrap and WorldSystemFilterFlags.ServerSimulation system in #if !UNITY_WEBGL:

#if !UNITY_WEBGL
class MyCustomClientServerBootstrap : ClientServerBootstrap {
    public override bool Initialize(string defaultWorld) {
        bool result = base.Initialize(defaultWorld);
        var customTickRate = new ClientServerTickRate(); //run at 30hz
        customTickRate.SimulationTickRate = 15;
        customTickRate.ResolveDefaults();
        foreach (var world in World.All) {
            if (world.IsServer()) {
                //In this case we only create on the server, but we can do the same also for the client world
                var tickRateEntity = world.EntityManager.CreateSingleton(new ClientServerTickRate { SimulationTickRate = 30 });
            }
        }
        return result;
    }
}


[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
public partial class TheServerUniverse : SystemBase {
}
#endif

But still no luck. My Unity WebGL build still loves to try and bootstrap a ClientServerBootstrap object.

(If I run the client-only in the Editor I can connect to my Linux dedicated server just fine.)

What am I doing wrong? What am I missing? As you can see, there’s not a lot of C# here, is there another build or player setting I’ve overlooked?

Your custom bootstrapper shouldn’t exist anymore, but the default ClientServerBootstrap still will. In its Initialize, it’ll still have bootstrapping logic to create client and/or server worlds. Can you log the value of ClientServerBootstrap.RequestedPlayType for me please? In theory it should be defined by #if

That ClientServerBootstrap is there for convenience, to get you started. But in most cases you’ll want to override it completely and have your own world creation logic (with no need to call base.Initialize()).

Thanks @SamuelBellomoUnity , I think my problem was that despite my screenshot in my initial post, the “Netcode Client Target” set to ‘Client’ didn’t seem to stick/save, and setting it again + building leads to the expected RequestedPlayType of Client.

The error I first described is thankfully gone…

… but now I receive another exception a ‘RuntimeError: index out of bounds’ error that, again, emerges from the system bootstrapping initialisation process, and specifically ClientNetworkConnectionSystem_OnCreate

Here’s the full stacktrace:

11:52:12.445 Uncaught RuntimeError: index out of bounds
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viiii http://localhost/Build/WebGL.framework.js:15879
WebGL.wasm:43670820:1
LogData_ToString_mB60780615C703016FB177C66F844BF93CC2C5F4E http://localhost/Build/WebGL.wasm:43670820
Logger_defaultOutput_mC2F06A5F1B0DF2F64032920F0E15859071CBF208 http://localhost/Build/WebGL.wasm:43672046
Action_2_Invoke_m7BFCE0BBCF67689D263059B56A8D79161B698587_OpenStatic(Action_2_t156C43F079E7E68155FCDCD12DC77DD11AEF7E3C*, Il2CppObject*, Il2CppObject*, MethodInfo const*) http://localhost/Build/WebGL.wasm:37876490
dynCall_viiii http://localhost/Build/WebGL.wasm:74891586
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viiii http://localhost/Build/WebGL.framework.js:15879
Logger_output_m476E9BB7F166442C18391BD91CE00DBB70F224C0 http://localhost/Build/WebGL.wasm:43614237
dynCall_viiii http://localhost/Build/WebGL.wasm:74891586
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viiii http://localhost/Build/WebGL.framework.js:15879
Logger_set_Level_m7F2B6EA2E57B7E1EB70E23FA6F0E111C803E204E http://localhost/Build/WebGL.wasm:43671679
ClientNetworkConnectionSystem_OnCreate_m7202C3AC618AD394861BEBABCF60DBCBACA1D06E http://localhost/Build/WebGL.wasm:53994728
dynCall_vii http://localhost/Build/WebGL.wasm:74891472
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_vii http://localhost/Build/WebGL.framework.js:15780
ComponentSystemBase_CreateInstance_m79F65A71BD533BB69AEA70980E414A9B49947B55 http://localhost/Build/WebGL.wasm:32777655
dynCall_viii http://localhost/Build/WebGL.wasm:74891518
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viii http://localhost/Build/WebGL.framework.js:15857
World_AddSystem_OnCreate_Internal_m52298962331E2236D3FC629EAB64974BB2CE14C4 http://localhost/Build/WebGL.wasm:45373626
dynCall_viii http://localhost/Build/WebGL.wasm:74891518
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viii http://localhost/Build/WebGL.framework.js:15857
World_GetOrCreateSystemsAndLogException_mAC5B30305ADE7068D0F4DA41FE93C3F944887399 http://localhost/Build/WebGL.wasm:45380616
World_GetOrCreateSystemsAndLogException_m65330BDD5D6A373B21E2B969BF898BDF4B9848D0 http://localhost/Build/WebGL.wasm:45382551
DefaultWorldInitialization_AddSystemToRootLevelSystemGroupsInternal_TisDefaultRootGroups_t7281EBC4DB68ACD923E7D99CD1882B8F517F0352_mA6CD87DE5B84E8808781EB42C46F3C5074F2F676_gshared http://localhost/Build/WebGL.wasm:30883632
dynCall_viiiii http://localhost/Build/WebGL.wasm:74891624
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_viiiii http://localhost/Build/WebGL.framework.js:15989
DefaultWorldInitialization_AddSystemToRootLevelSystemGroupsInternal_mDC54C031C8C17E90406CD8D368F448A378F4A2F3 http://localhost/Build/WebGL.wasm:11950477
DefaultWorldInitialization_AddSystemsToRootLevelSystemGroups_m488D92E2FC00EB0937F61703F0D80AFB95B3A9FD http://localhost/Build/WebGL.wasm:11952442
ClientServerBootstrap_CreateClientWorld_m2A138F5C27D90F4E67FAF387D5A15CC06465AC9E http://localhost/Build/WebGL.wasm:27278630
ClientServerBootstrap_CreateDefaultClientServerWorlds_mDC10D4BA1DE13F94A96F70A67E409CB56229BFC3 http://localhost/Build/WebGL.wasm:27278533
ClientServerBootstrap_Initialize_mBDE9E7A7C6113B3A75FF3FEDAEDC4F1628D52D37 http://localhost/Build/WebGL.wasm:27276704
MyCustomClientServerBootstrap_Initialize_mDEB2E8BA32D648F428D19F8F0A6D40920B19C761 http://localhost/Build/WebGL.wasm:54017664
dynCall_iiii http://localhost/Build/WebGL.wasm:74891486
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_iiii http://localhost/Build/WebGL.framework.js:15813
DefaultWorldInitialization_Initialize_m727EDEE4EEE3C6DA457EA83661F0716ED666186E http://localhost/Build/WebGL.wasm:11946772
AutomaticWorldBootstrap_Initialize_m5BEA540B46502396A82B923D1D62C0D693EAC1C1 http://localhost/Build/WebGL.wasm:40302466
RuntimeInvoker_FalseVoid_t4861ACF8F4594C3437BB48B6E56783494B843915(void ()(), MethodInfo const, void*, void**, void*) http://localhost/Build/WebGL.wasm:60270878
il2cpp::vm::Runtime::InvokeWithThrow(MethodInfo const*, void*, void**) http://localhost/Build/WebGL.wasm:60610500
dynCall_iiii http://localhost/Build/WebGL.wasm:74891486
unityFramework http://localhost/Build/WebGL.framework.js:1468
invoke_iiii http://localhost/Build/WebGL.framework.js:15813
il2cpp::vm::Runtime::Invoke(MethodInfo const*, void*, void**, Il2CppException**) http://localhost/Build/WebGL.wasm:60594578
il2cpp_runtime_invoke http://localhost/Build/WebGL.wasm:1761715
scripting_method_invoke(ScriptingMethodPtr, ScriptingObjectPtr, ScriptingArguments&, ScriptingExceptionPtr*, bool) http://localhost/Build/WebGL.wasm:74531012
ScriptingInvocation::Invoke(ScriptingExceptionPtr*, bool) http://localhost/Build/WebGL.wasm:74090529
RuntimeInitializeOnLoadManager::Execute(RuntimeInitializeOnLoadCall const&) http://localhost/Build/WebGL.wasm:74713806
RuntimeInitializeOnLoadManager::ExecuteInitializeOnLoad(RuntimeInitializeLoadType) http://localhost/Build/WebGL.wasm:74709324
RuntimeInitializeOnSceneLoadedBeforeAwake(int, AwakeFromLoadQueue&, SceneLoadingMode, bool) http://localhost/Build/WebGL.wasm:74707772
CallbackArray4<int const, AwakeFromLoadQueue&, SceneLoadingMode, bool>::Invoke(int, AwakeFromLoadQueue&, SceneLoadingMode, bool) http://localhost/Build/WebGL.wasm:63450966
LoadSceneOperation::CompleteAwakeSequence() http://localhost/Build/WebGL.wasm:63449497
LoadSceneOperation::CompleteLoadFirstScene() http://localhost/Build/WebGL.wasm:63449800
LoadSceneOperation::IntegrateMainThread() http://localhost/Build/WebGL.wasm:63449002
PreloadManager::UpdatePreloadingSingleStep(PreloadManager::UpdatePreloadingFlags, int) http://localhost/Build/WebGL.wasm:63455046
PreloadManager::WaitForAllAsyncOperationsToComplete() http://localhost/Build/WebGL.wasm:63455403
RuntimeSceneManager::LoadScene(core::basic_string<char, core::StringStorageDefault > const&, core::basic_string<char, core::StringStorageDefault > const&, core::basic_string<char, core::StringStorageDefault > const&, UnityGUID const&, int, InternalLoadSceneParameters const&) http://localhost/Build/WebGL.wasm:63423789
PlayerStartFirstScene(bool) http://localhost/Build/WebGL.wasm:73707090
PlayerLoadFirstScene(bool) http://localhost/Build/WebGL.wasm:73707368
InitWebGLPlayer(int, char**) http://localhost/Build/WebGL.wasm:73984128
main http://localhost/Build/WebGL.wasm:73984856
unityFramework http://localhost/Build/WebGL.framework.js:1468
callMain http://localhost/Build/WebGL.framework.js:17935
doRun http://localhost/Build/WebGL.framework.js:17969
run http://localhost/Build/WebGL.framework.js:17981
runCaller http://localhost/Build/WebGL.framework.js:17918
removeRunDependency http://localhost/Build/WebGL.framework.js:1423
unityFileSystemInit http://localhost/Build/WebGL.framework.js:223
doCallback http://localhost/Build/WebGL.framework.js:5300
done http://localhost/Build/WebGL.framework.js:5311
oncomplete http://localhost/Build/WebGL.framework.js:4819
(Async: EventHandlerNonNull)
reconcile http://localhost/Build/WebGL.framework.js:4817
syncfs http://localhost/Build/WebGL.framework.js:4585
http://localhost/Build/WebGL.framework.js:4674
(Async: EventHandlerNonNull)
getRemoteSet http://localhost/Build/WebGL.framework.js:4671
onsuccess http://localhost/Build/WebGL.framework.js:4621
(Async: EventHandlerNonNull)
getDB http://localhost/Build/WebGL.framework.js:4618
getRemoteSet http://localhost/Build/WebGL.framework.js:4661
syncfs http://localhost/Build/WebGL.framework.js:4581
getLocalSet http://localhost/Build/WebGL.framework.js:4654
syncfs http://localhost/Build/WebGL.framework.js:4579
syncfs http://localhost/Build/WebGL.framework.js:5318
forEach self-hosted:157
syncfs http://localhost/Build/WebGL.framework.js:5314
unityFileSystemInit http://localhost/Build/WebGL.framework.js:221
unityFramework http://localhost/Build/WebGL.framework.js:226
callRuntimeCallbacks http://localhost/Build/WebGL.framework.js:1624
preRun http://localhost/Build/WebGL.framework.js:1298
run http://localhost/Build/WebGL.framework.js:17956
runCaller http://localhost/Build/WebGL.framework.js:17918
removeRunDependency http://localhost/Build/WebGL.framework.js:1423
receiveInstance http://localhost/Build/WebGL.framework.js:1537
receiveInstantiationResult http://localhost/Build/WebGL.framework.js:1544
(Async: promise callback)
unityFramework http://localhost/Build/WebGL.framework.js:1565
(Async: promise callback)
instantiateAsync http://localhost/Build/WebGL.framework.js:1563
createWasm http://localhost/Build/WebGL.framework.js:1584
unityFramework http://localhost/Build/WebGL.framework.js:14744
loadBuild http://localhost/Build/WebGL.loader.js:1218
(Async: promise callback)
loadBuild http://localhost/Build/WebGL.loader.js:1217
createUnityInstance http://localhost/Build/WebGL.loader.js:1268
createUnityInstance http://localhost/Build/WebGL.loader.js:1246
onload http://localhost/:92
(Async: EventHandlerNonNull)
http://localhost/:91

We fixed the bootstrapping for WebGL in 1.2.1. In order to start a server using WebGL you should use relay, otherwise it is not supported to create your own listening web socket.
If you are building a client server build, the default world creation flow will start a client and server world. As such, the server is complaining that it can’t create a listening socket.

For the exception instead, is the ClientNetworkConnectionSystem a system of yours? we don’t have any system named like that (IIRC). I also found another couple of annoying crashes using WebGL recently