# 手动工作流程

> Create a C# module manually with control over the module deployment process.

本节介绍在项目中创建 C# 模块所需的步骤。

> **Important:**
>
> **重要**：手动工作流程是创建和部署模块的一种底层工作方法。此工作流程非常适合需要更好地控制模块部署过程的高阶情形。对于大多数用例，您可以使用 [Unity 编辑器](./write-modules/unity-editor.md)或 [UGS CLI](./write-modules/cli.md) 获得更简化的体验。如需快速入门，请参阅[入门](../getting-started)指南。

要开始使用 Cloud Code 模块，必须按照以下步骤操作：

1. [创建 .NET 项目：](#create-a-net-project)Cloud Code 模块是简单的 .NET 项目，其中公开了游戏客户端可以调用的终端。
2. [导入 Cloud Code Authoring 包：](#import-the-cloud-code-authoring-package)安装 Cloud Code Authoring 包来创建可调用的终端。
3. [在项目中创建模块终端：](#create-a-module-endpoint)定义可从游戏客户端调用的游戏逻辑。
4. [打包代码：](#package-code)为项目生成程序集，并将它们打包到存档中。
5. [部署项目：](#deploy-a-module-project)将存档部署到 Cloud Code 服务。
6. [调用模块终端：](#call-a-module-function-from-your-game)从游戏客户端调用模块终端。

### 创建 .NET 项目##create-a-net-project

Cloud Code 模块是简单的 .NET 项目，其中公开了游戏客户端可以调用的终端。首先，请在所选的集成开发环境 (IDE) 中创建新的 .NET 项目。要详细了解 Cloud Code 模块的结构，请参阅[模块结构](./module-structure.md)。

以下几节将介绍如何在 JetBrains Rider 和 Microsoft Visual Studio 集成开发环境中创建项目。

#### JetBrains Rider##jetbrains-rider

按照以下步骤在 JetBrains Rider 中创建新项目：

1. 选择 **File（文件）**> **New（新建）**。
2. 选择类库，即 **.NET Core** 或 **.NET Framework**。
3. 为模块命名。
4. 选择 **Create（创建）**。

#### Microsoft Visual Studio##microsoft-visual-studio

按照以下步骤在 Microsoft Visual Studio 中创建新项目：

1. 选择 **File（文件）**> **New Solution（新建解决方案）**。
2. 选择一个 .Net 类库。
3. 选择 **Next（下一步）**。
4. 为模块命名。
5. 选择 **Create（创建）**。

### 导入 Cloud Code Authoring 包##import-the-cloud-code-authoring-package

Cloud Code 模块是 .NET 项目，因此它们使用 [NuGet Package Manager](https://docs.microsoft.com/en-us/nuget/what-is-nuget) 来管理依赖项。

Cloud Code 模块需要 Cloud Code Authoring 包，以便能够创建可调用的终端。这是一个可以安装到项目中的 NuGet 包。

以下几节将演示如何在以下集成开发环境中导入包。

#### JetBrains Rider##jetbrains-rider

按照以下步骤使用 JetBrains Rider 安装 Cloud Code Authoring 包：

1. 选择 **Tools（工具）**> **NuGet** > **Show NuGet Packages（显示 NuGet 包）**。
2. 搜索 `Com.Unity.Services.CloudCode.Core`。
3. 将最新版本安装到您的项目中。

#### Microsoft Visual Studio##microsoft-visual-studio

按照以下步骤使用 Microsoft Visual Studio 安装 Cloud Code Authoring 包：

1. 右键单击项目 > **Manage NuGet Packages（管理 NuGet 包）**。
2. 搜索 `Com.Unity.Services.CloudCode.Core`。
3. 选择 **Add Package（添加包）**。

### 创建模块终端##create-a-module-endpoint

要在 C# 模块中创建终端，您需要创建一个可在外部调用的函数，使用 `CloudCodeFunction` 属性对其进行属性设置，然后为其指定公开使用的名称。

您可以选择不同的函数名称，这样可以在稍后重构代码时不破坏游戏客户端已调用的函数。

您可以使用以下模块函数的简单示例作为参考。此示例创建一个名为 `SayHello` 的模块终端。这个终端接受名为 `name` 的字符串参数并返回一个字符串：

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

namespace ExampleModule;

public class MyModule
{
    [CloudCodeFunction("SayHello")]
    public string Hello(string name)
    {
        return $"Hello, {name}!";
    }
}
```

### 打包代码##package-code

在部署模块之前，需要将代码打包到存档中。

此存档必须包含 Cloud Code 服务运行模块时所需的程序集。

要生成这些程序集，可以[发布项目](https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli)。

您需要为 `linux-x64` 目标运行时构建程序集。要提高性能，可以启用 `ReadyToRun` 编译。

* 如需更多有关如何生成程序集的信息，请参阅[打包代码](./package-code.md)。
* 如需更多有关如何自动执行此过程的信息，请查看[自动执行本地部署](./automate-local-deployment.md)。

按照以下步骤配置集成开发环境以生成程序集。

#### JetBrains Rider##jetbrains-rider

要使用 JetBrains Rider 集成开发环境生成程序集，请按照以下步骤操作：

1. 选择 **Run（运行）**> **Edit Configurations（编辑配置）**。
2. 选择 **+**。
3. 选择 **Publish to folder（发布到文件夹）**。
4. 为配置命名。
5. 将 **Target location（目标位置）** 设置为要存储构建输出的位置。
6. 选择 **Release | Any CPU（发布 | 任何 CPU）** 配置。
7. 选择 **linux-x64** 目标运行时。
8. （可选）启用 **Enable ReadyToRun compilation（启用 ReadyToRun 编译）**。
9. 选择 **Apply（应用）**。

#### Microsoft Visual Studio##microsoft-visual-studio

要使用 Microsoft Visual Studio 集成开发环境生成程序集，请按照以下步骤操作：

1. 右键单击解决方案，然后选择 **Publish（发布）**。
2. 按照屏幕上的步骤将文件存储在本地。
3. 选择 **Show All Settings（显示所有设置）**。
4. 将目标运行时设置为 **linux-x64**。
5. 选择 **Save（保存）**。
6. 选择 **Publish（发布）**。

#### 压缩程序集##zip-the-assemblies

默认情况下，发布过程会按照根项目目录下的 `bin/Release/net6.0/linux-x64/publish` 路径生成一个文件夹。您需要将此文件夹的内容压缩到存档中。

如果您希望[使用 UGS CLI 来部署模块](./write-modules/cli.md#deploy-modules)，建议您将存档文件扩展名更改为 .ccm。

> **Note:**
>
> **注意**：如果在 Windows 中使用文件资源管理器，要将存档文件扩展名更改为 .ccm，需要[启用通用文件扩展名](https://support.microsoft.com/en-us/windows/common-file-name-extensions-in-windows-da4a4430-8e76-89c5-59f7-1cdbbc75cb01)。

在 Unix 系统上，运行以下命令：

`zip ExampleModule.ccm *`

在 Windows 系统上，运行以下命令：

`zip -r ExampleModule.ccm path/to/your/project/bin/Release/net6.0/linux-x64/publish/*`

### 部署模块项目##deploy-a-module-project

要使游戏客户端能够访问您的模块终端，您需要将存档部署到 Cloud Code 服务。

请参阅[编写模块](./write-modules.md)以了解有关模块部署的更多信息。

要使用 UGS CLI 进行部署，必须将存档文件扩展名更改为 .ccm。

#### 配置 UGS CLI##configure-the-ugs-cli

按照以下步骤操作以开始使用 UGS CLI：

1. [安装 UGS CLI](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/install-the-cli/)。
2. 使用以下命令配置您的 Project ID 和环境：
   `ugs config set project-id <your-project-id>`
   `ugs config set environment-name <your-environment-name>`
3. 为服务帐户配置 [Cloud Code](https://services.docs.unity.com/docs/service-account-auth/index.html#cloud-code-editor) 和[环境管理](https://services.docs.unity.com/docs/service-account-auth/index.html#unity-environments-admin)所需的角色。请参阅[接受身份验证](https://services.docs.unity.com/guides/ugs-cli/latest/general/get-started/get-authenticated/)。

#### 部署该模块##deploy-the-module

要部署模块，请运行以下命令：

`ugs deploy <path-to-ccm-file>`

### 从游戏调用模块函数##call-a-module-function-from-your-game

部署模块后，可以从游戏客户端调用模块函数。

#### 先决条件##prerequisites

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

##### 关联项目##link-project

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

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 安装##sdk-installation

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

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

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

##### SDK 设置##sdk-setup

开始使用 Cloud Code SDK：

1. 确保在 [Unity Dashboard](https://cloud.unity.com) 中通过 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。

> **Note:**
>
> **注意**：玩家需要有效的玩家 ID 和访问令牌才能访问 Cloud Code 服务。在使用任何 Cloud Code API 之前，您需要使用 Authentication SDK 对玩家进行身份验证。您可以使用以下代码片段进行匿名身份验证，或者可以查看 [Authentication](./authentication.md) SDK 的文档，了解更多详细信息和其他登录方法。

\###**C#**

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

#### 调用模块函数##call-a-module-function

要从游戏客户端调用模块函数，必须对调用进行身份验证，在调用任何服务的功能之前[初始化 Services Core SDK](/services/getting-started.md#initialize-unity-services-in-your-game-code)，然后调用模块函数。

如需更多有关如何使用游戏客户端来调用模块的信息，请参阅[从 Unity Runtime 运行模块](./run-modules/unity-runtime.md)。

按照以下步骤调用模块函数：

1. 初始化 Services Core SDK。在调用 Cloud Code 之前，通过导入 Services Core 命名空间 (`Unity.Services.Core`) 在游戏代码中初始化 Unity Services，然后调用 `InitializeAsync` 方法。
2. 对调用进行身份验证。每次调用 Cloud Code 都必须经过身份验证，并且玩家必须拥有有效的玩家 ID 和访问令牌才能访问 Cloud Code 服务。请参阅[身份验证](./authentication.md)。建议通过调用 `SignInAnonymouslyAsync` 方法开始进行匿名身份验证。
3. 调用模块函数。使用 Cloud Code SDK 通过 `CallEndpointModuleAsync` 方法调用模块函数。

> **Note:**
>
> **注意**：从 Cloud Code SDK 版本 2.3.0 开始支持 `CallEndpointModuleAsync` 函数。

##### 集成示例##integration-sample

以下示例说明了如何从游戏客户端中的模块 `ExampleModule` 调用模块函数 `SayHello`。

*C#*

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

public class TestModule : 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
            string result = await CloudCodeService.Instance.CallModuleEndpointAsync("ExampleModule", "SayHello", new Dictionary<string, object> {{"name", "World"}});

            Debug.Log(result);
        }
        catch (CloudCodeException exception)
        {
            Debug.LogException(exception);
        }
    }
}
```

> **Important:**
>
> **重要**：首次调用模块函数时，可能需要一些时间才会开始响应。如果出现超时，请再次运行代码，直到在控制台中打印“`Hello, World!`”。
