Units¶
Lucky Engine uses SI units throughout. Distances are in metres, time in seconds, mass in kilograms and forces in newtons. Angles are radians in the script API and degrees in the Inspector, with a few exceptions listed on this page.
At a glance
| Quantity | Unit |
|---|---|
| Distance, position, size | metres (m) |
| Time, durations | seconds (s) |
| Rates (runners, sensors) | hertz (Hz) |
| Rotation in script | radians (rad) |
| Rotation in the Inspector | degrees (°) |
| Camera field of view | degrees (°), in the Inspector and in script |
| Mass | kilograms (kg) |
| Force | newtons (N) |
| Linear velocity | m/s |
| Angular velocity | rad/s |
| Directional, point and spot light intensity | unitless multiplier |
| Area light intensity | nits (cd/m²) |
| 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 fields, MuJoCo body
positions and Jolt rigid bodies all share the same scale.
There are no centimetres or millimetres in the scripting API. In the editor, millimetres appear in one camera field, Sensor Height (mm), and you can type distances in other units when you move objects with the keyboard or set up the editor camera (see Typing values in the editor).
Time¶
Simulation time and durations are 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).- Settings fields that carry
(s)in their label, such as Watchdog Timeout (s).
Rates are in hertz. A runner at 50 Hz steps every 1/50 s; see The Time Manager.
A few performance and network values use smaller units:
PerformanceTimers.GetFrameTime()returns milliseconds.- In the gRPC API,
timestamp_msfields are in milliseconds andStepResponse.physics_step_duration_usis in microseconds. Their names carry the unit.
Angles and rotation¶
Rotation is the one place where two units coexist:
- Script API: radians.
Entity.RotationandTransformComponent.Rotationare Euler angles in radians, andEntity.RotationQuatis the same rotation as a quaternion.RigidBodyComponent.Rotatealso takes radians. - Inspector: degrees. The Transform fields read, display and write degrees, and the editor converts to radians when it stores the value.
- Exceptions in script:
CameraComponent.VerticalFOV, theverticalFovargument ofCameraComponent.SetPerspective, andSpotLightComponent.Angleare in degrees, as they are in the Inspector. - Motion-graph orientation inputs: the graph decides the unit. The robot motion graphs
that ship with Lucky Engine take orientation targets in degrees, so scripts convert with
Mathf.Rad2Degwhen they callSetInputVector3. See Controlling robots → Driving IK targets. - Robot policy commands: the
WalkerCommandsandRotatorCommandsvalues are command IDs passed toSetFloat, not methods.SetVxandSetVytake metres per second, andSetYawRatetakes radians per second. - MuJoCo joint positions, for example from
MujocoSceneComponent.GetJointPositions, follow MuJoCo's convention: radians for hinge joints, metres for slide joints.
Two constants handle the conversions:
Mathf.WrapToPi(radians) normalises an angle to the [-π, π] range.
Why both?
Radians are the natural unit for maths and the script API. Degrees are easier to read in the Inspector and in motion-graph fields. The conversion is small, consistent, and always at the boundary.
Typing values in the editor¶
Number fields in the Inspector and in Settings accept arithmetic, evaluated when you press
Enter or click away: 0.5*3, (1+2)/4, sqrt(2). They do not accept unit
suffixes. Type the value in the field's own unit, as given in its label or on this page.
A value such as 5cm or 90deg is rejected, and the field keeps its old value.
Two functions help with angles:
| Function | Converts | Example |
|---|---|---|
r2d(x) |
radians to degrees | r2d(pi/2) in a Rotation field gives 90 |
d2r(x) |
degrees to radians | d2r(45) in a script field measured in radians gives 0.785… |
The trigonometric functions (sin, cos, tan and their inverses) work in radians.
Editing Values lists every operator, function and constant.
Moving objects with the keyboard is one exception. While you move a selection with G,
a typed distance may carry a unit suffix: mm, cm, m, km, in or ft, for example
1m + 5cm (1.05 m) or 6in. A number without a suffix is in metres. A typed rotation
(R) is in degrees, and a typed scale (S) is a plain factor. See
Viewport Navigation.
The menus on a Scene tab's toolbar are the other. In the Camera menu, which sets up the editor camera, fields that have a unit show it after the value and accept a suffix:
| Field | Suffixes | Without a suffix |
|---|---|---|
| Near Clip, Far Clip, Focus Distance | mm, cm, m, km, in, ft |
metres |
| Vertical FOV | deg, °, rad |
degrees |
| Shutter Speed, Brighten Time, Darken Time | ms, s, min, h |
seconds |
For example, 250ms in Brighten Time gives 0.25 s, and 2cm in Near Clip gives
0.02 m. Gizmos → Size in the Overlay menu is a percentage:
150 and 1.5x both mean 150%.
Physics¶
| Quantity | Unit | Where it appears |
|---|---|---|
| Mass | kg | RigidBodyComponent.Mass |
| Force | N | RigidBodyComponent.AddForce(force) (the default mode, EForceMode.Force) |
| Impulse | N·s | RigidBodyComponent.AddForce(impulse, EForceMode.Impulse) |
| Velocity change | m/s | RigidBodyComponent.AddForce(deltaV, EForceMode.VelocityChange), ignores mass |
| Acceleration | m/s² | RigidBodyComponent.AddForce(acceleration, EForceMode.Acceleration), ignores mass |
| Torque | N·m | RigidBodyComponent.AddTorque |
| Linear velocity | m/s | RigidBodyComponent.LinearVelocity, walker commands SetVx and SetVy |
| Angular velocity | rad/s | RigidBodyComponent.AngularVelocity, walker command SetYawRate |
AddForceAtLocation takes its location in world-space metres. All physics engines (Jolt,
MuJoCo, Box2D) use these units at the C# API boundary.
Camera, lighting, audio¶
Camera. The vertical field of view is in degrees: Vertical FOV in the Inspector,
and CameraComponent.VerticalFOV or SetPerspective(verticalFov, nearClip, farClip) in
script. Near and far clip distances are in metres.
A camera in Physical mode, and the exposure settings, show their units in the field labels:
| Field | Unit |
|---|---|
| FOV (degrees) (Fisheye and Kannala-Brandt lenses) | degrees |
| Aperture F-Stop, Aperture (f-stop) | f-number, no unit |
| Focus Distance (m) | metres |
| Sensor Height (mm) | millimetres |
| Shutter Speed (s) | seconds |
| ISO | ISO sensitivity |
| Exposure Compensation | stops (EV) |
| Min EV, Max EV | exposure value |
| Adaptation Time Brighten (s), Adaptation Time Darken (s) | seconds |
These settings are set in the Inspector; the C# CameraComponent does not expose them.
Cameras and Exposure explains what they do.
Lighting.
- Intensity on directional, point and spot lights (
DirectionalLightComponent,PointLightComponent,SpotLightComponent) is a unitless multiplier applied to the light's colour. It is not lux or lumens. - Angle on a spot light is the cone angle in degrees, from 1 to 160.
- Intensity on an area light follows a nits (cd/m²) convention for a white light, and its Width, Height, Radius and Length are in metres. See Lights and Materials.
Audio. VolumeMultiplier and PitchMultiplier on AudioComponent are unitless
multipliers around 1.0.
Sensors¶
| Quantity | Unit | Where it appears |
|---|---|---|
| Lidar range | metres, -1 for no return |
MujocoSceneComponent.GetLidarScan, gRPC GetLidarScan, recorded scans |
| Lidar intensity | 0 to 1, -1 when not available |
MujocoSceneComponent.GetLidarScanChannels |
| Lidar vertical field of view | degrees | Vertical FOV Min (deg), Vertical FOV Max (deg) |
| Lidar beam azimuth and elevation | radians | MujocoSceneComponent.GetLidarBeamAngles |
| Lidar spin or pattern rate | Hz | Rotation Hz, Pattern Hz |
| Sensor ranges and offsets | metres | Min Range (m), Max Range (m), Mount Offset, Stereo Baseline (m) |
| Depth image values | 16-bit codes; metres = code × depth scale | Depth Scale (m/code), default 0.001 (1 mm per code, up to 65.535 m) |
| Depth camera field of view | degrees | The camera's Vertical FOV |
For depth frames received over gRPC, read the scale from ImageFrame.depth_scale rather
than assuming a value. Lidar and RGBD and Depth cover
the sensors in full.
Coordinate system¶
The editor world is Y-up, right-handed. Gravity acts along -Y, at 9.81 m/s² by
default. Transforms, cameras and rendering all share that convention.
MuJoCo bodies (robots) run in MuJoCo's own coordinate space, which is Z-up. The engine converts between the world and MuJoCo so the simulation stays consistent for both sides. Lidar beam directions and hit normals are reported in the sensor's own frame: +X forward, +Z up.
Declaring units on a field¶
When a public script field has a meaningful unit, decorate it with [Units(...)] (see
Editor Attributes). The Inspector appends
the unit to the field's label in parentheses, so the unit is visible without spelling 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 changes the label and nothing else: the number box
shows the number alone, typed values are read in the field's own unit, and any conversion
stays the script's responsibility. For a field in radians, d2r(...) lets you type a value
in degrees.
Where to go next¶
- Editing Values explains dragging, typing and expressions in number fields.
- The Time Manager explains runners, rates and the fixed step
ts. - Working with Components shows how scripts read and drive MuJoCo bodies.
- Controlling Robots uses policy commands and motion-graph inputs in practice.