Unityの公式チュートリアルに掲載されているマルチプレイヤーネットワーキングを勉強を進めている様子をお送りします。前回の記事はこちらからどうぞ
プレイヤーの動きをネットワーク化する
公式サイトのチュートリアルページ プレイヤーの動きをネットワーク化する
今回ステップはプレイヤーオブジェクトを制御するスクリプトを修正し、サーバーとクライアントでゲームオブジェクトとスクリプトがどのように処理されているかについて解説されています。
- スクリプト PlayerController を開く
- 名前空間 UnityEngine.Networking を追加
- MonoBehaviour を NetworkBehaviour に変更
- 関数 Update に isLocalPlayer のチェック処理を追加
- スクリプトを保存
- Project ウィンドウでプレハブ Player を選択し Network > NetworkTransform コンポーネントを追加
- プロジェクトを保存
スクリプトコードにコメントを付けて内容を確認しました。今回のスクリプトのポイントは名前空間”using UnityEngine.Networking”の追加とクラス名の後にある”NetworkBehaviour”ですね。
using System.Collections; using System.Collections.Generic; using UnityEngine; // ネットワークコンポーネント関数を使用するため名前空間の追加 using UnityEngine.Networking; public class PlayerController : NetworkBehaviour { // ゲーム実行中の繰り返し処理 void Update() { // プレイヤーが自分自身でない場合 if (!isLocalPlayer) { // 以降の処理を中断 return; } // 左右方向の入力値を変数 x に代入 var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f; // 前後方向 入力値を変数 z に代入 var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f; // オブジェクトの方向転換の制御 // (変数 xの値をオブジェクトのY軸回転に代入) transform.Rotate(0, x, 0); // オブジェクトの前進、後退の制御 // (変数 z の値をオブジェクトのZ座標に代入) transform.Translate(0, 0, z); } }
プレハブ Player の[Inspector]ウィンドウはコンポーネント NetworkTransform を追加してこのようになりました。
今回のステップではネットワーキング処理について次のように解説されています。
サーバーが 1 つにクライアントが 2 つある場合、つまり2人のプレイヤーでゲームをプレイする場合、サーバーとクライアントで同時処理されるプレイヤーゲームオブジェクトの数は 6になる。
詳しいことはこれから勉強を進めていきますが、このあたりが リアルタイムネットワークゲーム開発の難しさなのではないか?と感じました。
マルチプレイヤーの動きをテストする
公式サイトのチュートリアルページ マルチプレイヤーの動きをテストする
今回のステップはネットワークマルチプレイヤーネットワーキングの動作確認です。
- Build Settingsウィンドウを開き、スタンドアロンのアプリケーションとして[Build and Run]をクリック
- ビルドファイルが完成するとゲームが実行される
- ゲーム内 UI から [LAN Host ] ボタンをクリックしてホストとして開始
- エディタ側で Play モードを開始
- ゲーム内 UI から [LAN Client] ボタンをクリックしてクライアントとしてホストに接続
- WASD キーまたは方向キーを押してクライアントのプレイヤーオブジェクトの動きをテスト
- スタンドアロンプレイヤーに切り替え、ホストのプレイヤーオブジェクトの動きをテスト
- スタンドアロンプレイヤーを終了、エディタ側のPlay モードを終了
ゲーム実行中のエディタ側(クライアント)の状態がこちら。
そしてスタンドアロンプレイヤー側(ホスト)の状態がこちら。ちゃんと同期されています。
ただし、このステップの解説にもありますが、自分が操作するプレイヤーオブジェクトの動きがリモート側(クライアントで操作している場合はホスト)でカクカクしていてスムーズに移動できていません。
解説によると…
ネットワークを利用したマルチプレイヤーゲームにおいては、同期を完璧に行うことはできません。
ということで、ゲームは完全に同期されているように印象を与えるためのテクニックを別のチュートリアルで紹介すると書いてあるので、とりあえずこのままにしておきましょう。
ローカルプレイヤーの特定
公式サイトのチュートリアルページ ローカルプレイヤーの特定
今回はプレイヤーが自分のプレイヤーオブジェクトを識別できるようにするために、ホスト側とクライアント側でプレイヤーのマテリアルを変更する処理を追加します。
- スクリプト PlayerController を開く
- OnStartLocalPlayer 関数を追加してプレイヤーオブジェクトの色を変更する
- スクリプトを保存
- Build Settingsウィンドウを開き、スタンドアロンのアプリケーションとして[Build and Run]をクリック
- ビルドファイルが完成するとゲームが実行される
- ゲーム内 UI から [LAN Host ] ボタンをクリックしてホストとして開始
- プレイヤーオブジェクトを操作テスト
- エディタ側でPlay モードを開始
- ゲーム内 UI から [LAN Client] ボタンをクリックしてクライアントとしてホストに接続
- プレイヤーオブジェクトを操作テスト
- スタンドアロンプレイヤーを終了、エディタ側のPlay モードを終了
スクリプトコードにコメントを付けて内容を確認しました。
using System.Collections; using System.Collections.Generic; using UnityEngine; // ネットワークコンポーネント関数を使用するため名前空間の追加 using UnityEngine.Networking; public class PlayerController : NetworkBehaviour { // ゲーム実行中の繰り返し処理 void Update() { // プレイヤーが自分自身でない場合 if (!isLocalPlayer) { // 以降の処理を中断 return; } // 左右方向の入力値を変数 x に代入 var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f; // 前後方向 入力値を変数 z に代入 var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f; // オブジェクトの方向転換の制御 // (変数 xの値をオブジェクトのY軸回転に代入) transform.Rotate(0, x, 0); // オブジェクトの前進、後退の制御 // (変数 z の値をオブジェクトのZ座標に代入) transform.Translate(0, 0, z); } // ローカルプレイヤー時のゲームのスタート処理 public override void OnStartLocalPlayer() { // MeshRenderer コンポーネントを取得してマテリアルカラーを blue に設定 GetComponent<MeshRenderer>().material.color = Color.blue; } }
今回のステップの手順を終えた状態のエディタ側(クライアント)の再生画面はこちら。右側のオブジェクトが自分のプレイヤーオブジェクト。色が青色に変化しています。
そしてスタンドアロンプレイヤー(ホスト)を実行した画面がこちら。左側のオブジェクトが自分のプレイヤーオブジェクト。こちらもちゃんと色が青色に変化しています。