This library includes a number of helpful pre-built tools that include components, methods, and systems. They offer simple solutions to common scenarios that you're likely to run into.
- Gradual Movement
- Action sequence
Using the Utils library
To use any of the helpers provided by the utils library
- Install it as an
npmpackage. Run this command in your scene's project folder:
npm install decentraland-ecs-utils
- Import the library into the scene's script. Add this line at the start of your
game.tsfile, or any other TypeScript files that require it:
- In your TypeScript file, write
utils.and let the suggestions of your IDE show the available helpers.
Move an entity
To move an entity over a period of time, from one position to another, use the
MoveTransformComponent has three required arguments:
Vector3for the start position
Vector3for the end position
duration: duration (in seconds) of the translation
This example moves an entity from one position to another over 2 seconds:
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define start and end positions// Move entitybox.addComponentnew utils.MoveTransformComponentStartPos, EndPos, 2// Add entity to engineengine.addEntitybox
Follow a path
To move an entity over several points of a path over a period of time, use the
FollowPathComponent has two required arguments:
points: An array of
Vector3positions that form the path.
duration: The duration (in seconds) of the whole path.
This example moves an entity over through four points:
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define the positions of the pathpath = new Vector31, 1, 1path = new Vector31, 1, 15path = new Vector315, 1, 15path = new Vector315, 1, 1// Move entitybox.addComponentnew utils.FollowPathComponentpath, 2// Add entity to engineengine.addEntitybox
Rotate an entity
To rotate an entity over a period of time, from one direction to another, use the
rotateTransformComponent component, which works very similarly to the
rotateTransformComponent has three required arguments:
Quaternionfor the start rotation
Quaternionfor the end rotation
duration: duration (in seconds) of the rotation
This example rotates an entity from one rotation to another over 2 seconds:
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define start and end directions// Rotate entitybox.addComponentnew utils.RotateTransformComponentStartRot, EndRot, 2// Add entity to engineengine.addEntitybox
To rotates an entity continuously, use
KeepRotatingComponent. The entity will keep rotating forever until it's explicitly stopped or the component is removed.
KeepRotatingComponent has one required argument:
rotationVelocity: A quaternion describing the desired rotation to perform each second second. For example
Quaternion.Euler(0, 45, 0)rotates the entity on the Y axis at a speed of 45 degrees per second, meaning that it makes a full turn every 8 seconds.
The component also contains the following method:
stop(): stops rotation and removes the component from any entities its added to.
In the following example, a cube rotates continuously until clicked:
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform// Rotate entitybox.addComponentnew utils.KeepRotatingComponentQuaternion.Euler0, 45, 0// Listen for clickbox.addComponentnew OnClick// Add entity to engineengine.addEntitybox
To adjust the scale of an entity over a period of time, from one size to another, use the
ScaleTransformComponent component, which works very similarly to the
ScaleTransformComponent has three required arguments:
Vector3for the start scale
Vector3for the end scale
duration: duration (in seconds) of the scaling
This example scales an entity from one size to another over 2 seconds:
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define start and end positions// Move entitybox.addComponentnew utils.ScaleTransformComponentStartSize, EndSize, 2// Add entity to engineengine.addEntitybox
All of the translation components, the
FollowPathComponent have an optional argument to set the rate of change. By default, the movement, rotation, or scaling occurs at a linear rate, but this can be set to other options.
The following values are accepted:
The following example moves a box following an ease-in rate:
box.addComponentnew utils.MoveTransformComponentStartPos, EndPos, 2, null, utils.InterpolationType.EASEINQUAD
Callback on finish
All of the translation components, the
FollowPathComponent have an optional argument that executes a function when the translation is complete.
onFinishCallback: function to execute when movement is done.
The following example logs a message when the box finishes its movement. The example uses
MoveTransformComponent, but the same applies to
box.addComponentnew utils.MoveTransformComponentStartPos, EndPos, 2,
FollowPathComponent has a two optional arguments that execute functions when a section of the path is complete and when the whole path is complete.
onFinishCallback: function to execute when movement is complete.
onPointReachedCallback: function to execute when each section of the path is done.
The following example logs a messages when the box finishes each segment of the path, and another when the entire path is done.
box.addComponentnew utils.FollowPathComponentpath, 2,,
ToggleComponent to switch an entity between two possible states, running a same function on every transition.
ToggleComponent has the following arguments:
startingState: Starting state of the toggle (ON or OFF)
onValueChangedCallback: Function to call every time the toggle state changed.
It exposes three methods:
toggle(): switches the state of the component between ON and OFF
isOn(): reads the current state of the component, without altering it. It returns a boolean, where
setCallback(): allows you to change the function to be executed by
onValueChangedCallback, for the next time it's toggled.
The following example switches the color of a box between two colors each time it's clicked.
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define two different materialsgreenMaterial.albedoColor = Color3.GreenredMaterial.albedoColor = Color3.Red// Add a Toggle componentbox.addComponentnew utils.ToggleComponentutils.ToggleState.Off,//listen for click on the box and toggle it's statebox.addComponentnew OnClick// Add entity to engineengine.addEntitybox
Combine Toggle with Translate
This example combines a toggle component with a move component to switch an entity between two positions every time it's clicked.
// Create entity// Give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform//Define two positions for toggling//toggle for wine bottlebox.addComponentnew utils.ToggleComponentutils.ToggleState.Off,//listen for click on the box and toggle it's statebox.addComponentnew OnClick// Add entity to engineengine.addEntitybox
These tools are all related to the passage of time in the scene.
Delay a function
Delay component to an entity to execute a function only after an
n amount of milliseconds.
This example creates an entity that only becomes visible in the scene after 100000 milliseconds (100 seconds) have passed.
// create entity// give entity a shape and set invisibleeasterEggShape.visible = falseeasterEgg.addComponenteasterEggShape// add a delayed functioneasterEgg.addComponentnew utils.Delay100000,// add entity to sceneengine.addEntityeasterEgg
To delay the execution of a task that isn't directly tied to any entity in the scene, create a dummy entity that only holds a
Delay removing an entity
ExpireIn component to an entity to remove it from the scene after an
n amount of milliseconds.
This example creates an entity that is removed from the scene 500 milliseconds after it's clicked.
// create entity// give entity a shapebox.addComponentnew BoxShape// add a function to run when clickedbox.addComponentnew OnClick// add entity to sceneengine.addEntitybox
Repeat at an Interval
Interval component to an entity to make it execute a same function every
This example creates an entity that changes its scale to a random size every 500 milliseconds.
// create entity// give entity a shape and transformbox.addComponentnew BoxShapebox.addComponentnew Transform// add a repeated functionbox.addComponentnew utils.Interval500,// add entity to sceneengine.addEntitybox
To repeat the execution of a task that isn't directly tied to any entity in the scene, create a dummy entity that only holds an
The trigger component can execute whatever you want whenever the player's position or the position of a specific entity or type of entity overlaps with an area.
TriggerComponent has the following arguments:
shape: Shape of the triggering collider area, either a cube or a sphere (
layer: Layer of the Trigger, useful to discriminate between trigger events. You can set multiple layers by using a
triggeredByLayer: Against which layers to check collisions
onTriggerEnter: Callback when an entity of a valid layer enters the trigger area
onTriggerExit: Callback when an entity of a valid layer leaves the trigger area
onCameraEnter: Callback when the player enters the trigger area
onCameraExit: Callback when the player leaves the trigger area
enableDebug: When true makes the trigger area visible for debug purposes.
It exposes the following property:
enabled: Set trigger as enabled or disabled
The following example creates a trigger that changes its position randomly when triggered by the player.
//create entity//create shape for entity and disable its collisionbox.addComponentnew BoxShapebox.getComponentBoxShape.withCollisions = false//set transform component with initial positionbox.addComponentnew Transform//create trigger for entitybox.addComponentnew utils.TriggerComponentnew utils.TriggerBoxShapeVector3.One, Vector3.Zero, //shape0, //layer0, //triggeredByLayernull, //onTriggerEnternull, //onTriggerExit,null //onCameraExit//add entity to engineengine.addEntitybox
You can set a custom shape for the player trigger according to your needs:
utils.TriggerSystem.instance.setCameraTriggerShapenew utils.TriggerBoxShapenew Vector305, 18, 05, new Vector30, -091, 0
Note: The trigger shape can be positioned or stretched, but it can't be rotated on any axis. This is a design decision taken for performance reasons. To cover a slanted area, we recommend adding multiple triggers if applicable.
You can define different layers (bitwise) for triggers, and set which other layers can trigger it.
The following example creates a scene that has:
- food (cones)
- mice (spheres)
- cats (boxes)
Food is triggered (or eaten) by both cats or mice. Also, mice are eaten by cats, so a mouse's trigger area is triggered by only cats.
Cats and mice always move towards the food. When food or mice are eaten, they respawn in a random location.
//define layers//create foodfood.addComponentnew ConeShapefood.getComponentConeShape.withCollisions = falsefood.addComponentnew Transformfood.addComponentnew utils.TriggerComponentnew utils.TriggerBoxShapeVector3.One, Vector3.Zero,foodLayer,mouseLayer | catLayer,//create mousemouse.addComponentnew SphereShapemouse.getComponentSphereShape.withCollisions = falsemouse.addComponentnew Transformmouse.addComponentnew utils.TriggerComponentnew utils.TriggerBoxShapeVector3.One, Vector3.Zero,mouseLayer,catLayer,//create catcat.addComponentnew BoxShapecat.getComponentBoxShape.withCollisions = falsecat.addComponentnew Transformcat.addComponentnew utils.TriggerComponentnew utils.TriggerBoxShapeVector3.One, Vector3.Zero,catLayer//set initial movement for mouse and catmouse.addComponentOrReplacenew utils.MoveTransformComponentmouse.getComponentTransform.position,food.getComponentTransform.position,4cat.addComponentOrReplacenew utils.MoveTransformComponentcat.getComponentTransform.position,food.getComponentTransform.position,4//add entities to engineengine.addEntityfoodengine.addEntitymouseengine.addEntitycat
Use an action sequence to play a series of actions one after another.
IAction interface defines the actions that can be added into a sequence. It includes:
hasFinished: Boolean for the state of the action, wether it has finished its execution or not.
onStart(): First method that is called upon the execution of the action.
update(): Called on every frame on the action's internal update.
onFinish(): Called when the action has finished executing.
Action Sequence Builder
This object creates action sequences, using simple building blocks.
SequenceBuilder exposes the following methods:
then(): Enqueue an action so that it's executed when the previous one finishes.
if(): Use a condition to branch the sequence
else(): Used with if() to create an alternative branch
endIf(): Ends the definition of the conditional block
while(): Keep running the actions defined in a block until a condition is no longer met.
breakWhile(): Ends the definition of the while block
Action Sequence System
The action sequence system takes care of running the sequence of actions. The
ActionsSequenceSystem exposes the following methods:
startSequence(): Starts a sequence of actions
setOnFinishCallback(): Sets a callback for when the whole sequence is finished
isRunning(): Returns a boolean that determines if the sequence is running
stop(): Stops a running the sequence
resume(): Resumes a stopped sequence
reset(): Resets a sequence so that it starts over
The following example creates a box that changes its scale until clicked. Then it resets its scale and moves.
;//set clicked flag//create box entitybox.addComponentnew BoxShapebox.addComponentnew Transformbox.addComponentnew OnClickboxClicked = trueengine.addEntitybox//Use IAction to define action for scaling//Use IAction to define action for movement//Use sequence builder to create a sequence.while!boxClicked.thennew ScaleActionbox, new Vector315,15,15.thennew ScaleActionbox, new Vector305,05,05.endWhile.thennew ScaleActionbox, new Vector31,1,1.thennew MoveActionbox, new Vector31,0,1//Create a sequence system, and add it to the engine to run the sequenceengine.addSystemnew utils.ActionsSequenceSystemsequence