UGTK cat mascotUGTKengine within an engine Request access

UGTK / Toolkit / Mobile / Motion System Completed

Mobile — UGTK

Motion System

Summary

The Motion System reads real device motion on WebGL through a JavaScript bridge (WebXR pose when available, DeviceOrientation/DeviceMotion sensors as fallback) and exposes orientation, rotation, world velocity/displacement and shake. It raises high-level events for jump, crouch, shake, stationary state and configurable angle thresholds.


Content


Modules Dependencies

This module has no hard UGTK dependencies. On WebGL it relies on a companion .jslib exposing the UGTK_Motion_* bridge functions (permission, start/stop, sample JSON, shake).

Only in the demo scene. The Debug scene of this module also uses UIModule/TextUpdaterSystem. Nothing in the runtime code needs it: import this module on its own and it works, but the demo scene opens with a missing script where that component was.


Setup

  1. Add the MotionObj prefab, which carries Mn_MotionManager.
  2. Describe the gestures you care about as AngleThreshold entries - an Axis, an Op and a value. Jump, crouch and shake are configured this way rather than hard-coded.
  3. Read MotionSample (with its OrientationDeg, Accel and RotRate) if you need the raw values instead.

On WebGL the sensors come from the browser through Plugins/WebGL/UGTK_Motion.jslib, and three conditions must all hold or you get silence rather than an error:

In the editor there are no sensors. That is what the inspector's buttons are for: they fire the same gestures the sensors would, so the game logic can be finished at a desk and only the sensors themselves need a phone.


How To Use

  1. Add Mn_MotionManager to a GameObject. On Start (WebGL) it initialises the JS bridge with the GameObject name and jsCallbackMethod, and, if connectOnStart is true, starts listening (on iOS it may wait for a user tap for permission).
  2. Configure the sensor fallback filters, jump/crouch acceleration thresholds, shake gain/smoothing, integration caps and the angleThresholds list (axis Yaw/Pitch/Roll, operator, threshold, hysteresis, one-shot rearm).
  3. Handle permissions with RequestPermission(), ShowPermissionOverlay(), HasPermission(); control the stream with StartMotion() / StopMotion() and preferences with SetXRPreferred(bool), SetOriginToCurrent(), SetPositionScale(float), ResetDisplacement().
  4. Subscribe to OnSample(MotionSample), OnJump, OnCrouch, OnStationary(bool), OnShake(float), OnXRActiveChanged(bool), and each AngleThreshold.OnTriggered. Read state via IsXRActive, IsStationary, Shake01, WorldVelocity, CurrentRotation, LastSample.
  5. In the Editor there is no real sensor data; holding SPACE simulates shake for quick testing.

Testing Scene

Open MotionSceneTest in the module's Debug/ folder.

What to do, in order:

  1. In the editor, fire jump, crouch, shake and stationary from the inspector.
  2. Build for WebGL, serve it over HTTPS, and open it on a phone.
  3. On iOS, check the permission prompt appears after a tap.
  4. Deny the permission and see what the game does.

Step 1 is how the game logic gets finished without a phone; steps 2 to 4 are the only way to know the sensors themselves work. The failures are silent and in this order of frequency: the page is not HTTPS so sensors are blocked, iOS needs a user gesture before it will even ask, and a denied permission reaches Unity as nothing at all.

The recording is the Editor Test Tools block on MotionObj, which is where this module is legible without a phone: hold the space bar with the Game view focused and the Shake reading climbs to 1 and falls back. Everything else stays still, and says so - there is no sensor in the editor, so Source reads "no sample" and the orientation stays at zero. The buttons underneath raise the events directly, which is enough to finish the game logic before any device is involved.

The scene's own panel shows the same readings inside the game, one line per value:

Mn_MotionReadout, on the scene's Canvas, fills it. Every line whose value can only come from the browser says no sensor rather than 0 while you are in the editor: a tilt of exactly zero and a tilt that was never measured look identical otherwise, and the second one is what the editor has.


Technical Info


© 2026 Marcello De Bonis. All rights reserved

Real dependenciesOpen in the map →

Depends on 2

Used by 0

  • No other module depends on it.

Measured from the repository: code references (asmdef) plus prefab and asset GUIDs. Importing this module alone brings in 3 modules in total.