Skip to content

OpenFlight port

TL;DR: OpenFlight’s actual lift comes from hand position deltas — detect flap, apply upward impulse proportional to hand speed. CVR WASM does not expose hand transforms to scripts, so the flap model cannot be reproduced. The port keeps the orchestration layer (FlightMode state machine, avatar-whitelist detection, CanFly / CannotFly hooks) and provides a stand-in SimpleHoverFlight driven by CVRInput axes.

PartPorts?Notes
FlightMode enum + state machineYesIdentical
AvatarDetection whitelistYesUses Avatar.GetContentId() instead of VRC avatar id
SwitchFlight(bool) toggling a sub-GameObjectYesSame SetActive(bool) pattern
WingFlightPlusGlide flap liftNoNeeds hand velocity; not exposed
VR-only flightPartialNo direct IsUserInVR(), but LocalPlayer.GetPlaySpaceOffset() returns Vector3.zero unconditionally in desktop (VR returns a non-zero playspace offset); use that as a heuristic. Edge case: a VR user at the exact tracking centre also reads zero until they move.
JSON avatar whitelist downloaded at runtimeNoPossible via WebRequest world permission; left to author

The original ships three runtime scripts you need (OpenFlight.cs, AvatarDetection.cs, WingFlightPlusGlide.cs) plus a pile of UI, integration, and logger helpers. The port provides:

  • OpenFlight — state machine + wiring, unchanged in shape.
  • AvatarDetection — keeps the ReevaluateFlight() public entry point; whitelist is a static string[] in the inspector.
  • SimpleHoverFlight — replaces WingFlightPlusGlide. Reads CVRInput.Movement and the Jump / Sprint buttons, writes via LocalPlayer.SetVelocity().

Everything else (PoolController, PlayerInfoStore, the UI stack, CyanPlayerObjectPool integration) is skipped — those scripts are infrastructure for VRChat-specific player pool syncing and have no direct analogue.

  1. Put OpenFlight on an empty root object (world scale must be 1).
  2. Put SimpleHoverFlight on a child GameObject; assign that child to OpenFlight.wingedFlight.
  3. Put AvatarDetection on another GameObject; wire it back at OpenFlight.avatarDetection. Fill flightWhitelist with avatar content ids.
  4. When the player swaps avatars, call avatarDetection.ReevaluateFlight(). There’s no automatic avatar-change hook exposed to scripts — call it from your content’s equivalent of the OnPlayerRespawned or a timer.