> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/zh/docs/sample-projects/unity-netcodes/photon-fusion-2-on-edgegap.md).

# Photon Fusion 2

了解如何使用以下内容中的技术在 Edgegap 上托管 Unity 项目 [Fusion 2 小行星示例](https://doc.photonengine.com/fusion/current/game-samples/fusion-asteroids).

{% embed url="<https://youtu.be/bg41HpPmE3E>" %}

## ✔️ 准备工作

开始之前，你需要：

* Unity 6 - [使用 Unity Hub 下载](https://unity.com/releases/unity-6),
* Fusion 2 小行星示例项目（已为 Edgegap 修改） - [从 GitHub 下载](https://github.com/edgegap/netcode-sample-photon-fusion-2).

## ⚡ 部署并连接

### 1. 在 Edgegap 上部署服务器

☑️ 要开始，你需要 [在 Edgegap 创建一个免费账户](https://app.edgegap.com/auth/register). 无需信用卡。

☑️ [为你的应用创建一个新的应用版本](https://app.edgegap.com/application-management/applications/fusion-2-asteroids-sample/versions/create)，选择 Fusion 2 小行星示例。

☑️ 在 Unity 中打开你的新项目。

☑️ 导航到 Tools / Edgegap Hosting，然后到第 6 步。 在 Edgegap 上部署服务器。

☑️ 点击 Deploy to cloud，然后 [打开你新部署的详细信息](https://app.edgegap.com/deployment-management/deployments/list).

☑️ 找到你部署的唯一一次性连接信息：

* **主机 URL** 格式为 `780aa4260e83.pr.edgegap.net` .

✅ 你现在可以继续下一步。

### 2. 从编辑器连接

☑️ 在 Unity 中打开你的新项目。

☑️ 按 ▶️ Play 按钮启动你的游戏客户端。

☑️ 将主机 URL（上一步的连接信息）作为房间名称输入。

☑️ 按 Start Edgegap 按钮连接到你的服务器。

☑️ 连接第二个虚拟玩家，使用 [多人游戏模式](https://docs-multiplayer.unity3d.com/mppm/current/about/) 或 [ParrelSync](https://github.com/VeriorPies/ParrelSync).

🙌 恭喜你在 Edgegap 上完成了第一次部署！

## ✏️ 自定义服务器构建

{% hint style="success" %}
查看 [Unity](/zh/unity.md) 用于 Unity 的 **了解如何构建和自定义服务器**.
{% endhint %}

### 在 Photon 上创建一个应用

{% hint style="info" %}
为了让最初的演示更容易，我们使用了一个由 Edgegap 拥有的免费层 Photon Cloud 账户。
{% endhint %}

☑️ [在 Photon 创建一个免费账户](https://dashboard.photonengine.com/).

☑️ [在 Photon 上创建一个应用程序](https://dashboard.photonengine.com/app/create):

* `多人游戏`,
* `Fusion` Photon SDK，
* `Fusion 2` SDK 版本。

☑️ 找到你的 Application ID，格式为 `85314a99-56fc-4ab3-ba26-50efca09f303` .

☑️ 在 Tools / Fusion / Fusion Hub（Alt + F）下的 Photon Settings 中输入你的 ID。

### 将 Fusion 2 项目与 Edgegap 集成

{% hint style="success" %}
查看 `EdgegapServerManager.cs`  用于将 Fusion 2 与 Edgegap 集成的示例脚本。
{% endhint %}

{% hint style="warning" %}
你的 `NetworkProjectConfig`  **必须使用 `Peer Mode = Single` （专用服务器）**，而不是 `Multiple` （客户端主机）！
{% endhint %}

游戏客户端将通过 [Photon Fusion 2 ](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session)[会话（房间） ](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session)[功能](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session).

当调用时，你的游戏服务器需要将其 IP 地址和外部端口与会话名称一起注册， `_runnerInstance.StartGame(StartGameArgs args)`:

* 使用 `GameMode.Server`  以确保你的连接不会经过 Photon Cloud 中继（会增加延迟），
* 使用 `NetAddress.CreateFromIpPort` 来自 Fusion 的方法，
* 提供服务器的 IP 地址：\
  `Environment.GetEnvironmentVariable("ARBITRIUM_PUBLIC_IP")`
* 提供服务器的外部端口：\
  `Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_EXTERNAL")`
  * 如果你使用我们的，这就是默认的端口映射名称 [Unity 插件来打包你的服务器](/zh/unity.md).

将 Edgegap 部署主机 URL 作为会话名称使用：

* 在游戏服务器中，通过以下方式获取它\
  `$"{Environment.GetEnvironmentVariable("ARBITRIUM_REQUEST_ID")}.pr.edgegap.net"`
* 在测试游戏客户端时，从仪表板 - 部署详情页面 / Host URL 获取它
  * 从我们的 [快速开始托管插件](/zh/unity/developer-tools.md#dedicated-servers-quickstart-plugin),
* 在正式运行的游戏客户端中，从以下位置获取它 [匹配 / 票据分配 / fqdn](/zh/learn/pi-pei/matchmaker-in-depth.md#player-api):
  * 另见 [入门使用 Matchmaking](/zh/learn/pi-pei.md).

{% tabs %}
{% tab title="客户端集成" %}
{% code title="EdgegapClientManager.cs" %}

```csharp
// 获取 fusion 2 网络运行器
_runnerInstance = FindFirstObjectByType<NetworkRunner>();
_runnerInstance.ProvideInput = true;

// 从 Edgegap Matchmaker Assignment 或 Fusion 2 Sessions API 获取此值
string sessionName = "<requestId.pr.edgegap.net>";

// 查找 fusion 2 会话（使用会话名称）
var result = await _runnerInstance.StartGame(
    new StartGameArgs() {
        GameMode = GameMode.Client,
        SessionName = sessionName,
        ObjectProvider = _runnerInstance.GetComponent<NetworkObjectPoolDefault>(),
    }
);

// fusion 现在将根据会话名称获取服务器 IP 和端口并连接
```

{% endcode %}
{% endtab %}

{% tab title="服务器集成" %}
{% code title="EdgegapServerManager.cs" %}

```csharp
// 读取 Edgegap 注入的环境变量
string requestId = Environment.GetEnvironmentVariable("ARBITRIUM_REQUEST_ID");
string listenPortStr = Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_INTERNAL");
string connectIP = Environment.GetEnvironmentVariable("ARBITRIUM_PUBLIC_IP");
string connectPort = Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_EXTERNAL");

// 获取 fusion 2 网络运行器
_runnerInstance = FindFirstObjectByType<NetworkRunner>();
_runnerInstance.ProvideInput = true;

// 将监听端口解析为 StartGame 预期的 ushort
ushort.TryParse(listenPortStr, out ushort listenPort);

// 为客户端注册 fusion 2 会话，以便之后找到它（使用会话名称）
var result = await _runnerInstance.StartGame(
    new StartGameArgs() {
        GameMode = GameMode.Server,
        SessionName = $"{requestId}.pr.edgegap.net",
        ObjectProvider = _runnerInstance.GetComponent<NetworkObjectPoolDefault>(),
        Address = NetAddress.Any(listenPort),
        CustomPublicAddress = NetAddress.CreateFromIpPort(connectIP, connectPort),
    }
);

// 加载初始场景
if (result.Ok && _runnerInstance.IsServer) {
    await _runnerInstance.LoadScene(sceneName);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 故障排除

<details>

<summary><code>游戏不存在（32758）</code></summary>

* Photon 房间要求玩家连接到部署所在的 Photon Cloud 区域。 从仪表板部署时会使用随机化的玩家 IP。
* 你可能需要在地图上找到部署的位置，并在 Assets / Photon / Fusion / Resources / PhotonAppSettings.asset 中将你的游戏客户端配置为匹配的 [Photon Cloud 区域](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/regions#photon-cloud-for-gaming).
* Edgegap [尽可能靠近玩家进行部署](https://docs.edgegap.com/zh/docs/sample-projects/unity-netcodes/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-server-score-strategy-best-practice) 当使用我们的 [插件](/zh/unity/developer-tools.md) 或 [API](/zh/docs/api/zhuan-yong-fu-wu-qi.md) 因此在生产环境中，不需要设置 Photon Cloud 区域。

</details>
