# Call from Unity runtime

> Invoke module endpoints from an authenticated game client in the Unity Editor.

Run a module endpoint by calling it from an authenticated game client in the Unity Editor.

To call a module endpoint from the Unity Editor, complete the following tasks:

1. [Link project](#link-project): Link your Unity Gaming Services (UGS) project with the Unity Editor.
2. [SDK installation](#sdk-installation): Install the Cloud Code package.
3. [SDK setup](#sdk-setup): Create a script and initialize the SDKs.
4. [Authentication](#authentication): Sign in the player with the Authentication SDK.
5. [Calling a Cloud Code module endpoint](#calling-a-cloud-code-module-endpoint): Add the module call to your script.
6. [Run the script](#run-the-script): Make your module available, then test the call in Play mode.

> **Note:**
>
> If a module hasn't received any traffic in the last 15 minutes, you might experience a cold start latency. Any subsequent calls to the module are faster. It's possible to mitigate this by pre-warming the module, thereby [reducing cold start latency](#reduce-cold-start-latency).

## Prerequisites

To use Cloud Code in the Unity Editor, you must first install the Cloud Code SDK and link your [Unity Gaming Services project](/cloud/projects.md) to the Unity Editor.

## Link project

Link your [Unity Gaming Services project](/cloud/projects.md) with the Unity Editor. You can find your UGS project ID in the Unity Dashboard.

1. In Unity Editor, select **Edit** > **Project Settings** > **Services**.

2. Link your project.

   * If your project doesn't have a Unity project ID:

     1. Select **Create a Unity Project ID** > **Organizations**, then select an organization from the dropdown menu.
     2. Select **Create project ID**.

   * If you have an existing Unity project ID:

     1. Select **Use an existing Unity project ID**.
     2. Select an organization and a project from the dropdown menus.
     3. Select **Link project ID**.

Your Unity Project ID appears, and the project is now linked to Unity services. You can also access your project ID in a Unity Editor script using `UnityEditor.CloudProjectSettings.projectId`.

## SDK installation

To install the latest Cloud Code package for Unity Editor:

1. In the Unity Editor, open **Window** > **Package Manager**.
2. In the Package Manager, select the **Unity Registry** list view.
3. Search for `com.unity.services.cloudcode`, or locate the Cloud Code package in the list.
4. Select the package, then click **Install**.

> **Note:**
>
> Check [Unity - Manual: Package Manager window](https://docs.unity3d.com/Manual/upm-ui.html) to familiarize yourself with the Unity Package Manager interface.

## SDK setup##sdk-setup

To get started with the Cloud Code SDK:

1. Ensure the service is enabled via the Cloud Code service dashboard page.
2. Ensure that you have installed both the Cloud Code and the Authentication SDKs.
3. Sign into your cloud project from within Unity Editor by selecting **Edit** > **Project Settings** > **Services**.
4. Create a new C# Monobehaviour script in Unity Editor. Refer to [Creating and using scripts](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html) in the Unity Manual.
5. In the script, initialize the Core SDK using await `UnityServices.InitializeAsync()`.
6. In the script, initialize the Authentication SDK.

## Authentication

Players must have a valid player ID and access token to access the Cloud Code services.
You must authenticate players with the Authentication SDK before using any of the Cloud Code APIs.
You can do this by initializing the Authentication SDK inside a C# Monobehaviour script.
Refer to [Authenticate players](../authentication#authenticate-players).

To initialize the Authentication SDK, include the following in your C# Monobehaviour script:

*C#*

```cs
await AuthenticationService.Instance.SignInAnonymouslyAsync();
```

The recommended best practice is to get started with anonymous authentication. The following example demonstrates how to start anonymous authentication using the [Authentication package](https://docs.unity3d.com/Packages/com.unity.services.authentication@latest) and log the player ID in a script within Unity Editor.

*C#*

```cs
using Unity.Services.Authentication;
using System.Threading.Tasks;
using Unity.Services.Core;
using UnityEngine;

public class AuthenticationExample : MonoBehaviour
{
    internal async Task Awake()
    {
        await UnityServices.InitializeAsync();
        await SignInAnonymously();
    }

    private async Task SignInAnonymously()
    {
        AuthenticationService.Instance.SignedIn += () =>
        {
            var playerId = AuthenticationService.Instance.PlayerId;

            Debug.Log("Signed in as: " + playerId);
        };
        AuthenticationService.Instance.SignInFailed += s =>
        {
            // Take some action here...
            Debug.Log(s);
        };

        await AuthenticationService.Instance.SignInAnonymouslyAsync();
    }
}
```

## Calling a Cloud Code module endpoint

After including authentication in your newly created script, you are ready to call a Cloud Code module endpoint. Include the following namespace to integrate Cloud Code into your Unity Editor project:

```cs
using Unity.Services.CloudCode;
```

The samples below assume your project contains a module called `HelloWorld` with an endpoint called `RollDice` with the following code:

```csharp
using System;
using System.Threading.Tasks;
using Unity.Services.CloudCode.Core;

namespace HelloWorld;

public class HelloWorld
{
    public class Response
    {
        public Response(int roll, int sides)
        {
            Roll = roll;
            Sides = sides;
        }

        public int Roll { get; set; }
        public int Sides { get; set; }
    }

    [CloudCodeFunction("RollDice")]
    public async Task<Response> RollDice(int diceSides)
    {
        var random = new Random();
        var roll = random.Next(1, diceSides);

        return new Response(roll, diceSides);
    }
}
```

### Use editor bindings

You can generate editor bindings for your Cloud Code modules, so that you can use them in the Unity Editor interface.
Refer to [Generate bindings](../write-modules/unity-editor-module-reference#generate-bindings) for more information.

The following examples are a type-safe way to call your Cloud Code modules from the Unity Editor.
Create a C# MonoBehaviour script `RollDiceExample` in the Unity Editor, and include the following code:

*C#*

```cs
using Unity.Services.Authentication;
using Unity.Services.CloudCode;
using Unity.Services.CloudCode.GeneratedBindings;
using Unity.Services.Core;
using UnityEngine;

public class RollDiceExample : MonoBehaviour
{
    private async void Start()
    {
        // Initialize the Unity Services Core SDK
        await UnityServices.InitializeAsync();

        // Authenticate by logging into an anonymous account
        await AuthenticationService.Instance.SignInAnonymouslyAsync();

        try
        {
            // Call the function within the module and provide the parameters we defined in there
            var module = new HelloWorldBindings(CloudCodeService.Instance);
            var result = await module.RollDice(6);

            Debug.Log($"You've rolled {result.Roll}/{result.Sides}");
        }
        catch (CloudCodeException exception)
        {
            Debug.LogException(exception);
        }
    }
}
```

### Use `CallModuleEndpointAsync`

You can also use the `CallModuleEndpointAsync` API client method, which you can find under `CloudCodeService.Instance`.

*C#*

```cs
        /// <summary>
        /// Calls a Cloud Code function.
        /// </summary>
        /// <param name="module">Cloud Code Module to call</param>
        /// <param name="function">Cloud Code function to call.</param>
        /// <param name="args">Arguments for the cloud code function. Will be serialized to JSON.</param>
        /// <typeparam name="TResult">Serialized from JSON returned by Cloud Code.</typeparam>
        /// <returns>Serialized output from the called function.</returns>
        /// <exception cref="CloudCodeException">Thrown if request is unsuccessful.</exception>
        /// <exception cref="CloudCodeRateLimitedException">Thrown if the service returned rate limited error.</exception>
        Task<TResult> CallModuleEndpointAsync<TResult>(string module, string function, Dictionary<string, object> args = null);
```

* The `module` parameter is the name of your module.
* The `function` parameter is the name of your module endpoint, which you labeled with the `CloudCodeFunction` attribute.
* The `args` parameter is a dictionary of parameters to pass to the module endpoint.

Create a C# Monobehaviour script `RollDiceExample` in the Unity Editor.
The following is a full example of how to integrate both Authentication and Cloud Code into your script:

```cs
using System.Collections.Generic;
using UnityEngine;
using Unity.Services.Authentication;
using Unity.Services.CloudCode;
using Unity.Services.Core;

public class RollDiceExample : MonoBehaviour
{
    // ResultType structure is the serialized response from the RollDice script in Cloud Code
    private class ResultType
    {
        public int Roll;
        public int Sides;
    }

    // Call this method
    public async void CallMethod()
    {
        await UnityServices.InitializeAsync();
        // Sign in anonymously into the Authentication service
        if (!AuthenticationService.Instance.IsSignedIn) await AuthenticationService.Instance.SignInAnonymouslyAsync();

        // Creates a dictionary of arguments, setting diceSides to 6
        var args = new Dictionary<string, object> { ["diceSides"] = 6 };
        
        // Call out to the RollDice endpoint in the HelloWorld module in Cloud Code
        var response = await CloudCodeService.Instance.CallModuleEndpointAsync<ResultType>("HelloWorld", "RollDice", args);

        // Log the response of the module endpoint in console
        Debug.Log($"You rolled {response.Roll} / {response.Sides}");
    }
}
```

## Run the script

If you use the `CallModuleEndpointAsync` example, add the following `Start()` method to the `RollDiceExample` class, so the script calls `CallMethod()` when it starts:

```csharp
public void Start()
{
    CallMethod();
}
```

To run the script in the Unity Editor:

1. Attach the script to a GameObject in your scene.
2. Make your module available to the script in one of the following ways:
   * To call the module on the Cloud Code service, deploy the module to your environment. Refer to [Deploy the module](../write-modules/unity-editor#deploy-the-module).
   * To test module changes without deploying them, start a local Cloud Code server. Refer to [Execute modules on the local server](../local-cloud-code-server#execute-modules-on-the-local-server).
3. In the toolbar, select **Play** to enter Play mode.

The **Console** window displays the result of the module call. If the call fails, make sure that the local server is running, or that the module is deployed to the environment selected in the Unity Editor.

If you enter Play mode through a Multiplayer Play Mode scenario with **Deploy to Cloud Code** enabled, the scenario chooses the server instead. Refer to [Multiplayer Play Mode integration](../mppm-integration).

## Reduce cold start latency

Every C# module in a project runs in the same module host. If the module host hasn't served a call in the last 15 minutes, the first module call waits while the host starts. Use `ModuleHostWarmup` to start the module host when the player signs in, so it's ready by the time the game calls a module.

`ModuleHostWarmup` is in the `Unity.Services.CloudCode` namespace. One warm-up covers every module in the project, so use the shared `ModuleHostWarmup.Default` instance.

### Arm the warm-up

Call `Arm()` at `BeforeSceneLoad` or later:

```cs
using Unity.Services.CloudCode;
using UnityEngine;

static class CloudCodeStartup
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void ArmModuleHostWarmup()
    {
        ModuleHostWarmup.Default.Arm();
    }
}
```

`Arm()` waits for Unity Services to initialize and a player to sign in, then sends a warm-up request. If a player is already signed in, it sends the request immediately. The warm-up runs once for each call to `Arm()`, because one module host serves every player in the project. Calling `Arm()` again while the warm-up is armed has no effect.

If you call `Arm()` before Unity Services exists, it logs a warning and does nothing.

### Wait for the module host

`ModuleHostWarmup` has two properties that report the warm-up's progress:

| Property | Description                                                                                                                                                                                                       |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IsWarm` | `true` after the module host responds to the warm-up request.                                                                                                                                                     |
| `Task`   | The warm-up in progress, or `null` if it hasn't started yet. The task completes when the module host is ready, faults with a `CloudCodeException` if the module host doesn't start. Calling `Reset()` cancels it. |

To make sure the first module call doesn't wait for the module host to start, await `Task` before the call:

```cs
using System.Threading.Tasks;
using Unity.Services.CloudCode;
using UnityEngine;

public class FirstModuleCall : MonoBehaviour
{
    async Task WaitForModuleHostAsync()
    {
        var warmup = ModuleHostWarmup.Default;
        if (warmup.IsWarm || warmup.Task == null)
            return;

        try
        {
            await warmup.Task;
        }
        catch (CloudCodeException e)
        {
            Debug.LogWarning($"Module host warm-up failed: {e.Message}");
        }
    }
}
```

While the module host is starting, the warm-up retries up to five times with exponential backoff. It doesn't retry errors that waiting can't fix, such as authentication errors or rate limiting. After a failed warm-up, call `Arm()` again to retry.

If the host doesn't support warm-up requests, as with the [local Cloud Code server](../local-cloud-code-server), `Task` completes without an error and `IsWarm` stays `false`, but module calls work as normal.

### Warm up a separate Unity Services instance

If your game calls Cloud Code through its own `IUnityServices` instance, create a `ModuleHostWarmup` for that instance instead of using `Default`. Call `Reset()` when you stop using the instance. `Reset()` cancels any warm-up in progress and stops waiting for a player to sign in. The next call to `Arm()` starts again.

```cs
var warmup = new ModuleHostWarmup(services);
warmup.Arm();

// When you stop using the services instance:
warmup.Reset();
```

## Additional resources

* [Run a local Cloud Code server](../local-cloud-code-server)
* [Multiplayer testing workflow](../multiplayer-testing-workflow)
* [Get started with Cloud Code modules](../../getting-started)
