【unity】PhotonFusion備忘録

## 経緯
ネットワークまったくわからないけれどu1wでオンラインゲーム作るか！
と意気込んでPhotonFusionを使わせていただいたところ、
一人で屍山血河を作り上げるほど難航したため、来世の自分のための基本的な機能の備忘録です。


## 前提
内容は公式リファレンスなどに掲載されているものを細かく書き直したものです。
photonFusionでわからないことがあったら公式とo8queさんのzennの記事とニム式さんのスライドを100回読み直したほうが良いです。

※記述についてはHost/Client Modeの想定です。

公式

https://doc.photonengine.com/ja-jp/fusion/current/tutorials/host-mode-basics/overview

(023/05/15　↑ いま見たらUIが変わってた！！！！マ？？？？？)

https://doc-api.photonengine.com/en/fusion/current/index.html



o8queさんのzenn記事。本当の本当に大助かりした記事。感謝

https://zenn.dev/o8que/articles/afe59cfb76404b



ニム式さんのqiita。スライドを読むとphotonFusionの理解度が上がるから必聴。

https://qiita.com/nimushiki



## NetworkObject
ネットワーク上で共有するオブジェクトに付与するコンポーネント。

### よく使う（継承）クラス
ネットワークの動作に関するクラスは２つある。
用途に応じてどちらかのクラスを継承する（callback系は別のクラスがあります）

- **SimulationBehaviour**
    - オブジェクトの動作をネットワーク上で共有する場合に継承する。
- **NetworkBehaviour**
    - **[networked]** をつけた変数などの状態を維持、または追跡するときなどにしようするクラス。ネットワークに関連するクラスはほぼ継承必須。


### 権限系
NetworkObjectには権限が２種類ある。
操作入力を受け付ける**InputAuthority** と
入力結果を反映できる**StateAuthority**
 
それぞれの権限は１ユーザーのみ持つことが出来る。
イメージは以下。
例）キャラクターアバター
    inputAuth ...Player1
    StateAuth ...Player2(HOST)
    Player1のwasd操作をPlayer2に送って処理することで、player3の画面に描画される


オブジェクトの所有権限の確認は
bool Object.HasStateAuthority()
関数を使用する。

※Object は、NetworkBehaviorを継承したクラスなどでは、同じオブジェクトにアタッチされている NetworkObjectコンポーネントを指す

他、権限系で使用する頻度が高そうな関数

- **DestroyWhenStateAuthorityLeaves**
    - オブジェクトの認証権限を持っているユーザーがゲームから離れた場合に一緒にオブジェクトを消すかどうかのflg
- **AllowStateAuthorityOverride**
    - 状態権限を他のユーザーが持っている場合に、ゲーム中に別のユーザーに状態権限を移行できるかどうかのflg
    - spawn前に設定が必要（基本は有効）
- **RequestStateAuthority**
    - 状態権限を取得したいとき、クライアントから呼ぶリクエスト
    - 状態権限が喪失しているオブジェクトに対してのみ有効　
    または（かつ、かもしれない）、
    AllowStateAuthorityOverrideがtrue



## 切断

### 切断するときの処理

プレイヤーがセッションを退出するときの関数は
**Networkrunner.shutdown()**
だと思います。おそらく。。。

※リファレンスが少ないため正解か不明。公式が想定する正しい方法などを知りたい場合はサンプルプロジェクトを読み解いて私に教えてくださいお願いします何でもしますから！

誰かがゲームから退出した場合、全プレイヤーの
INetworkRunnerCallbacksを継承した OnPlayerLefted() が呼ばれます。

ホストが切断した場合は
- ゲームの解散
- ホストがrunnner.spawnしたオブジェクトが全て消去される

となります。

ホストが切断した後もゲームを続ける場合は、ホストマイグレーションという機能を使用するそうです（未使用のため機能不明。公式に説明ページあり）

（ホストマイグレーションを使用しない場合）
OnDisconnectedFromServer() を使用するか、OnPlayerLefted()でホストが退出する場合を検知するなど、sessionが強制的に解散されたときは必ず安全なsceneに遷移するような設計にしてください（一敗）


## RPC

他のプレイヤーに関数の発動を命じる素敵な機能（意訳）。
オンラインゲーム全くわからんマンなので、この機能が一番動かしやすいように感じました。

公式曰く、送られない可能性も想定してね、だそうですが、私はRPCを主軸にターンベースのゲームを作りました。**たぶんやめたほうがいいです**
~~TCPで送信できるrelyableみたいな項目あるらしいけれど私にはよくわかりませんでした~~

### 注意点１　引数
引数の一覧が日本語のページにはないため、原文を読みにいきましょう

引数にはNetworkCollectionがありません。
そのため、配列やリスト、辞書などを渡すときはNetworkStructを作って、その中にNetworkArrayなどを宣言する必要があります。


string は NetworkString にキャストする必要があります
◯　NetworkString = String
✗　string = NetworkSting
◯　string = NetworkSting.ToString()

### 注意点２　関数名
RPCの関数名には必ず「RPC」「rpc」「Rpc」など、**とにかくRPCを付ける必要があります**（必須）

RPC関連で意味不明なエラーが出た場合、基本的に引数に渡せない変数が入っているか、RPCが関数名に含まれていないかのどちらかが多かったです。


## 未だにわからないこと

### scene
まーじで使い方がよくわからないです。
NetworkRunnerとSceneの結びつきがわからないので、半ば理解を諦めている状態です。
~~わからなくてもオブジェクトの生成と消去をゴリ押しで行えばなんとかなります~~

## PhotonFusionを使用した感想
ネットワーク全く知らない人でもオンラインプレイを１週間足らずで実装できた。すごい！嬉しい！
サーバー系のことを何も考えずに、プレイヤー間で受け渡しが必要なデータにだけ頭のリソースを割けばいいので、（ミニゲームくらいなら）設計に拘らずに実装できる点がとてもよかった。


## 要望
リファレンスが後百倍わかりやすいと嬉しいです。
日本語のページは（誤記はともかく）前verと比べて情報が抜けていることが多いため、困ったときに原文ページを読みに行く回数が多かった。
英語の原文ページはgoogle翻訳にかけると語順がバラバラになってリアルでカイジの「ぐにゃあ～」みたいな表情になった。

ロビー機能はともかくとして、ゲーム切断部分の詳細な方法はどこかに書いてあって欲しかった。

現状、サンプルを紐解くことが一番理解度を高める方法っぽいので、誰かサンプルを紐解く動画とか出して欲しい。私だけで１００回は再生します！ｗ