Events
TL;DR: A WasmBehaviour receives events by defining instance methods whose names match values in the UnityEvents or GameEvents enums. Presence is detected at build time via reflection; any you don’t define are never dispatched. Six Unity events are explicitly stubbed and will not fire. Post-phase events (PostUpdate, PostLateUpdate, PostFixedUpdate) run after all Unity and CVR scripts have finished the corresponding phase.
How detection works
Section titled “How detection works”At CCK build, WasmBuildProcessor.ScanForUnityEvents and ScanForGameEvents iterate the UnityEvents / GameEvents enums and match by method name:
foreach (UnityEvents flag in Enum.GetValues(typeof(UnityEvents))) { MethodInfo method = scriptType.GetMethod(flag.ToString(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); unityEvents = WasmEventUtils.SetEvent(unityEvents, flag, method != null);}Source: CVR.CCK.Wasm/CCK/Editor/WasmBuildProcessor.cs (ScanForUnityEvents, ScanForGameEvents).
Matching is by name only (known TODO in source). A public or private method with the matching name is detected. Parameter types are not checked by the scanner — if you give a wrong-shape signature, the runtime dispatcher may pass mismatched args. Stick to the exact canonical signatures listed below.
The detected-events bitmask is stored on each WasmBehaviourInfo.definedEvents, and the union of definedGameEvents across every behaviour on the content root goes on the WasmVMAnchor.definedGameEvents. At VM setup, WasmVM.InitializeEvents only subscribes to the WasmGameEvents delegates that appear in the union, and WasmRuntimeBehaviour only attaches BaseEventForwarder components (OnAnimatorIKForwarder, OnRenderImageForwarder, …) for the Unity events the behaviour actually implements. Unused events cost nothing at runtime.
Unity lifecycle events
Section titled “Unity lifecycle events”| Event | Signature | Notes |
|---|---|---|
Awake | void Awake() | Before Start. |
Start | void Start() | After serialized state is restored. |
Update | void Update() | Every frame. |
LateUpdate | void LateUpdate() | After animations. |
FixedUpdate | void FixedUpdate() | Physics step. In CVR, Time.fixedDeltaTime scales with the display refresh rate (30–144 Hz) — rate varies, timestep is consistent. |
OnEnable | void OnEnable() | Behaviour enabled. |
OnDisable | void OnDisable() | Behaviour disabled. |
OnDestroy | void OnDestroy() | Before teardown. |
OnBeforeSerialize | void OnBeforeSerialize() | Before state is snapshotted. |
OnAfterDeserialize | void OnAfterDeserialize() | After state is restored. |
Post-phase events
Section titled “Post-phase events”| Event | Signature | Description |
|---|---|---|
PostUpdate | void PostUpdate() | Runs after all Unity + scene Update calls have finished. |
PostLateUpdate | void PostLateUpdate() | Runs after all LateUpdate calls, including local Avatar IK and Network IK. Best place to sample a player’s final pose. |
PostFixedUpdate | void PostFixedUpdate() | Runs after all FixedUpdate calls. |
These events are a CVR-specific mechanism that lets a WASM script act after everyone else in a given phase. See Execution order for the scene-scoping gotcha.
Physics events
Section titled “Physics events”| Event | Signature | Notes |
|---|---|---|
OnTriggerEnter | void OnTriggerEnter(Collider other) | 3D trigger. other is the entering collider. |
OnTriggerStay | void OnTriggerStay(Collider other) | Every frame while inside. |
OnTriggerExit | void OnTriggerExit(Collider other) | |
OnTriggerEnter2D | void OnTriggerEnter2D(Collider2D other) | 2D variant. |
OnTriggerStay2D | void OnTriggerStay2D(Collider2D other) | |
OnTriggerExit2D | void OnTriggerExit2D(Collider2D other) | |
OnCollisionEnter | void OnCollisionEnter(Collision c) | 3D solid contact. |
OnCollisionStay | void OnCollisionStay(Collision c) | |
OnCollisionExit | void OnCollisionExit(Collision c) | |
OnCollisionEnter2D | void OnCollisionEnter2D(Collision2D c) | 2D variant. |
OnCollisionStay2D | void OnCollisionStay2D(Collision2D c) | |
OnCollisionExit2D | void OnCollisionExit2D(Collision2D c) | |
OnParticleTrigger | void OnParticleTrigger() | |
OnParticleCollision | void OnParticleCollision(GameObject other) | |
OnControllerColliderHit | void OnControllerColliderHit(ControllerColliderHit hit) | Character controller. |
OnJointBreak | void OnJointBreak(float breakForce) | |
OnJointBreak2D | void OnJointBreak2D(Joint2D brokenJoint) |
Rendering events
Section titled “Rendering events”| Event | Signature |
|---|---|
OnBecameVisible | void OnBecameVisible() |
OnBecameInvisible | void OnBecameInvisible() |
OnPreCull | void OnPreCull() |
OnPreRender | void OnPreRender() |
OnPostRender | void OnPostRender() |
OnRenderObject | void OnRenderObject() |
OnWillRenderObject | void OnWillRenderObject() |
OnRenderImage | void OnRenderImage(RenderTexture src, RenderTexture dst) |
Mouse events
Section titled “Mouse events”| Event | Signature |
|---|---|
OnMouseEnter | void OnMouseEnter() |
OnMouseOver | void OnMouseOver() |
OnMouseExit | void OnMouseExit() |
OnMouseDown | void OnMouseDown() |
OnMouseUp | void OnMouseUp() |
OnMouseUpAsButton | void OnMouseUpAsButton() |
OnMouseDrag | void OnMouseDrag() |
CVR is VR-first; mouse events only fire in desktop mode. For in-world interaction in both modes, use CVR Pointer / Interactable components or bound events.
Animation / audio / transform
Section titled “Animation / audio / transform”| Event | Signature |
|---|---|
OnAnimatorMove | void OnAnimatorMove() |
OnAnimatorIK | void OnAnimatorIK(int layerIndex) |
OnAudioFilterRead | void OnAudioFilterRead(float[] data, int channels) |
OnTransformChildrenChanged | void OnTransformChildrenChanged() |
OnTransformParentChanged | void OnTransformParentChanged() |
Player events (game events)
Section titled “Player events (game events)”Fired for any player crossing triggers / colliding with objects inside this script’s content root. Single-argument — the event does not tell you which trigger or collider was involved. If you need that, use Unity’s OnTriggerEnter(Collider) on the specific trigger GameObject and filter for a player collider inside.
| Event | Signature |
|---|---|
OnPlayerJoined | void OnPlayerJoined(Player player) |
OnPlayerLeft | void OnPlayerLeft(Player player) |
OnPlayerRespawned | void OnPlayerRespawned(Player player) |
OnPlayerTriggerEnter | void OnPlayerTriggerEnter(Player player) |
OnPlayerTriggerStay | void OnPlayerTriggerStay(Player player) |
OnPlayerTriggerExit | void OnPlayerTriggerExit(Player player) |
OnPlayerCollisionEnter | void OnPlayerCollisionEnter(Player player) |
OnPlayerCollisionStay | void OnPlayerCollisionStay(Player player) |
OnPlayerCollisionExit | void OnPlayerCollisionExit(Player player) |
Prop events
Section titled “Prop events”Props carry both the Prop handle and the Unity Collider / Collision — useful because a prop can enter multiple triggers in your content.
| Event | Signature |
|---|---|
OnPropSpawned | void OnPropSpawned(Prop prop) |
OnPropDespawned | void OnPropDespawned(Prop prop) |
OnPropTriggerEnter | void OnPropTriggerEnter(Prop prop, Collider other) |
OnPropTriggerStay | void OnPropTriggerStay(Prop prop, Collider other) |
OnPropTriggerExit | void OnPropTriggerExit(Prop prop, Collider other) |
OnPropCollisionEnter | void OnPropCollisionEnter(Prop prop, Collision c) |
OnPropCollisionStay | void OnPropCollisionStay(Prop prop, Collision c) |
OnPropCollisionExit | void OnPropCollisionExit(Prop prop, Collision c) |
Portal events
Section titled “Portal events”| Event | Signature |
|---|---|
OnPortalCreated | void OnPortalCreated(Portal portal) |
OnPortalDestroyed | void OnPortalDestroyed(Portal portal) |
Networking / system events
Section titled “Networking / system events”| Event | Signature | Notes |
|---|---|---|
OnInstanceOwnerChange | void OnInstanceOwnerChange(Player newOwner) | Fires on GSInfoChanged.InstanceOwner. Dispatched via CVR_WasmBehaviour_OnInstanceOwnerChanged(behavioursPtr, count, playerHandle). |
OnInputReady | void OnInputReady() | CVR input subsystem tick. Dispatched via CVR_WasmBehaviour_OnInputReady(behavioursPtr, count). The host also mirrors the current CVRInputStruct into the guest’s _inputStructPtr every tick, even if the behaviour doesn’t define this event. |
OnWorldPermissionsChanged | void OnWorldPermissionsChanged() | Fires only on world VMs (gameObject.scene.buildIndex == -1). Dispatched via CVR_WorldPermissions_OnWorldPermissionsChanged(marshalStructPtr) — single argument, not the behaviour-list shape the others use. The guest-side dispatcher fans it out to every behaviour that defined the method. |
OnReceiveMessage is not an auto-detected event — you subscribe explicitly:
void Start(){ Networking.OnReceiveMessage += HandleNetMessage;}
void OnDestroy(){ Networking.OnReceiveMessage -= HandleNetMessage;}
private void HandleNetMessage(Player sender, Span<byte> message){ // parse and act}The host dispatches incoming payloads through the guest export CVR_Networking_OnReceiveMessage(senderHandle, msgPtr, msgLen) (WasmVM.CallOnReceiveMessage), which the shim converts into the delegate above. See Networking.
Explicitly disallowed events
Section titled “Explicitly disallowed events”Stubbed to empty in CVR.CCK.Wasm/Scripting/WasmBehaviour.cs inside #if !CVR_SCRIPTING_ENVIRONMENT so they compile in Unity but never dispatch at runtime:
OnServerInitialized()OnConnectedToServer()OnGUI()OnApplicationQuit()OnApplicationFocus(bool)OnApplicationPause(bool)
Defining them has no effect. Use OnEnable / OnDisable / OnDestroy for lifecycle hooks.
Execution order
Section titled “Execution order”[DefaultExecutionOrder]
Section titled “[DefaultExecutionOrder]”Unity’s built-in attribute is supported only among WasmBehaviours inside the same VM. It does not change when your scripts run relative to Unity or other CVR systems.
[DefaultExecutionOrder(-100)]public partial class EarlyBird : WasmBehaviour{ void Awake() { /* runs before most other WasmBehaviours in this VM */ }}When multiple behaviours receive the same event (e.g. OnPlayerJoined), their execution order follows this attribute. Two behaviours without the attribute run in undefined order.
Post-phase events and additive scenes
Section titled “Post-phase events and additive scenes”Unity processes execution order per scene. When scenes load additively, each scene runs its full phase before the next:
World scene (active): FixedUpdate -> Update -> LateUpdateRemote Avatars/Props/Portals scene (additive): FixedUpdate -> Update -> LateUpdateLocal Avatar + LateEventManager (DontDestroyOnLoad): FixedUpdate -> fires PostFixedUpdate for all (subscription order) Update -> fires PostUpdate for all LateUpdate -> fires PostLateUpdate for allThis order matters when:
- You sample a player’s final pose —
PostLateUpdateis the only place where local Avatar IK + Network IK have both been applied. - You write to shared state that one of the other scenes will read next frame — use Post-phase variants.
Most scripts don’t need to think about this. If you do, read Unity’s execution order docs alongside.
Script-defined events (UI / persistent callback)
Section titled “Script-defined events (UI / persistent callback)”Any public method on a WasmBehaviour can be the target of a Unity UnityEvent persistent call (e.g. Button.onClick, Slider.onValueChanged). At build time the persistent call is rewritten to WasmRuntimeBehaviour.TriggerScriptEvent*(...) which fires a scripting_call_trigger_script_event* export. See Unity Events Rewiring. Supported argument types:
| Type | Setter | Trigger |
|---|---|---|
UnityEngine.Object | set__InternalEventObjectArg | TriggerScriptEventObject("Method") |
int | set__InternalEventIntArg | TriggerScriptEventInt("Method") |
float | set__InternalEventFloatArg | TriggerScriptEventFloat("Method") |
string | set__InternalEventStringArg | TriggerScriptEventString("Method") |
bool | set__InternalEventBoolArg | TriggerScriptEventBool("Method") |
Void-signature persistent calls become TriggerScriptEvent("Method").
Source
Section titled “Source”CVR-GameFiles/WasmScripting.Enums/UnityEvents.cs— 47-flag[Flags]long enum, one bit per Unity event.CVR-GameFiles/WasmScripting.Enums/GameEvents.cs— 22-flag[Flags]long enum, one bit per CVR game event.CVR-GameFiles/WasmScripting.Enums/ScriptEvent.cs— non-flagintenum, the values passed toscripting_call_event. Unity events occupy IDs 0–49, game events 200–221.CVR-GameFiles/WasmScripting/WasmRuntimeBehaviour.cs— UnityMonoBehaviourcallbacks that route into the VM.CVR-GameFiles/WasmScripting/WasmVM.cs—InitializeEvents, per-eventCall*methods,CallGlobalOnPlayerEvent,CallOnReceiveMessage,CallOnWorldPermissionsChanged.CVR-GameFiles/WasmScripting.Proxies/*Forwarder.cs— engine-side forwarders for the ten Unity events (OnAnimatorIK,OnAnimatorMove,OnAudioFilterRead,OnCollisionStay,OnParticleCollision,OnRenderImage,OnRenderObject,OnTriggerStay,OnWillRenderObject) thatWasmRuntimeBehaviourattaches on demand.
Related
Section titled “Related”- Runtime Lifecycle — where each event export is looked up on the VM.
- Permissions — any event body can throw
WasmAccessDeniedExceptionfrom a binding call. - Unity Events Rewiring — details for hooking UI widgets into script methods.
- Performance — call costs inside event bodies.