Getting Started¶
Scripts add behaviour to entities in a scene. This page explains the scripting model, then walks through a first script that drives a Unitree G1 humanoid with the keyboard.
In short
A script is a C# class that derives from Entity and is attached to an entity through a
Script component. The engine calls its lifecycle methods, such as OnCreate and
OnUpdate, while the scene plays. Install the .NET 9 SDK first; see
Creating and building scripts.
The scripting model¶
Lucky Engine scripts are C# classes that derive from Entity.
The scripting API lives in the Hazel namespace, so script files start with
using Hazel;. Your own classes can be in any namespace; new scripts use the project's
Default Namespace. A compiled script attaches to an entity in the editor through a
Script component, and the engine calls the overridden lifecycle methods at the right
moments.
A script has access to:
- This entity: its
Transform,Translation/Rotation/Scale,Tag,Parent, andChildren. - Components:
GetComponent<T>()and friends (see Working with components). - Engine services:
Input,Physics,Audio, the math types, and more.
Your first script¶
This script lets you drive a Unitree G1 with W, A, S and D while the scene plays. The G1's trained walker policy does the walking: W and S move it forward and back, and A and D turn it left and right.
- Get a G1 into a scene. Either create a project from the Unitree G1 template on the Welcome screen (see Get Started), or, in an open project, open View → Robots and click Add to scene on the Unitree G1 (click Download first if it is not installed). See Robots.
- In the Content Browser, right-click an empty area, choose New → Script, enter
WalkerInputas the Class Name, and click Create. - Double-click
WalkerInput.csto open it in the Text Editor, replace its contents with the code below, and save with Ctrl+S. Saving builds the scripts. - Select the robot's root entity, the one with the Robot Controller component. It
already has a Script component running the script the robot came with. Set that
component's Script Class to
WalkerInput. - Press Play in the viewport toolbar (or F5) and drive with W, A, S and D.
using Hazel;
public class WalkerInput : Entity
{
[Tooltip("Forward speed while holding W or S.")]
public float ForwardSpeed = 0.5f;
[Tooltip("Yaw rate while holding A or D.")]
public float TurnRate = 1.0f;
// Id of the walker's slot under Policy Slots in the Robot Controller component.
private const uint k_WalkerSlot = 1u;
private const uint k_SetVx = 1u;
private const uint k_SetVy = 2u;
private const uint k_SetYawRate = 3u;
private RobotControllerComponent? m_Robot;
protected override void OnCreate()
{
m_Robot = GetComponent<RobotControllerComponent>();
m_Robot?.SetPolicyActive(k_WalkerSlot, true);
}
protected override void OnUpdate(float ts)
{
if (m_Robot is null)
return;
float forwardVelocity = 0.0f;
float yawRate = 0.0f;
if (Input.IsKeyDown(KeyCode.W))
forwardVelocity = ForwardSpeed;
if (Input.IsKeyDown(KeyCode.S))
forwardVelocity = -ForwardSpeed;
if (Input.IsKeyDown(KeyCode.A))
yawRate = TurnRate;
if (Input.IsKeyDown(KeyCode.D))
yawRate = -TurnRate;
m_Robot.SetFloat(k_WalkerSlot, k_SetVx, forwardVelocity); // m/s
m_Robot.SetFloat(k_WalkerSlot, k_SetVy, 0.0f); // m/s
m_Robot.SetFloat(k_WalkerSlot, k_SetYawRate, yawRate); // rad/s
}
}
Check the walker's slot Id
Policy slots are numbered in the order the robot's policies were added, starting at 1.
In the Inspector, find the walker under Policy Slots on the Robot Controller
component and look at its Id. If it is not 1, change k_WalkerSlot to match.
Conventions used here
Member fields are prefixed m_ and constants k_, and components are cached in
OnCreate rather than fetched on every step. These are conventions, not requirements.
What's happening:
| Piece | Reference |
|---|---|
: Entity |
Entity, the base class for all scripts |
OnCreate / OnUpdate |
Entity lifecycle |
RobotControllerComponent |
RobotControllerComponent, which holds the robot's policies and motion graph |
SetPolicyActive / SetFloat |
Turn a policy slot on, and send it a command value. For the walker, command IDs 1, 2 and 3 are forward velocity, sideways velocity and yaw rate. |
Input.IsKeyDown(KeyCode.W) |
Input |
Public fields are editable in the Inspector
ForwardSpeed and TurnRate appear as fields on the Script component, labelled with
their C# names. Change them there to retune the robot without touching the code; the
editor also writes the new value into the field's initializer in WalkerInput.cs. See
Editor attributes for sliders, ranges, tooltips, and other
Inspector polish.
Where to go next¶
- Creating and building scripts: the .NET SDK, project files, building, and hot reload.
- Entity lifecycle: every callback and when it fires.
- Time runners: the fixed-step clocks that drive callbacks, and how multiple runners share the timeline.
- Working with components: transforms, physics, and the rest of the component surface.
- Editor attributes: decorate script fields to shape the Inspector.