Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 0 additions & 98 deletions en/manual/scripts/types-of-script.md

This file was deleted.

119 changes: 119 additions & 0 deletions en/manual/scripts/types-of-script/async-script.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Async script

<span class="badge text-bg-primary">Advanced</span>
<span class="badge text-bg-success">Programmer</span>

Asynchronous scripts get executed only once asynchronously. They can be used for initializing the scene and it's contents or performing game logic for every frame.

```csharp
public class Example : AsyncScript
{
public override Task Execute()
{
// Execute the asynchronous code
}

public override void Cancel()
{
// Do stuff for when the script is unloaded
}
}
```

## When to use

Asynchronous scripts are meant to be used for doing game logic that needs to await something.

If you **don't need to await any tasks**, consider **using a [startup script](./startup-script.md) or a [synchronous script](./sync-script.md)** instead.

## What is asynchronous code?

Asynchronous programming in C# means writing code that can **run in parallel**.

For example: let's say we have a method for saving the game's state that **takes 10 seconds** to execute. Instead of pausing everything until it finishes running, **we can run it asynchronously**, meaning that **the game can continue while we are saving the player's progress**.

An asynchronous method is a normal method that returns a `Task`, which can then be awaited. While it's running, other non asynchronous and asynchronous code will be allowed to run.

```csharp
protected override async Task Execute()
{
// Waits for 1 second without freezing the game
await Task.Delay(1000);
}
```

## Performing code every frame

In order to keep performing logic for every frame (like a synchronous script), you can use `Script.NextFrame()` in a loop.

```csharp
public class Example : AsyncScript
{
public override async Task Execute()
{
// Initialization code goes here

// A loop that will keep running as long as the script is active
while (Game.IsRunning)
{
// Code that gets executed every frame goes here

await Script.NextFrame();
}
}
}
```

## Executing tasks in parallel

Sometimes it's useful to execute two async tasks in the same script. This can be achieved using [`Script.AddTask()`](xref:Stride.Engine.Processors.ScriptSystem.AddTask).

```csharp
public class Example : AsyncScript
{
public override async Task Execute()
{
Script.AddTask(ParallelTask);

// Execute code at the same time as ParallelTask
}

private async Task ParallelTask()
{
// Execute code at the same time as Execute
}
Comment thread
ferafiks marked this conversation as resolved.
}
```

> [!WARNING]
> **Avoid using [`Task.Run`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run)** for parallel tasks, as it will execute your code **on the thread pool instead of the main thread**. This will make interacting with the engine **unsafe** and could result in **unexpected behaviours**.

## Overridable methods

Asynchronous scripts feature 2 methods which can be overridden in order to perform game logic.

> [!NOTE]
> These methods **only get called during runtime** - they will never be called in Game Studio.

### `Execute()`

The [Execute](xref:Stride.Engine.AsyncScript.Execute) method gets called when the script is added to the game. For example:
* When a scene the script is in gets loaded
* When a new entity containing the script is added to a scene
* When the script is added to an already existing entity

The method may be executed more than once if an entity the script is attached to gets removed and then re-added to the scene.

### `Cancel()`

The [Cancel](xref:Stride.Engine.ScriptComponent.Cancel) method gets called when the script is removed from the game. This includes:
* When a scene the script is in gets unloaded
* When an entity the script is attached to gets removed from it's scene
* When the script gets removed from a scene entity
* When the game gets closed

The method may be executed more than once if an entity the script is attached to gets re-added and then removed from the scene.

## Tutorial

Check out the [Async scripts tutorial](../../../tutorials/csharpintermediate/async-scripts.md) for more examples.
77 changes: 77 additions & 0 deletions en/manual/scripts/types-of-script/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Types of script

<span class="badge text-bg-primary">Beginner</span>
<span class="badge text-bg-success">Programmer</span>

There are three main types of script in Stride: **startup scripts**, **synchronous scripts**, and **asynchronous scripts**.

When you write your script, inherit from the type of script with the behavior that best fits your needs.

## Startup scripts

Startup scripts only run when they are added or removed at runtime. They're mostly used to initialize game elements (eg spawning characters) and destroy them when the scene is unloaded. They have a [Start](./startup-script.md#start) method for initialization and a [Cancel](./startup-script.md#cancel) method. You can override either method if you need to.

```cs
public class Example : StartupScript
{
public override void Start()
{
// Do some stuff during initialization
}
}
```

For more information check out the [startup script page](./startup-script.md).

## Synchronous scripts

Synchronous scripts are initialized, then updated every frame, and finally canceled (when the script is removed).

* The initialization code, if any, goes in the [Start](./sync-script.md#start) method.
* The code performing the update goes in the [Update](./sync-script.md#update) method.
* The code performing the cancellation goes in the [Cancel](./sync-script.md#cancel) method.

The following script performs updates every frame, no matter what:

```cs
public class Example : SyncScript
{
public override void Update()
{
// Do stuff that needs to be executed every frame
}
}
```

For more information check out the [sync script page](./sync-script.md).

## Asynchronous scripts

Asynchronous scripts are initialized only once, then canceled when removed from the scene.

* Asynchronous code goes in the [Execute](./async-script.md#execute) function.
* Code performing the cancellation goes in the [Cancel](./async-script#cancel) method.

The following script performs actions that depend on events and triggers:

```cs
public class Example : AsyncScript
{
public override async Task Execute()
{
// Execute asynchronous code
}
}
```

For more information check out the [async script page](./async-script.md).

## See also

* [Create a script](create-a-script.md)
* [Use a script](use-a-script.md)
* [Public properties and fields](public-properties-and-fields.md)
* [Scheduling and priorities](scheduling-and-priorities.md)
* [Events](events.md)
* [Debugging](debugging.md)
* [Preprocessor variables](preprocessor-variables.md)
53 changes: 53 additions & 0 deletions en/manual/scripts/types-of-script/startup-script.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Startup script

<span class="badge text-bg-primary">Beginner</span>
<span class="badge text-bg-success">Programmer</span>

Startup scripts run when they are added or removed from a scene.

```csharp
public class Example : StartupScript
{
public override void Start()
{
// Do stuff for when the script is loaded
}

public override void Cancel()
{
// Do stuff for when the script is unloaded
}
}
```

## When to use

Startup scripts are meant to be used for **executing code once when the scene is loaded or when an entity the script is attached to is added to a scene**. They serve as a way to initialize other scripts and entities, but not control them every frame.

However, if your code **needs to await asynchronous methods**, then it's advised to **use an [asynchronous script](./async-script.md)** instead.

## Overridable methods

Startup scripts feature 2 methods which can be overridden in order to perform game logic.

> [!NOTE]
> These methods **only get called during runtime** - they will never be called in Game Studio.

### `Start()`

The [Start](xref:Stride.Engine.StartupScript.Start) method gets called when the script is added to the game. For example:
* When a scene the script is in gets loaded
* When a new entity containing the script is added to a scene
* When the script gets added to an already existing entity

The method may be executed more than once if an entity the script is attached to gets removed and then re-added to the scene.

### `Cancel()`

The [Cancel](xref:Stride.Engine.ScriptComponent.Cancel) method gets called when the script is removed from the game. This includes:
* When a scene the script is in gets unloaded
* When an entity the script is attached to gets removed from it's scene
* When the script gets removed from a scene entity
* When the game gets closed
Comment thread
ferafiks marked this conversation as resolved.

The method may be executed more than once if an entity the script is attached to gets re-added and then removed from the scene.
Loading