Update on our progress with Unity WebGL builds from Linux CI
We’ve made progress on getting Cesium for Unity working in WebGL builds cross-compiled from Linux. Here’s a summary of what we found and our workarounds.
1. “Missing script” issue on Linux CI builds
PR #634 (adding !UNITY_EDITOR_LINUX defineConstraint to the asmdef) was sufficient to fix cross-compilation from Linux to macOS, but it does not fix Linux-to-WebGL cross-compilation. It makes the build process succeed for both platforms, but the resulting WebGL build throws exceptions at runtime and doesn’t show any Cesium.
It is unclear to us why the same mechanism works for macOS but not WebGL, as the asset serialization process should be the same for both targets.
The root cause: the Cesium package includes resource assets (CesiumCreditSystem.prefab, CesiumRuntimeSettings.asset, ion.cesium.com.asset) that reference CesiumForUnity MonoBehaviours. When the assembly is excluded on the Linux editor, these assets are loaded into memory with broken script references. Unity then uses these broken in-memory representations when building for WebGL, baking the broken references into the output. The on-disk prefab files remain unchanged (Unity does not re-serialize them), but the build uses the in-memory state.
At runtime in the browser, this results in:
The referenced script (Unknown) on this Behaviour is missing!
The referenced script on this Behaviour (Game Object 'CesiumCreditSystem') is missing!
Notably, Resources.Load<GameObject>("CesiumCreditSystem") returns a non-null GameObject, but with null MonoBehaviour components. The prefab is there, but the scripts are gone.
Our workaround: We override ResourcesAPI.Load to intercept Cesium resource requests and create the objects from code at runtime (CesiumCreditSystem with CesiumCreditSystemUI + UIDocument components, CesiumIonServer, CesiumRuntimeSettings). At runtime in the WebGL player, the CesiumForUnity assembly is compiled and available, so this works. The pure Unity assets referenced by the UIDocument (PanelSettings, VisualTreeAsset) survive the Linux build without issues since they have no script references.
2. Physics.BakeMesh crash in WebGL
After fixing the missing scripts, Cesium loads and starts rendering in WebGL. However, the app crashes after some time with:
RuntimeError: memory access out of bounds
at il2cpp::icalls::mscorlib::System::Diagnostics::StackFrame::get_frame_info(...)
...
at Physics::CollisionMeshCooking::CookMeshFromUnityMesh(...)
at PhysicsManager::BakeMesh(...)
at CesiumForUnityNative::UnityPrepareRendererResources::prepareInLoadThread(...)
The crash chain: Cesium calls Physics.BakeMesh during tile preparation. PhysX mesh cooking fails on large terrain triangles (>500 units). Unity tries to log the error. The stack trace extraction itself crashes with an out-of-bounds memory access in WASM. The original PhysX error might have been recoverable, but the crash in the error-reporting path kills the app.
Our workaround: Setting createPhysicsMeshes = false on the tileset for WebGL builds. This means no physics raycasting against Cesium terrain on WebGL, but it prevents the crash.
Note on desktop: The same BakeMesh path produces ~27,000 warning lines in the log within seconds of navigating (“Detected one or more triangles where the distance between any 2 vertices is greater than 500 units”). This doesn’t crash on desktop but has significant performance and disk usage implications.
Related: Errors in Playmode after Updateing to Unity 6