Units¶
Lucky Engine uses SI units throughout. Distances are in metres, time in seconds, mass in kilograms, forces in Newtons. Angles are radians in the script API and degrees in the Inspector; the engine converts between them at the boundary.
At a glance
| Quantity | Unit |
|---|---|
| Distance, position, scale | metres (m) |
| Time, durations | seconds (s) |
| Rotation in script | radians (rad) |
| Rotation in Inspector | degrees (°) |
| Mass | kilograms (kg) |
| Force | Newtons (N) |
| Linear velocity | m/s |
| Angular velocity | rad/s |
| Camera FOV | degrees (°) |
| Light intensity | unitless multiplier |
| Audio volume, pitch | unitless multiplier |
Distance and position¶
Translations, world positions, mesh sizes, and collider dimensions are all in metres.
Entity.Translation, Entity.Scale, the Inspector's Transform widget, MuJoCo body
positions, and Jolt rigid bodies all share the same scale.
There are no centimetres or millimetres in the user-facing API.
Time¶
Every duration the engine exposes is in seconds:
OnUpdate(float ts)and the other per-step callbacks.tsis the runner's fixed step in seconds (for example0.02for a 50 Hz runner).Timer.Set(callback, rateSeconds, looping, firstDelaySeconds).- Animation lengths, audio durations.
No public API takes or returns milliseconds.
Angles and rotation¶
Rotation is the one place where two units coexist:
- Script API: radians.
Entity.Rotation,TransformComponent.Rotation, andEntity.RotationQuat(quaternion derived from radians). - Inspector: degrees. The Transform widget reads, displays, and writes degrees; the editor converts to radians when it stores the value.
- Motion-graph IK targets: degrees. The
Target_Orientationinput on a motion graph expects degrees, so script code appliesMathf.Rad2Degat the boundary. - Robot policy angular commands: rad/s.
SetYawRateon the walker takes radians per second.
Two helpers handle the conversions:
Mathf.WrapToPi(radians) normalises an angle to the [-π, π] range.
Why both?
Radians are the natural unit for math and the script API. Degrees are easier to read in the Inspector and in motion-graph editor fields. The conversion is small, consistent, and always at the boundary.
Physics¶
| Quantity | Unit | Where it appears |
|---|---|---|
| Mass | kg | RigidBodyComponent.Mass |
| Force | N | RigidBodyComponent.AddForce |
| Impulse | N·s | RigidBodyComponent.AddImpulse |
| Linear velocity | m/s | RigidBodyComponent.LinearVelocity, walker SetVx, SetVy |
| Angular velocity | rad/s | RigidBodyComponent.AngularVelocity, walker SetYawRate |
All physics solvers (Jolt, MuJoCo, Box2D) use these same units at the C# API boundary.
Camera, lighting, audio¶
- Camera vertical FOV: degrees. The Inspector and
CameraComponent.SetVerticalFOVboth take degrees; an internal helper exposes the radian form when needed. - Light intensity on
DirectionalLightComponent,PointLightComponent, andSpotLightComponent: a unitless multiplier applied to the light's radiance. Not lux, not lumens. - Spot light cone angle: degrees.
- Audio volume and pitch on
AudioComponent(VolumeMultiplier,PitchMultiplier): unitless multipliers around1.0.
Coordinate system¶
The editor world is Y-up, right-handed. Gravity acts in -Y. Transforms, camera,
and rendering all share that convention.
MuJoCo bodies (robots) run in MuJoCo's own coordinate space. The engine bridges between the world and MuJoCo so the simulation stays consistent for both sides.
Declaring units on a field¶
When a public field has a meaningful unit, decorate it with
[Units(...)].
The Inspector appends the suffix to the label, so the unit is visible without forcing
script authors to spell it out in the field name:
[Units("m/s")] public float Speed = 0.5f;
[Units("rad")] public float TurnAngle = 0.0f;
[Units("s")] public float Cooldown = 1.0f;
The attribute is informational. It appends the suffix and nothing else; conversions stay the script's responsibility.