# Photon Fusion 2

Explore how to host Unity projects on Edgegap using techniques from the [Fusion 2 Asteroids Sample](https://doc.photonengine.com/fusion/current/game-samples/fusion-asteroids).

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

## ✔️ Preparation

Before we start, you will need:

* Unity 6 - [download using Unity Hub](https://unity.com/releases/unity-6),
* Fusion 2 Asteroids Sample project (modified for Edgegap) - [download from GitHub](https://github.com/edgegap/netcode-sample-photon-fusion-2).

## ⚡ Deploy and Connect

### 1. Deploy a Server on Edgegap

☑️ To get started, you'll need to [create a free account with Edgegap](https://app.edgegap.com/auth/register). No credit card required.

☑️ [Create a new app version for your application](https://app.edgegap.com/application-management/applications/fusion-2-asteroids-sample/versions/create), choose Fusion 2 Asteroids Sample.

☑️ Open your new project in Unity.

☑️ Navigate to Tools / Edgegap Hosting, then to step 6. Deploy a Server on Edgegap.

☑️ Press Deploy to cloud and [open your new deployment's details](https://app.edgegap.com/deployment-management/deployments/list).

☑️ Find your deployment's unique, one-time connection details:

* **Host URL** in format `780aa4260e83.pr.edgegap.net` .

✅ You may now proceed to the next step.

### 2. Connect from Editor

☑️ Open your new project in Unity.

☑️ Press the ▶️ Play button to start your game client.

☑️ Input Host URL (connection details from previous step) as room name.

☑️ Press Start Edgegap button to connect to your server.

☑️ Connect a second virtual Player with [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/mppm/current/about/) or [ParrelSync](https://github.com/VeriorPies/ParrelSync).

🙌 Congratulations on your first Deployment on Edgegap!

## ✏️ Customize Server Build

{% hint style="success" %}
See [unity](https://docs.edgegap.com/unity "mention") for Unity to **learn how to build and customize servers**.
{% endhint %}

### Create an App on Photon

{% hint style="info" %}
To make the initial demo easy, we used a free tier Photon Cloud account owned by Edgegap.
{% endhint %}

☑️ [Create a free account with Photon](https://dashboard.photonengine.com/).

☑️ [Create an Application on Photon](https://dashboard.photonengine.com/app/create):

* `Multiplayer Game`,
* `Fusion` Photon SDK,
* `Fusion 2` SDK version.

☑️ Find your Application ID in format `85314a99-56fc-4ab3-ba26-50efca09f303` .

☑️ Input your ID in Photon Settings under Tools / Fusion / Fusion Hub (Alt + F).

### Integrate Fusion 2 Project with Edgegap

{% hint style="success" %}
See `EdgegapServerManager.cs`  script for an example integration of Fusion 2 with Edgegap.
{% endhint %}

{% hint style="warning" %}
Your `NetworkProjectConfig`  **must use `Peer Mode = Single` (Ded. Server)**, not `Multiple` (Client-Host)!
{% endhint %}

Game clients will connect to game servers through [Photon Fusion 2 ](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session)[Session (room) ](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session)[feature](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/matchmaking#creating-and-joining-a-game-session).

Your game server needs to register it's IP address and external port with the Session name, when calling `_runnerInstance.StartGame(StartGameArgs args)`:

* use `GameMode.Server`  to ensure your connection isn't relayed over Photon Cloud (adds latency),
* use `NetAddress.CreateFromIpPort` method from Fusion,
* provide server's IP address:\
  `Environment.GetEnvironmentVariable("ARBITRIUM_PUBLIC_IP")`
* provide server's external port:\
  `Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_EXTERNAL")`
  * this is the default port mapping name if you use our [Unity plugin to package your server](https://docs.edgegap.com/unity).

Use Edgegap Deployment Host URL as a Session name:

* in game server, get it with\
  `$"{Environment.GetEnvironmentVariable("ARBITRIUM_REQUEST_ID")}.pr.edgegap.net"`
* when testing game client, get it from dashboard - deployment details page / Host URL
  * create deployments for testing from our [quickstart hosting plugin](https://docs.edgegap.com/unity/developer-tools#dedicated-servers-quickstart-plugin),
* when live in game client, get it from [matchmaking / ticket assignment / fqdn](https://docs.edgegap.com/learn/matchmaking/matchmaker-in-depth#player-api):
  * see also [getting started with Matchmaking](https://docs.edgegap.com/learn/matchmaking).

{% tabs %}
{% tab title="Client Integration" %}
{% code title="EdgegapClientManager.cs" %}

```csharp
// get fusion 2 network runner
_runnerInstance = FindFirstObjectByType<NetworkRunner>();
_runnerInstance.ProvideInput = true;

// get this value from Edgegap Matchmaker Assignment or Fusion 2 Sessions API
string sessionName = "<requestId.pr.edgegap.net>";

// find fusion 2 session (using session name)
var result = await _runnerInstance.StartGame(
    new StartGameArgs() {
        GameMode = GameMode.Client,
        SessionName = sessionName,
        ObjectProvider = _runnerInstance.GetComponent<NetworkObjectPoolDefault>(),
    }
);

// fusion will now fetch server IP and port based on session name and connect
```

{% endcode %}
{% endtab %}

{% tab title="Server Integration" %}
{% code title="EdgegapServerManager.cs" %}

```csharp
// read edgegap injected environment variables
string requestId = Environment.GetEnvironmentVariable("ARBITRIUM_REQUEST_ID");
string listenPort = Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_INTERNAL");
string connectIP = Environment.GetEnvironmentVariable("ARBITRIUM_PUBLIC_IP");
string connectPort = Environment.GetEnvironmentVariable("ARBITRIUM_PORT_GAMEPORT_EXTERNAL");

// get fusion 2 network runner
_runnerInstance = FindFirstObjectByType<NetworkRunner>();
_runnerInstance.ProvideInput = true;

// register fusion 2 session for clients to find it later (using session name)
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),
    }
);

// load initial scene
if (result.Ok && _runnerInstance.IsServer) {
    await _runnerInstance.LoadScene(sceneName);
}
```

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

### Troubleshooting

<details>

<summary><code>Game Does Not Exist (32758)</code></summary>

* Photon rooms require the player to be connecting to the Photon Cloud region where the deployment is located. Deploying from dashboard uses a randomized player IP.
* You may need to find the deployment's location on the map, and configure your game client in Assets / Photon / Fusion / Resources / PhotonAppSettings.asset with the matching [Photon Cloud region](https://doc.photonengine.com/fusion/current/manual/connection-and-matchmaking/regions#photon-cloud-for-gaming).
* Edgegap [deploys as close to the player as possible](https://docs.edgegap.com/learn/orchestration/deployments#id-1.-server-score-strategy-best-practice) when using our [plugins](https://docs.edgegap.com/unity/developer-tools) or [API](https://docs.edgegap.com/docs/api/dedicated-servers) so in production, setting Photon Cloud region is not required.

</details>
