# Systems

Decentraland scenes rely on *systems* to update any data over time, including information stored in each entity's [components](/creator/scenes-sdk7/architecture/entities-components.md).

![](/files/PkQSel4dkPfJ1v9USxu1)

*systems* are what make scenes dynamic, they're functions that are executed periodically on every tick of the scene's game loop, changing what will be rendered.

The following example shows a basic system declaration:

```ts
// Define the system
function mySystem() {
  console.log("Performed on every tick. My system is running")
}
// Add system to engine
engine.addSystem(mySystem)
```

The function in a system can perform anything you want. Typically, it will act upon all the entities that meet certain [query](/creator/scenes-sdk7/architecture/querying-components.md), following certain logic to change the values stored in the entity's components.

```ts
function moveSystem(dt: number) {
  // iterate over all entiities with a Transform
  for (const [entity] of engine.getEntitiesWith(Transform)) {

  // fetch a mutable Transform component
  const transform = Transform.getMutable(entity)

  // update the position value
    transform.position.z += 0.01
  }
}

engine.addSystem(moveSystem)
```

In the example above, the system `MoveSystem` is a function that runs on each tick of the game loop, changing position of every entity in the scene that has a Transform.

![](/files/oYr4IZybDo3BTK5EBPnt)

You can have multiple systems in your scene to decouple different behaviors, making your code cleaner and easier to scale and reuse. For example, one system might handle physics, another might make an obstacle entity move back and forth continuously, another could handle the AI of characters.

Multiple systems can act on a single entity. For example a non-player character might move on its own based on an AI, but also be affected by gravity when accidentally walking from off a cliff. In that scenario, the physics and the AI systems don't even need to know about each other. They independently reassess their current state on each tick of the game loop and implement their own separate logic.

## The system function

A system's function is executed periodically, once per every tick of the game loop. This happens automatically, you don't need to explicitly call this function from anywhere in your code.

In a Decentraland scene, you can think of the game loop as the aggregation of all the system functions in your scene.

{% hint style="warning" %}
**📔 Note**: If you add multiple instances of a same system to the engine, the function will be executed multiple times per tick of the game loop. For example, adding a system twice could result in an entity moving at twice the speed as expected, as it advances two increments on each tick.
{% endhint %}

## Handle entities by reference

Some components and systems are meant for using only on one entity in the scene. For example, on an entity that stores a game's score or perhaps a main gate that is unique in the scene. To access one of those entities within a system, you can simply refer to the entity or its components by name in the system's functions.

```ts
export function main(){
	// create a new entity
	const game = engine.addEntity()

	// add component to that entity
	ScoreComponent.create(game)
}

// Define the system
export function UpdateScore() {

  // call reference to individual entity
  const points = ScoreComponent.get(game).points
  console.log(points)
}

// Add system to engine
engine.addSystem(UpdateScore)
```

For larger projects, we recommend that you keep system definitions on separate files from the instancing of entities and components.

## Loop over a component query

A lot of times, your scene will have multiple entities of the same type that will have similar behaviors. For example many doors that can be opened, or many enemies that can attack the player. It makes sense to handle all of these similar entities in a single system, iterating over the list and performing the same checks on each.

You don't want a system's function to iterate over *the entire* set of entities in the scene, as this could be very costly in terms of processing power. To avoid this, you can [query components](/creator/scenes-sdk7/architecture/querying-components.md), to only iterate over the relevant entities.

For example, your scene can have a `PhysicsSystem` that calculates the effect of gravity over the entities of your scene. Some entities in your scene, such as trees, are not meant to ever move; so it would be smart to avoid calculating the effects of gravity on these. You can define a `HasPhysics` component to mark entities that could be affected by gravity, and then have `PhysicsSystem` only deal with the entities returned by this query.

```ts
// Define the system
export function PhysicsSystem() {
  // iterate over all entiities with a HasPhysics
  for (const [entity] of engine.getEntitiesWith(HasPhysics)) {

  // fetch a mutable Transform component
  const transform = Transform.getMutable(entity)

  // Calculate effect of physics
  }
}

// Add system to engine
engine.addSystem(PhysicsSystem)
```

## Delta time between frames

The function in a system can optionally include an argument called `dt`, of type `number` (representing *delta time*).

```ts
function MySystem(dt: number) {

  // Udate scene
  console.log("time since last tick: ", dt)
}

engine.addSystem(MySystem)
```

*delta time* represents time that passed since the last tick of the game loop, in seconds.

Decentraland scenes are updated by default at 30 ticks per second. This means that the `dt` argument passed to all systems will tend to equal to *1/30* (0.0333...).

If the processing of a frame takes less time than this interval, then the engine will wait the remaining time to keep updates regularly paced and `dt` will remain equal to *1/30* .

![](/files/ZKYj9RrvqoVHc3HwZCPu)

If the processing of a frame takes longer than *1/30* seconds, the drawing of that frame is delayed. The engine then tries to finish that frame and show it as soon as possible. It then proceeds to the next frame and tries to show it *1/30* seconds after the last frame. It doesn't compensate for the previous delay.

![](/files/je2cd7sup5QH2z7NmkNt)

Ideally, you should avoid your scene dropping frames, as it impacts the quality of the player's experience. Since this is dependant on the processing power of the player's machine, it's always a possibility that your scene should be ready to handle gracefully.

The `dt` variable is useful when frame processing exceeds the default time. Assuming that the current frame will take as much time as the previous one, this information may be used to calculate how much to adjust a gradual change, so that the rate of change appears steady and in proportion to the lag between frames.

See [entity positioning](/creator/scenes-sdk7/3d-content-essentials/entity-positioning.md) for examples of how to use `dt` to make movement smoother.

## Loop at a timed interval

If you want a system to execute something at a regular time interval, you can do this by combining the `dt` argument with a timer.

```ts
let timer: number = 10

function LoopSystem(dt: number) {
  timer -= dt
  if (timer <= 0) {
      timer = 10
      // DO SOMETHING
    }
}

engine.addSystem(LoopSystem)
```

There is also a shortcut function `setInterval` and `clearInterval` that uses Systems on the background. This allows an easier and shorter version when the intention is to run a certain function every X amount of time.

```ts
const intervalId = timers.setInterval(() => {
    console.log('Printing this every 10 seconds')
}, 10000)
```

Where the first argument, `callback`, is the function to be executed (in this case, the `console.log()`), and the second argument, `ms`(1000 in this case), is the miliseconds to wait between each function execution.

To stop the `setInterval` function, `clearInterval` is used.

```
timers.clearInterval(intervalId)
```

Where `intervalId` is the reference to the `setInterval` return defined before.

For more complex use cases, where there may be multiple delays and loops being created dynamically, it may be worth defining a custom component to store an individual timer value for each entity. See [Custom components](/creator/scenes-sdk7/architecture/custom-components.md).

## System execution order

In some cases, when you have multiple systems running, you might care about what system is executed first by your scene.

For example, you might have a *physics* system that updates the position of entities in the scene, and another *boundaries* system that ensures that none of the entities are positioned outside the scene boundaries. In this case, you want to make sure that the *boundaries* system is executed last. Otherwise, the *physics* system could move entities outside the bounds of the scene but the *boundaries* system won't find out till it's executed again in the next frame.

When adding a system to the engine, set an optional `priority` field to determine when the system is executed in relation to other systems.

```ts
engine.addSystem(PhysicsSystem, 1)
engine.addSystem(BoundariesSystem, 5)
```

Systems with a lower priority number are executed first, so a system with a priority of *1* is executed before one of priority *5*.

Systems that aren't given an explicit priority have a default priority of *0*, so these are executed first.

If two systems have the same priority number, there's no way to know for certain which of them will be executed first.

## Remove a system

An instance of a system can be added or removed from the engine to turn it on or off.

If a system is defined but isn't added to the engine, its function isn't called by the engine.

To remove a system, you must first give it a name when adding it to the engine, so that you can refer to the system later.

```ts
// declare system
function mySystem(dt: number){
  console.log("delay since last tick: ", dt)
}

// add system (giving it a priority and name)
engine.addSystem(mySystem, 1, "DelaySystem")

// remove system
engine.removeSystem("DelaySystem")
```

A scene can potentially have multiple instances of a same system running together, so you need to tell the engine which one of those to remove.

Another way to delete a system is to declare a pointer to the system, and then pass that pointer to the `engine.removeSystem()` method.

```ts
// declare system
function mySystem(dt: number){
  console.log("delay since last tick: ", dt)
}

// add system (making a pointer)
const mySystemInstance = engine.addSystem(mySystem)

// remove system
engine.removeSystem(mySystemInstance)
```

Note that the pointer is to the *instance* of the system, not to the system's class. In the above example, `engine.removeSystem()` is not being passed `mySystem` (the system class declaration). It's being passed `mySystemInstance` (the instance that was added to the engine).

You can use the method below to make a system self-terminate when its purpose is complete.

```ts
   const mySystem = function(dt: number){
        time += dt
        if(time > 3){
		engine.removeSystem(mySystem)
        }    
    }
    engine.addSystem(mySystem)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/scenes-sdk7/architecture/systems.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
