Skip to content

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.

Translation = new Vector3(0.0f, 1.0f, 0.0f);   // one metre up

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. ts is the runner's fixed step in seconds, for example 0.02 for 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_ms fields are in milliseconds and StepResponse.physics_step_duration_us is in microseconds. Their names carry the unit.

Angles and rotation

Rotation is the one place where two units coexist:

  • Script API: radians. Entity.Rotation and TransformComponent.Rotation are Euler angles in radians, and Entity.RotationQuat is the same rotation as a quaternion. RigidBodyComponent.Rotate also 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, the verticalFov argument of CameraComponent.SetPerspective, and SpotLightComponent.Angle are 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.Rad2Deg when they call SetInputVector3. See Controlling robots → Driving IK targets.
  • Robot policy commands: the WalkerCommands and RotatorCommands values are command IDs passed to SetFloat, not methods. SetVx and SetVy take metres per second, and SetYawRate takes 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:

float radians = degrees * Mathf.Deg2Rad;
float degrees = radians * Mathf.Rad2Deg;

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;
Speed(m/s)
0.50
TurnAngle(rad)
0.00
Cooldown(s)
1.00

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