# 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](/unity.md) 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](/unity.md).

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](/unity/developer-tools.md#dedicated-servers-quickstart-plugin),
* when live in game client, get it from [matchmaking / ticket assignment / fqdn](/learn/matchmaking/matchmaker-in-depth.md#player-api):
  * see also [getting started with Matchmaking](/learn/matchmaking.md).

{% 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/docs/sample-projects/unity-netcodes/pages/0UXQAhtFuL0FkdoUmYTh#id-1.-server-score-strategy-best-practice) when using our [plugins](/unity/developer-tools.md) or [API](/docs/api/dedicated-servers.md) so in production, setting Photon Cloud region is not required.

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/docs/sample-projects/unity-netcodes/photon-fusion-2-on-edgegap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
