Photonを使ったリアルタイムのオンライン対応はやりましたが、UnityNetwork(UNet)でもやり方が少し変わりますがオンライン対応が出来ます。
UNetの機能は古くなり現在はUnityで新しいマルチプレイヤーシステムが開発されている途中ですので、このカテゴリの記事はあくまで参考程度にお願いします(2020/11/22)。
新しいマルチプレイヤーシステムに関してはUnity Blogを参照してみてください。
そこで今回からいくつかの記事に分けてシンプルなオフラインゲームをオンラインに対応させたいと思います。
一応は、これからオンライン対応したいという方に向けての記事という風にしてありますが、自分の備忘録としての意味合いが強いです。
今回はオンライン対応する前にUnityNetworkでのオンラインの概要を書いておきます。
正確で詳しい内容については参考サイトに記載しているUnityマニュアルのオンライン対応のページを順に追っていくと良いと思います。
この記事ではわたくし個人の思っている事と解釈してください。(^_^;)
サーバーとホストとクライアント
オンラインではサーバー(提供する側)とクライアント(提供される側)があり、クライアントがサーバーに接続してオンラインに接続します。
データを共有する場合はサーバーを介してデータをクライアントに送信するという形になります。
UnityNetworkではこのサーバーを兼任するクライアントがおり、それをホストと呼びます。
ホストのクライアントをローカルクライアント、ホストに接続しているクライアントはリモートクライアントと呼びます。
自分のキャラクターと他人のキャラクター
クライアントがサーバーに接続すると自身のキャラクターをオンライン上に登場させます。
パソコンで起動するスタンドアロン形式の場合は自身のゲーム上に自分のキャラクターを登場させますが、すでに他のキャラクターがオンライン上に存在した場合はそのキャラクターも自身のアプリケーション上に表示されます。
キャラクターはプレハブ化したキャラクターをインスタンス化し登場させているので、CharacterControllerやキャラクターを動かすスクリプト(ここではUCharaとします)も他人のキャラクターに設定されています。
つまり他人のキャラを自身のアプリケーション上でインスタンス化しているだけなので、キーボード等で操作するとUCharaスクリプトを持っている他人のキャラクターも自身のキャラクターと同じように動きます。
その為、自身のキャラか他人のキャラかを判別し、移動処理等を行わないようにしなければいけません。
データの同期
オンラインにキャラクターを登場させた場合、自分のアプリケーション上でキャラクターを移動させたら、他人のアプリケーション上でも自身のキャラクターが移動しなければいけません。
その為、キャラクターの位置やアニメーション等を同期させます。
RPC(リモートプロシージャコール)
RPCはネットワークを通じてサーバーやクライアント上で何らかの処理を実行する方法です。
ここら辺で結構混乱しますね・・・(^_^;)
というわけでメソッドに取り付けるアトリビュートを書き遺しておきます。
クライアントから呼び出しサーバー上で実行
まずはクライアントから呼び出しサーバ上で実行するメソッドです。
メソッド定義の前に[Command]アトリビュートを取り付け、メソッド名の前にCmdというプリフィックスを付けます。
1 2 3 4 5 6 7 8 9 10 11 12 | void Update() { // マウスの左ボタンを押したらサーバー上でCmdDoを実行 if (Input.GetButtonDown ("Fire1")) { CmdDo (); } } [Command] void CmdDo() { Debug.Log ("サーバー上で実行"); } |
↑の例ではクライアント上のスクリプトでマウスの左ボタンを押したら、サーバー上でCmdDoメソッドを実行します。
サーバからクライアントメソッドを実行
Commandの逆でサーバからクライアントのメソッドを実行する場合は、
メソッドの定義の前に[ClientRpc]アトリビュートを取り付け、メソッド名の前にRpcというプリフィックスを付けます。
1 2 3 4 5 6 | [ClientRpc] void RpcDo() { Debug.Log ("クライアントで実行"); } |
↑の例ではサーバ上で実行されているメソッドからRpcDoメソッドを呼び出すと実行されます。
わたくしの場合ここら辺が混乱しますね、サーバーで実行すべき事、クライアントで実行すべき事の分け方とか。(^_^;)
ここら辺はUnityマニュアルを参照してください。
フィールドを同期させる
Photonのオンライン対応の記事ではOnPhotonSerializeViewというメソッドでデータの取得と書き換えをしていました。
UnityNetworkでもOnSerializeとOnDeserializeを使うと同じような感じで出来ますが、[SyncVar]アトリビュートをフィールドに取り付けるとそのフィールドを同期する事が出来ます。
1 2 3 4 | [SyncVar] public int hp; |
[SyncVar]アトリビュートを付けたフィールドはサーバーからクライアントに同期されます。
先ほどの例でhpのフィールド値が更新された場合にキャラクターのHPを表示しているテキストUIの値を書き変えたい場合はフックを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 | // HP表示用テキストUI public Text hpText; // 体力 [SyncVar (hook = "OnChangeHP")] public int hp; // SyncVar指定したhpに変更があったら呼び出される void OnChangeHP(int hp) { hpText.text = hp.ToString (); } |
フックを使用すると値が書き変わった時に指定したメソッドが呼び出されるので、UpdateメソッドでHPを監視して変更があった時だけ更新というスクリプトを組まなくて済みますね。
終わりに
オンライン対応はやはり混乱しますね。(^_^;)
サーバーもクライアントも同じスクリプトで動作していますから、サーバーで実行するのか?クライアントで実行するのか?
自分のキャラクターなのか?他人のキャラクターなのか?
スマートに理解出来たらなと思うんですが、もっとスクリプトを組んで理解していくしかなさそうです。
と言う事で次回からUnityNetworkでのオンライン対応をしていきます。