Photon Fusion for Unityを使った自分のプロダクトをサーバーモードに対応する～基礎編

# *はじめ*に

Photon FusionはドイツのExit Games社が開発し、GMOグローバルサイン・ホールディングス株式会社が日本展開を行っているオンラインゲーム開発向けネットワークエンジンです。

サーバーへのデプロイを前提にしたゲームを作りたい、例えば多人数対戦ゲームでセキュリティや安定性を高めたい、MMORPGのような常時稼働させたい、といった場合があるかと思います。

前回の記事ではそういったゲームを作成する準備段階として、サンプルプロジェクトを動かす手順を解説しました。

https://qiita.com/nimushiki/items/39f1648b81a8cfff65e2

本記事ではサンプルプログラムを参考に、自身のプロジェクトに実装すべき機能について解説します。

### 前提記事

Photon Fusionの基本的な解説は別記事で行っています。詳しく知りたい方は以下のリンクからご参照下さい。

[Photon Fusion for Unityの導入手順とPUN2との機能比較](https://qiita.com/nimushiki/items/d6fe4f0cbe0437677fa8)

関連記事

[https://qiita.com/tags/photonfusion](https://qiita.com/tags/photonfusion)

### 動作確認環境

Windows 10 Home 21H2

Unity 2021.3.15f1

Fusion Dedicated Server 1.1.2 Build 2

# サーバーに必要な機能

サンプルにはサーバーモードをUGS上で動かすのに必要な機能が多く実装されています。その中でも重要な要素を紹介します。

多くのスクリプトはそのままコピーするだけで機能します。

### 起動パラメータを取得する処理　CommandLineUtils

build configurationのlaunch parametersを取得するためのユーティリティです。主にDedicatedServerConfigから呼び出して使います。

### 起動パラメータを変換、保存する処理　DedicatedServerConfig

CommandLineUtilsを使って取得した文字列パラメータを、使いやすいように型変換をして保存します。

### サーバー機能　ServerManager

サーバーモードの場合にサーバー向けの初期化、接続処理を行います。

初期化処理でクライアントモードの場合に専用のシーンへ遷移させていますが、別クラスに分離したほうが後々管理しやすいかもしれません。

### ログを出力する機能　ServerEventsInfo

Photon Fusionで取得できるイベント（プレイヤーの接続・切断やクライアントの終了など）をログに出力します。

サーバー、クライアントどちらの処理も同クラスに含まれているため、こちらも別クラスに分離したほうが分かりやすいかもしれません。

### クライアントの入退室管理　GameManager

クライアントがjoin・leftした時にプレイヤーオブジェクトをスポーン・デスポーンさせる処理が書かれています。

クライアントの接続数が０になった時に`runner.Shutdown();`でシャットダウンを行っていますが、常時起動型を実現したい場合は不要な処理となります。

### クライアントがログインする処理の管理　ClientManager

これはサーバーではなくクライアント側でのみ使用します。

サーバーやロビーに接続する処理と、それを呼び出すUIを表示する処理です。各プロジェクトに必要な部分だけ参考にすると良いでしょう。

# 開発を効率化するTips

## UGSでビルドを更新する時の最短手順

前回の記事ではビルドを初回設定する手順を紹介しました。ここではビルドを更新していく2回目以降の手順を紹介します。

1. サーバーを全てstopする
![サーバーを全てstop](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/9f0f5c00-08cb-7298-6229-adf70a624d9a.png)

2. Fleetをオフラインにして（少し待ち）Deleteする
![FleetをオフラインにしてDeleteする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/9c49dfe9-aa4d-373a-a6d3-8d95754f9430.png)

3. 新しいファイルをアップロードする
新しいBuildを作成する必要はなく、既存のものを更新すれば問題ありません。
![新しいビルドをアップロードする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/814e038e-69ca-31c8-9c15-321430d65b4d.png)

4. Fleetを作り直し、Test Allocationsを行い完了まで待つ

実際にビルドが置き換わったかをUGS上で確認するのは難しいため、例えば　`Debug.Log("Build GUID : " + UnityEngine.Application.buildGUID);`　というようにビルド固有の情報をログに出力すると良いでしょう。

## UGSでビルドを更新せずにローカルマシンで実行する

前述した手順ではUGSの処理を待つ時間があるため、試行回数を多くしたい場合には向きません。しかし細かい調整や検証のための変更をする場合など、可能な限り早く試したい時があると思います。

そういった場合はLinux版をビルドするのではなく、Windows版をビルドしてサーバーモードで起動するのが良いでしょう。

クライアント同様のWindows版でビルドをした後、Power shellを使い、build configurationで使用したlaunch parameters（`-batchmode -nographics -logFile $$log_dir$$/Engine.log`）をパラメータに追加して起動すればサーバーモードで起動します。

![Power shellでサーバーモードを起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2576800/4602eab5-a8f4-0ddd-99a6-80b775bbd89c.png)

ウィンドウは表示されませんが、タスクマネージャーから動作していることを確認できます。

同様の理由で、終了させる場合もタスクマネージャー経由である必要がありやや手間がかかります。この場合はGameManagerクラスに実装されている、クライアント接続数が0になった時にシャットダウンさせる機能を使うと手間が省けます。

## Screen position out of view frustumというエラー

`Screen position out of view frustum (screen pos 0.000000, 0.000000, 1000.000000) (Camera rect 0 0 1280 720)`　といったエラーが出ることがあります。

これは、シーンにあるcameraの設定で不正な値がある場合（clipping planesがNear<0.3やFar<0.11といった場合）に起こるようです。クライアントモードでは正常に動作している場合でも起こり得るようです。

しかしそもそもカメラはサーバーモードでは不要なため、カメラを生成しない、無効にする、探して削除する、といった対処をするとよいでしょう。

# さいごに

前回の準備編でUGSへのデプロイ手順、今回の基礎編で最低限実装するべき機能について紹介しました。

これでようやくゲームの開発を始める準備が整ったため、次回以降の記事ではゲームを実装する時に考慮すべき事柄について紹介する予定です。