# 从 Unity Runtime 调用

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

在 Unity 编辑器中从经过身份验证的游戏客户端调用模块终端来运行该终端。

> **Note:**
>
> **注意：** 如果一个模块在过去 15 分钟内没有收到任何流量，可能遇到了冷启动延迟。对该模块的所有后续调用会更快。

## 先决条件##prerequisites

要在 Unity 编辑器中使用 Cloud Code，必须先安装 Cloud Code SDK，并将 [Unity Gaming Services（Unity 游戏服务）项目](/cloud/projects.md)关联到 Unity 编辑器。

## 关联项目##link-project

将 [Unity Gaming Services（Unity 游戏服务）项目](/cloud/projects.md)与 Unity 编辑器关联。您可以在 Unity Dashboard 中找到您的 UGS Project ID。

1. 在 Unity 编辑器中，选择 **Edit（编辑）**> **Project Settings（项目设置）**> **Services（服务）**。

2. 关联您的项目。

   * 如果项目没有 Unity Project ID：

     1. 选择 **Create a Unity Project ID（创建 Unity Project ID）**> **Organizations（组织）**，然后从下拉菜单中选择一个组织。
     2. 选择 **Create project ID（创建 Project ID）**。

   * 如果已有 Unity Project ID：

     1. 选择 **Use an existing Unity project ID（使用现有 Unity Project ID）**。
     2. 从下拉菜单中选择组织和项目。
     3. 选择 **Link project ID（关联 Project ID）**。

此时将显示您的 Unity Project ID，并且项目现在已关联到 Unity 服务。此外，还可以使用 `UnityEditor.CloudProjectSettings.projectId` 在 Unity 编辑器脚本中访问您的 Project ID。

## SDK 安装##sdkinstallation

要安装适用于 Unity 编辑器的最新 Cloud Code 包，请执行以下操作：

1. 在 Unity 编辑器中，打开 **Window（窗口）**> **Package Manager（包管理器）**。
2. 在 Package Manager（包管理器）中，选择 **Unity Registry（Unity 注册表）** 列表视图。
3. 搜索 `com.unity.services.cloudcode` 或在列表中找到 Cloud Code 包。
4. 选择包，然后单击 **Install（安装）**。

> **Note:**
>
> 请查看 [Unity - 手册：Package Manager（包管理器）窗口](https://docs.unity3d.com/Manual/upm-ui.html)，熟悉 Unity Package Manager（包管理器）界面。

## SDK 设置##sdk-setup

开始使用 Cloud Code SDK：

1. 确保通过 Cloud Code 服务后台页面启用该服务。
2. 确保 Cloud Code SDK 和 Authentication SDK 均已安装。
3. 在 Unity 编辑器中选择 **Edit（编辑）**> **Project Settings...（项目设置...）**> **Services（服务）** 登录到您的云项目。
4. 在 Unity 编辑器中创建新的 C# Monobehaviour 脚本。请参阅 Unity 手册中的[创建和使用脚本](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html)。
5. 在脚本中，使用 await `UnityServices.InitializeAsync()` 初始化 Core SDK。
6. 在脚本中，初始化 Authentication SDK。

## 典型工作流程##typical-workflow

您可以在 Unity 编辑器中从常规 MonoBehaviour C# 脚本调用 Cloud Code SDK。

1. 在 Unity 引擎中创建 C# `MonoBehaviour` 脚本。请参阅 [Unity - 手册：创建和使用脚本](https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html)。
2. 在 `MonoBehaviour` 脚本中，配置 [Unity Authentication](#authentication) 服务。
3. 在 `MonoBehaviour` 脚本中，添加对 Cloud Code SDK 的调用。
4. 将 `MonoBehaviour` 脚本附加到游戏对象。请参阅[编辑器脚本](https://docs.unity3d.com/Manual/ScriptingSection.html)。
5. 选择 **Play（运行）** 并运行项目，查看 Cloud Code 的运行情况。

## 身份验证##authentication

玩家必须拥有有效的玩家 ID 和访问令牌才能访问 Cloud Code 服务。在使用任何 Cloud Code API 之前，您必须使用 Authentication SDK 对玩家进行身份验证。为此，可以在 C# Monobehaviour 脚本中初始化 Authentication SDK。请参阅[对玩家进行身份验证](../authentication#authenticate-players)。

要初始化 Authentication SDK，请在 C# Monobehaviour 脚本中添加以下代码：

*C#*

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

首先，我们建议使用匿名身份验证。以下示例演示了如何使用身份验证包启动匿名身份验证，并在 Unity 编辑器中使用脚本记录玩家 ID。

*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();
    }
}
```

## 调用 Cloud Code 模块终端##calling-a-cloud-code-module-endpoint

在新创建的脚本中加入身份验证后，您就可以调用 Cloud Code 模块终端了。为了将 Cloud Code 集成到 Unity 编辑器项目中，请添加以下命名空间：

```cs
Using Unity.Services.CloudCode;
```

以下示例假设您已经部署了一个名为 `HelloWorld` 的模块，其中包含一个名为 `RollDice` 的终端，代码如下：

```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

您可以为 Cloud Code 模块生成编辑器绑定，以便在 Unity 编辑器界面中使用这些模块。请参阅[生成绑定](../write-modules/unity-editor#generate-bindings)以了解更多信息。

以下示例以类型安全 (type-safe) 的方式从 Unity 编辑器调用 Cloud Code 模块。在 Unity 编辑器中创建 C# MonoBehaviour 脚本 `RollDiceExample`，并包含以下代码：

*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);
        }
    }
}
```

### 使用 `CallModuleEndpointAsync`##use-callmoduleendpointasync

还可以使用位于 `CloudCodeService.Instance` 下的 `CallModuleEndpointAsync` API 客户端方法。

*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);
```

* `module` 参数是模块的名称。
* `function` 参数是模块终端的名称，由 `CloudCodeFunction` 属性进行标记。
* `args` 参数是传递给模块终端的参数字典。

在 Unity 编辑器中创建 C# Monobehaviour 脚本 `RollDiceExample`。以下是如何将 Authentication 和 Cloud Code 集成到脚本中的完整示例：

```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();

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

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

### 运行该脚本##run-the-script

要测试该脚本，请将其附加到 Unity 编辑器中的游戏对象，然后选择 **Play（运行）**。

您可以在 `Start()` 方法中包含以下代码来调用 `CallMethod()` 方法：

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