Skip to content

Not Exposed

TL;DR: If a .NET / Unity symbol does not have a binder link and is not stubbed by the WASI layer, calls fall through to BindingManager.FillNonLinkedWithEmptyStubs and silently no-op. This page enumerates the conspicuous absences and the CVR-approved replacements.

  • Allow-list by generation — only types that have a file in CVR-GameFiles/WasmBinder.Links.*/ or a manual binding in WasmBinder.LinksManual.UnityEngine/ or a hand-written binding in WasmScripting/*Bindings.cs are reachable.
  • Anything else is either (a) filled with an empty stub at instantiation time or (b) filtered out by the CCKWasmModule shim at compile time.

Not supported. A [SerializeField] public MyScriptableObject data; field on a WasmBehaviour is skipped by the serializer — it doesn’t cross the build boundary and is null at runtime.

Substitutions:

  • Replace shared data with a [WasmSerialized] custom class on a WasmBehaviour component, or plain fields on a “config” WasmBehaviour that lives on a well-known GameObject in your content.
  • For inspector-editable asset-style data, pack it into arrays of serializable fields on the behaviour.

Not bound. Common substitutions:

  • Application.platform, .version, .productName — not available. If you need to branch, use the CCK CVR_SCRIPTING_CONTEXT_* preprocessor defines at compile time.
  • Application.Quit() — not available. CVR controls the process lifetime.
  • Application.isPlaying — not available. You are always running; there is no editor play mode from the guest’s perspective.

Not bound. CVR is VR-first, so hooking into keyboard/mouse at this level would be misleading anyway. Substitutions:

  • Interactions — use CVR’s CVRPointer, CVRInteractable, or bindable CCK components with persistent UnityEvents. See Unity Events Rewiring.
  • VR controller buttons — surfaced via CCK input components (e.g. CVRInputManager / CCK AvatarInput) and the OnInputReady game event, not via UnityEngine.Input.

Not bound. Screen size / orientation / resolution are not meaningful for a script that doesn’t own the window — they belong to CVR.

Not bound. Substitution:

  • World-scoped persistence — File Storage (requires world permission).
  • Per-avatar or per-prop persistence — not directly supported. Use network messages to sync transient state across clients and rely on the host for instance lifetime.

Not bound. Loading new assets at runtime from outside the original CCK upload is forbidden — otherwise the content-integrity model (signed uploads, per-content permissions) breaks.

  • You can still reference any asset that shipped with your avatar/world/prop via regular field references (serialized UnityEngine.Object fields).

UnityEngine.Application / OnApplicationX events

Section titled “UnityEngine.Application / OnApplicationX events”

Already covered in Events. Disallowed:

  • OnServerInitialized, OnConnectedToServer
  • OnGUI
  • OnApplicationQuit, OnApplicationFocus, OnApplicationPause

Define them — they will be detected and ignored.

Only the Scene struct is bound. Not bound:

  • SceneManager.LoadScene*
  • SceneManager.UnloadScene*
  • Scene instantiation APIs

CVR manages world scene loading itself (portals, instance joins). Scripts observe scene state — they do not drive it.

Not bound. The WASI filesystem imports (fd_close, fd_read, fd_write, fd_seek, fd_filestat_get, fd_fdstat_get, fd_prestat_get, …) are stubbed to return 8 (WASI EBADF). path_open / path_filestat_get / path_readlink / path_unlink_file return 0 but never produce data. environ_get / environ_sizes_get return 0 with empty output. clock_time_get is implemented (real-time and monotonic clocks), random_get + mono_wasm_browser_entropy fill the buffer with Random.NextBytes. See CVR-GameFiles/WasmScripting/WasmStubs.cs.

  • Persistent state — File Storage.
  • In-module resources — pack them into the .wasm via dotnet publish embedded resources and read via System.Reflection.Assembly.GetManifestResourceStream. (Requires enableReflection on the descriptor.)

Not bound. No raw TCP / UDP.

  • Player-to-player messaging — Networking.
  • External HTTP — gated by the HttpApiAllowed + HttpAllowedDomains world permissions. See World Permissions.

Not bound. No subprocess spawning. Wasmtime would refuse anyway — WASI’s process APIs are only stubs.

Effectively disabled. The default csproj sets <IlcDisableReflection>true</IlcDisableReflection>, which strips reflection metadata during NativeAOT compilation. Emit-style dynamic codegen is fundamentally incompatible with the AOT toolchain.

  • If you need limited reflection, set CCKWasmProjectDescriptor.enableReflection = true. The module size increases significantly.

UnityEngine.GameObject.Find / FindObjectOfType

Section titled “UnityEngine.GameObject.Find / FindObjectOfType”

Not generally bound (check GameObjectLinksManual.cs for the subset that is). Even if available they would be forbidden by the scope check: results outside your content root are ScopeContext.ExternalContent and most write operations demand Self.

  • Wire references at design time via serialized public fields.
  • Use hierarchy traversal from this.transform (Transform is bound) to find children.

UnityEngine.Instantiate (prefab instantiation)

Section titled “UnityEngine.Instantiate (prefab instantiation)”

Restricted. Manual binding in ObjectLinksManual.cs gates instantiation behind scope + permissions. In practice:

  • Instantiating a prefab inside your own content root is fine.
  • Instantiating into external content (another player’s avatar, the world if you’re an avatar/prop) is rejected.

Partially supported: Coroutine is a type that can be held, but StartCoroutine exposure depends on the GameObjectLinksManual.cs surface. Prefer:

  • Update / FixedUpdate for periodic work.
  • A lightweight state machine you tick yourself rather than multiple coroutines.

Read is fine (Time is bound). Writes are not accepted — Time.timeScale and similar mutators are either not bound or gated away.

UnityEngine.Application.persistentDataPath / streamingAssetsPath

Section titled “UnityEngine.Application.persistentDataPath / streamingAssetsPath”

Not bound. There is no notion of a per-session working directory in the sandbox. Use File Storage.

Not usable. The generated .wasm has no loadable native libraries — only the WASM imports CVR defines in its linker. P/Invoke declarations compile but fail to link.

  • WASM threads — disabled (WasmManager.Config does not set WithWasmThreads).
  • Task / async — you can use Task and async/await at the C# level (the NativeAOT runtime supports it), but all work runs on the WASM single thread. Awaits serialize into continuations on the same call; they do not actually yield to other Unity work.
  • Thread.Sleep — not bound (there’s nothing to sleep to — you’d block the single thread).

Reflection-dependent culture / formatting APIs may throw or behave unexpectedly under IlcDisableReflection. Stick to invariant-culture formatting and explicit number/date parsers.

WASI environ_get / environ_sizes_get return empty. There is no command line for a WASM module inside CVR.

You want to …Use
Read / write a fileFile Storage (world, permissioned)
Call an HTTP APICCK WasmModule HTTP helpers, gated by world permissions
Move the local playerCVR_LocalPlayer_* (world only)
Send data to other clientsNetworking
Persist state across sessionsFile Storage (world) or network-sync with instance owner
Read the user’s identityCVR_Player_GetUserId + AccessUserIdentity permission; CVR_Player_GetUsername no longer needs a permission
Load an asset at runtimeReference it at design time; runtime dynamic loading is forbidden
Schedule work on another threadNot possible — WASM threads disabled