プレイヤーキャラクタの出現処理と単体テスト
目次
概要
プレイヤーキャラクタを登場させる
ここまでのNetworkControlの内容
単独で動作テストをする
エラーの原因を特定し、修正を加える
ここまでのThirdPersonCameraの内容
起動時のカメラの位置も変更する
再度、単独で動作テストをする
プレイヤーキャラクタを出現させ、単体での動作確認を行なう
ネットワークの接続・切断、およびルームへの入退室が組み込み終わりました。
では改めてプレイヤーキャラクタを登場させてみましょう。
注記:このページの途中から、実行ボタンを押して動作確認できます。
長らく作業が続きましたが、お待たせしました。
「このページの途中から」ですが、ようやくプレイすることができます。
プレイヤーキャラクタを登場させる▲
プレイヤーキャラクタを保持する変数を用意する
NetworkControl の 10 行目に、以下の変数を宣言します。
/** プレイヤーキャラクタ. */
private GameObject playerObject = null;
上記のように、プレハブから生成されたプレイヤーキャラクタの GameObject を保持する変数を用意します。
プレイヤーキャラクタを「全てのクライアントでほぼ同時に」出現させる
NetworkControl の 22 行目から、以下のコードを記述します。
// Update is called once per frame
void Update()
{
// MUNサーバに接続しており、かつルームに入室している場合
if (MonobitNetwork.isConnect && MonobitNetwork.inRoom)
{
// プレイヤーキャラクタが未登場の場合に登場させる
if (playerObject == null)
{
playerObject = MonobitNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity, 0);
}
}
}
MUNサーバに接続している状態で、かつルームに入室しており、プレイヤーキャラクタが未登場の場合(playerObject にまだ値が設定されていない場合)に、
MonobitNetwork.Instantiate() メソッドを使い、ネットワーク越しに全てのクライアントに対し、自身のプレイヤーキャラクタを登場させます。
MonobitNetwork.Instantiate() メソッドは以下のパラメータを持ちます。
第一引数
("Player")
GameObjectとして生成される元データの、プレハブの名前を指定します。
注意すべき点として、読み込み対象となるprefabファイルが、Resources フォルダに存在する必要があります。
第二引数
(Vector3.zero)
GameObjectを出現させる座標値について、Vector3型で指定します。
第三引数
(Quaternion.identity)
GameObjectを出現させるときの回転量について、Quaternion型で指定します。
第四引数
(0)
その GameObject が所属する、MUNネットワーク上のグループIDを指定します。
通常は0を指定します。
ここまでのNetworkControlの内容▲
改めて触れますが、ここまでの NetworkControl.cs の内容は以下の通りです。
using UnityEngine;
using System.Collections;
using MonobitEngine;
public class NetworkControl : MonobitEngine.MonoBehaviour {
/** ルーム名. */
private string roomName = "";
/** プレイヤーキャラクタ. */
private GameObject playerObject = null;
// Use this for initialization
void Start () {
// デフォルトロビーへの自動入室を許可する
MonobitNetwork.autoJoinLobby = true;
// MUNサーバに接続する
MonobitNetwork.ConnectServer("Bearpocalypse_v1.0");
}
// Update is called once per frame
void Update()
{
// MUNサーバに接続しており、かつルームに入室している場合
if (MonobitNetwork.isConnect && MonobitNetwork.inRoom)
{
// プレイヤーキャラクタが未登場の場合に登場させる
if (playerObject == null)
{
playerObject = MonobitNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity, 0);
}
}
}
// OnGUI is called for rendering and handling GUI events
void OnGUI() {
// デフォルトのボタンと被らないように、段下げを行なう。
GUILayout.Space(24);
// MUNサーバに接続している場合
if (MonobitNetwork.isConnect)
{
// ボタン入力でサーバから切断&シーンリセット
if (GUILayout.Button("Disconnect", GUILayout.Width(150)))
{
// サーバから切断する
MonobitNetwork.DisconnectServer();
// シーンをリロードする
Application.LoadLevel(Application.loadedLevelName);
}
// ルームに入室している場合
if (MonobitNetwork.inRoom)
{
// ボタン入力でルームから退室
if (GUILayout.Button("Leave Room", GUILayout.Width(150)))
{
MonobitNetwork.LeaveRoom();
}
}
// ルームに入室していない場合
if (!MonobitNetwork.inRoom)
{
GUILayout.BeginHorizontal();
// ルーム名の入力
GUILayout.Label("RoomName : ");
roomName = GUILayout.TextField(roomName, GUILayout.Width(200));
// ボタン入力でルーム作成
if (GUILayout.Button("Create Room", GUILayout.Width(150)))
{
MonobitNetwork.CreateRoom(roomName);
}
GUILayout.EndHorizontal();
// 現在存在するルームからランダムに入室する
if (GUILayout.Button("Join Random Room", GUILayout.Width(200)))
{
MonobitNetwork.JoinRandomRoom();
}
// ルーム一覧から選択式で入室する
foreach (RoomData room in MonobitNetwork.GetRoomData())
{
if (GUILayout.Button("Enter Room : " + room.name + "(" + room.playerCount + "/" + ((room.maxPlayers == 0) ? "-" : room.maxPlayers.ToString()) + ")"))
{
MonobitNetwork.JoinRoom(room.name);
}
}
}
}
}
}
単独で動作テストをする▲
プレイヤーキャラクタがきちんと動作するかどうかを確認する
ここまで組み込んだところで、プレイヤーキャラクタがきちんと動作するか確認をしてみましょう。
Unityエディタ上の実行ボタンを押してください。
実行して少し待つとGUIが現れるのですが、白色の背景に溶け込んで、「Room Name : 」の文字が見えないようです。
[Create Room] ボタンの左隣にあるのは、「ルーム名入力用のテキストボックス」ですので、
まずはそこにルーム名を入力し、[Create Room] ボタンを押しましょう。
ボタンを押すとプレイヤーが登場しますが、カメラが後ろに回り込みません。
一応、カーソルキーで移動したりスライディングしたりするのは確認できるようです。
Unityエディタのコンソールログを見ると、エラーが発生しているようです。
これが原因で、動作がおかしくなっている可能性が高そうです。
エラーの原因を特定し、修正を加える▲
コンソールでエラーが表示されている箇所をダブルクリックする
コンソールでエラーが発生している原因を特定しましょう。
まず、Unityエディタ上でコンソールウィンドウに切り替えてください。
通常は Project タブの隣に Console タブがあり、それをクリックすれば切り替えられます。
見当たらない場合には Unity のメニューから Window > Console を選んで開いてください。
コンソールウィンドウが表示されたら、その中にある
「NullReferenceException : Object reference not set an instance of an object」
と記述されている箇所をダブルクリックして、原因を特定します。
※ 環境によっては、下図のように
「NpShape::setFlag(s):triangle mesh and heightfield triggers are not supported!」
と表示されますが、こちらはどうしようもないので無視します。
エラーの原因を特定する
ダブルクリックすると、エラーが出ているのが、ThirdPersonCamera.cs の 18 行目(下記の赤枠)であることが分かります。
ここまでの状況を十分に把握していないとエラーの原因が分からないと思いますが、
このエラーがなぜ発生しているかについて解説すると、以下のことが言えます。
プレイヤーキャラクタをプレハブ化した結果、ThirdPersonCamera.Start() メソッドの実行時(ゲームスタート時)に
プレイヤーキャラクタが存在せず、GameObject.FindWithTag("Player") の結果が null になってしまうから。
よって、エラーを回避するためにプログラムを修正する必要が出ます。
エラーを修正する
このエラーを修正するために、ThirdPersonCamera.cs に修正を加えます。
まず、ThirdPersonCamera.cs の 18 行目をコメントアウトします。
//follow = GameObject.FindWithTag ("Player").transform;
このままでは ThirdPersonCamera.cs の LateUpdate() メソッドでエラーが発生してしまいますので、
ThirdPersonCamera.cs の LateUpdate() メソッドを、以下のように書き換えます。
void LateUpdate ()
{
// follow に値が入っていない場合
if ( follow == null )
{
// プレイヤーが存在したら、その transform を follow にセット
GameObject gameObject = GameObject.FindWithTag("Player");
if( gameObject != null )
{
follow = GameObject.FindWithTag("Player").transform;
}
}
else
{
// setting the target position to be the correct offset from the
m_TargetPosition = follow.position + Vector3.up * distanceUp - follow.forward * distanceAway;
// making a smooth transition between it's current position and the position it wants to be in
transform.position = Vector3.Lerp(transform.position, m_TargetPosition, Time.deltaTime * smooth);
// make sure the camera is looking the right way!
transform.LookAt(follow);
}
}
ここまでのThirdPersonCameraの内容▲
改めて触れますが、ここまでの ThirdPersonCamera.cs の内容は以下の通りです。
using UnityEngine;
using System.Collections;
/// <summary>
/// Third person camera.
/// </summary>
public class ThirdPersonCamera : MonoBehaviour
{
public float distanceAway;
public float distanceUp;
public float smooth; // how smooth the camera movement is
private Vector3 m_TargetPosition; // the position the camera is trying to be in)
Transform follow;
void Start(){
//follow = GameObject.FindWithTag ("Player").transform;
}
void LateUpdate ()
{
// follow に値が入っていない場合
if ( follow == null )
{
// プレイヤーが存在したら、その transform を follow にセット
GameObject gameObject = GameObject.FindWithTag("Player");
if( gameObject != null )
{
follow = GameObject.FindWithTag("Player").transform;
}
}
else
{
// setting the target position to be the correct offset from the
m_TargetPosition = follow.position + Vector3.up * distanceUp - follow.forward * distanceAway;
// making a smooth transition between it's current position and the position it wants to be in
transform.position = Vector3.Lerp(transform.position, m_TargetPosition, Time.deltaTime * smooth);
// make sure the camera is looking the right way!
transform.LookAt(follow);
}
}
}
起動時のカメラの位置も変更する▲
Projectビュー内の「Camera」の位置・姿勢を変更する
ついでに、起動時のカメラビューのままでは、こちらが用意したGUIが良く見えないので、カメラ位置を調整してしまいましょう。
Projectビューにある「Camera」を選択してください。
シーンビュー内に Camera Preview が表示されますので、本来であれば、それを見ながら調整します。
今回は面倒ですので、Inspector に、以下の値を直接入力してください。
再度、単独で動作テストをする▲
改めて、プレイヤーキャラクタがきちんと動作するかどうかを確認する
改めて、プレイヤーキャラクタがきちんと動作するか確認をしてみましょう。
Unityエディタ上の実行ボタンを押してください。
実行して少し待つとGUIが現れます。さきほどよりも、少しは見やすくなりました。
"RoomName : " の右隣にあるテキストボックスにルーム名を入力し、[Create Room] ボタンを押しましょう。
ボタンを押すとプレイヤーが登場し、カメラが即座に後ろに回り込みます。
カーソルキーで移動したりスライディングしたりしている間も、カメラが追随してくれます。
NullReferenceException のエラー表示も消えています。問題ありませんね。