【目次】
導入指針
Unityちゃんアセットのインポート
地面を作る
プレハブを展開する
プレイヤープレハブにアニメーターコントローラを適用する
プレイヤープレハブにスクリプトを適用する
プレイヤープレハブを保存する
非プレイヤープレハブを保存する
複数体表示の下準備
導入指針▲
prefork_battle_matching_lite を使って、複数のキャラクタの姿勢同期を行ってみましょう。
イメージとしては以下のようになります。
1. キャラクタはSD-Unityちゃんを用い、三人称視点で自由に走れるようにする。
2. キャラクタの頭上にCharaId(プレイヤーのユニークID)を表示する。
3. キャラクタ同士の位置や向きを同期させる。
4. その他の部分は prefork_battle_matching 準拠で実装する。
上記のうち、1.と2.についてはモノビットエンジン特有の部分は全くなく、Unity特有のコーディングです。
厄介ではありますが、先にこちらの方を実装していきましょう。
次のページでは 3. について触れています。既に「チャットで会話するシステム」は出来上がっていますので、これを参考に
『文字列送受信』と同様に『キャラクタ姿勢の送受信』を組むことで実現します。
Unityちゃんアセットのインポート▲
■ まだ基礎編を実践していない方は
先に基礎編を一通り行ない、現状のサンプルが正常に動作することを確認してください。
■ SD-Unityちゃんアセットのインポート
SD-UnityちゃんアセットをUnityプロジェクトにインポートします。
まずは以下のリンクからアセットをダウンロードしてください。
SDユニティちゃん 3Dモデルデータ ダウンロード
ダウンロード(Download ver1.0)をクリックし、SD_unitychan.unitypackage を任意の場所に保存してください。
保存したファイルは Unity の Projectビューの Assets にドラッグ&ドロップします(下図参照)。
ドロップするとアセットの Importing package のウィンドウが開きますので、Import ボタンを押下します。
インポートが終了すると、以下のように、Assets 直下に UnityChan フォルダが作成されます。
地面を作る▲
■ Plane を作成する
続けて、地面を作成してみましょう。
Unity メニューから GameObject > 3D Object > Plane を選択します。
Inspecter から Scale を 20倍にしておきましょう。
■ テクスチャを貼る
作成した Plane にテクスチャを貼り付けましょう。
テクスチャはSD-Unityちゃんアセットを利用します。
Assets/UnityChan/Stage/Textures にある4枚のテクスチャのうち1枚を選択して
Hierarchyビューにある Plane にドラッグ&ドロップしてください。
選択したテクスチャに応じて地面の色が変化します。
プレハブを展開する▲
■ ベースとなるプレハブを展開する
今回登場させる複数のキャラクタを表示するための、SD-Unity ちゃんのプレハブを新規作成します。
まずはベースとなるプレハブを Hierarchy に展開します。
ProjectビューからAssets/UnityChan/SD_unitychan/Prefabs 内にある SD_unitychan_generic.prefab を
Hierarchy にドラッグ&ドロップしてください。
すると画面中央にSD-Unityちゃんが表示されます。
ただし、今の状態ではライトが反映されませんので、SD-Unityちゃん専用のライトをシーンに配置します。
ProjectビューからAssets/UnityChan/Prefabs 内にある Directional light for UnityChan.prefab を
Hierarchy にドラッグ&ドロップしてください。
するとライトが追加されます。
■ 三人称視点のカメラを追加する
SD-Unityちゃんを三人称視点で表示させるためのカメラを用意します。
Unity メニュ-から GameObject > Camera を選択し、Hierarchy に新規カメラ Camera を作成します。
更に作成した Camera を、同じ Hierarchy にある SD_unitychan_generic にドラッグ&ドロップします。
以下のように、SD_unitychan_generic の子になるように設定してください。
更に、Camera のインスペクタを変更します。
下記のように、キャラクタの原点位置に対し、(0, 1, -2) の位置に来るように設定します。
この時点でUnityの実行ボタンを押し、SD-Unityちゃんの後姿が以下のように表示されることを確認してください。
確認し終わったら実行ボタンを解除してください。
プレイヤープレハブにアニメーターコントローラを適用する▲
■ アニメーターコントローラを新規作成する
今回使用するSD-Unityちゃんの仕様に基づいた、アニメーターコントローラを新規作成します。
Projectビューから Assets/Projects/Prefabs を選択した状態で、
Unity メニューから Assets > Create > Animator Controller を選択して、新規作成してください。
■ アニメーターコントローラを編集する
作成した New Animator Controller.controller をダブルクリックで開きます。
すると以下の画面に変化します。
薄黒グリッド枠の任意の場所を右クリックして、CreateState > Empty を選択します。
すると以下のように New State が作成されます。
作成した New State について、Inspector から Stand に名前を変更します。
また Motion について、◎ボタンを押し Select Motion ウィンドウを表示させ
Assets タグから Standing@loop を選択します。
なお Standing@loop は2種類表示されますが、ウィンドウ下部に表示される Animation Clip を参照し
SD_unitychan_motion_Generic.fbx に関連付けられているものを選択してください。
同様の手順で、Run も作成しておきましょう。
こちらもSelect Motion の選択時に Running@loop が2種類表示されますが、
SD_unitychan_motion_Generic.fbx に関連付けられているものを選択してください。
更に、作成した Stand の枠内を右クリックして、Make Transition を選択します。
すると引き伸ばし可能な矢印(Transition)が出てきますので、Run の枠内を選択します。
すると、以下のように Stand → Run への矢印が出来ます。
同様の手順で、Run → Stand への矢印も引きます。
これがアニメーションの遷移を示すわけですが、その条件として変数値を用いましょう。
Parameters の右側の + ボタンを押し、Int を選択します。
変数の名前が付けられますので、animIdとしておきましょう。
Stand → Run の Transitions(矢印)を選択し、Inspector から遷移条件を設定します。
Atomicのチェックボックスを外し、かつ Conditions の ExitTime を animId に差し替え、
animId, Equals, 1 となるよう設定します。
同様に Run → Stand への遷移条件についても以下のように設定してください。
これで animId が 0 なら Stand, animId が 1 なら Run になるように設定できました。
■ アニメーターコントローラを適用する
作成した New Animator Controller.controller を Hierarchy ビュー内の SD_unitchan_generic に適用します。
Hierarchy ビューから SD_unitchan_generic を選択し、/Assets/Projects/Prefabs フォルダ内の
New Animator Controller.controller を Inspector 無いの Animator > Controller にドラッグ&ドロップします。
以下のように切り替わります。
プレイヤープレハブにスクリプトを適用する▲
■ スクリプトを新規に作成する
今回使用するSD-Unityちゃんの仕様に基づいた、スクリプトを新規作成します。
Projectビューから Assets/Projects/Scripts/sample を選択した状態で、
Unity メニューから Assets > Create > C# Script を選択して、新規作成してください。
また作成したスクリプト名は SD_Unitychan_PC にしておきましょう。
この SD_Unitychan_PC をダブルクリックして開き、以下の中身に置き換えてください。
using UnityEngine;
using System;
using System.Collections;
public class SD_Unitychan_PC : MonoBehaviour
{
private Animator animator; // アニメータコントローラ
private int animId = 0; // 再生中のアニメーションID
private UInt64 charaId = 0; // キャラクタID
private Vector3 charaIdDisp; // キャラクタIDの表示位置
private static Camera mainCamera = null; // メインカメラ
// Use this for initialization
void Start()
{
animator = gameObject.GetComponent<Animator>();
animId = Animator.StringToHash("animId");
}
// Update is called once per frame
void Update()
{
// キャラクタID表示位置の算出
if (mainCamera != null)
{
charaIdDisp = mainCamera.WorldToScreenPoint(gameObject.transform.position + new Vector3(0, 1.25f, 0));
}
// キャラクタの移動&アニメーション切り替え
if (Input.GetKey("up"))
{
gameObject.transform.position += gameObject.transform.forward * 0.1f;
animator.SetInteger(animId, 1);
}
else
{
animator.SetInteger(animId, 0);
}
if (Input.GetKey("right"))
{
gameObject.transform.Rotate(0, 2.0f, 0);
}
if (Input.GetKey("left"))
{
gameObject.transform.Rotate(0, -2.0f, 0);
}
}
void OnGUI()
{
// キャラクタIDの表示
if (charaIdDisp != null)
{
GUI.Label(new Rect(charaIdDisp.x - 60, Screen.height - charaIdDisp.y - 20, 120, 40), "CharaId:0x" + mln.Utility.ToHex(charaId));
}
}
public void SetCharaID(UInt64 charaId)
{
this.charaId = charaId;
}
public void SetMainCamera(Camera camera)
{
mainCamera = camera;
}
public static Camera GetMainCamera()
{
return mainCamera;
}
}
■ 既存のスクリプトをすべて破棄し、SD_Unitychan_PC のスクリプトを割り当てる。
スクリプトを作成し終えたら、Hierarchy の SD_unitychan_generic を選択します。
Inspecter に表示されている以下のスクリプトをすべて、右クリック > Remove Component で破棄します。
・ Idle Changer
・ Spring Manager
・ Random Wind
・ Auto Blinkfor SD
・ Face Update
その上で、先ほど作成した SD_Unitychan_PC のスクリプトを SD_unitychan_generic に
ドラッグ&ドロップして組み込み、以下のように設定します。
■ 実行ボタンを押し、動作することを確認する。
ここでUnityの実行ボタンを押下し、カーソルキーによってキャラクタが移動・回転するのを確認しておきましょう。
プレイヤープレハブを保存する▲
■ プレイヤーのプレハブとして保存しておく
ここまで作成した SD_unitychan_generic を一旦プレイヤープレハブとして保存しておきます。
まず、SD_unitychan_generic を SD_unitychan_PC にリネームしておきましょう。
その上で、Projectビューを Assets/Projects/Prefabs を開いた状態で、SD_unitychan_PC をドラッグ&ドロップします。
SD_unitychan_PC.prefab は以下のように保存されます。
非プレイヤープレハブを保存する▲
■ Hierarchy登録データのリネーム
操作しないプレイヤー(ネット回線先にいるユーザーの操作プレイヤー)用の「非プレイヤー」のプレハブを同じ手順で作成します。
すべて最初からやり直しだと厳しいので、既存の hierarchy に登録されている SD_unitychan_PC を使いましょう。
SD_unitychan_PCのプレハブは既に保存して退避済みですから、SD_unitychan_NPC とリネームしてしまいましょう。
■ 非プレイヤー用のスクリプトを作成する
Projectビューから Assets/Projects/Scripts/sample を選択した状態で、
Unity メニューから Assets > Create > C# Script を選択して、新規作成してください。
また作成したスクリプト名は SD_Unitychan_NPC にしておきましょう。
この SD_Unitychan_NPC をダブルクリックして開き、以下の中身に置き換えてください。
using UnityEngine;
using System;
using System.Collections;
public class SD_Unitychan_NPC : MonoBehaviour
{
private Animator animator; // アニメータコントローラ
private int animId = 0; // 再生中のアニメーションID
private UInt64 charaId = 0; // キャラクタID
private Vector3 charaIdDisp; // キャラクタIDの表示位置
// Use this for initialization
void Start()
{
animator = gameObject.GetComponent<Animator>();
animId = Animator.StringToHash("animId");
}
// Update is called once per frame
void Update()
{
// キャラクタID表示位置の算出
if (SD_Unitychan_PC.GetMainCamera() != null)
{
charaIdDisp = SD_Unitychan_PC.GetMainCamera().WorldToScreenPoint(gameObject.transform.position + new Vector3(0, 1.25f, 0));
}
}
void OnGUI()
{
// キャラクタIDの表示
if (charaIdDisp != null)
{
GUI.Label(new Rect(charaIdDisp.x - 60, Screen.height - charaIdDisp.y - 20, 120, 40), "CharaId:0x" + mln.Utility.ToHex(charaId));
}
}
public void SetCharaID(UInt64 charaId)
{
this.charaId = charaId;
}
public void SetAnimId(Int32 animId)
{
if(animator != null )
{
animator.SetInteger(this.animId, animId);
}
}
}
■ 既存のスクリプトをすべて破棄し、SD_Unitychan_NPC のスクリプトを割り当てる。
スクリプトを作成し終えたら、Hierarchy の SD_unitychan_NPC を選択します。
Inspecter に表示されている SD_unitychan_PC を右クリック > Remove Component で破棄します。
その上で、先ほど作成した SD_Unitychan_NPC のスクリプトを SD_unitychan_NPC に
ドラッグ&ドロップして組み込み、以下のように設定します。
■ カメラを削除する
もう1つ、Hierarchy の SD_unitychan_NPC に追加しているCamera情報は
プレイヤーキャラクタとしては三人称視点で必要ですが、他人のプレイヤーキャラクタとしては
カメラ情報として不要になりますので、これを削除します。
Hierarchy の SD_unitychan_NPC 以下のような状態にしてください。
■ 非プレイヤーのプレハブとして保存しておく
ここまで作成した SD_unitychan_NPC を一旦非プレイヤープレハブとして保存しておきます。
Projectビューを Assets/Projects/Prefabs を開いた状態で、SD_unitychan_NPC をドラッグ&ドロップします。
SD_unitychan_NPC.prefab は SD_unitychan_PC.prefab と同階層に保存されます。
■ プレハブ生成用に作成したオブジェクトを削除する。
後片付けとして、PC/NPC 両方の prefab の元となったhierarchyオブジェクトを削除し、最初の画面では地面以外なにも表示させないようにします。
hierarchy 内の SD_unitychan_NPC を削除してください。
複数体表示の下準備▲
■ ここまでの内容を踏まえて、複数体表示のための組み込みを行なう。
ここまでの内容を踏まえ、ゲーム中の複数体キャラクタ表示の下準備を行います。
NPC/PCの両方のprefabを使い、Instantiateで任意のタイミングで出現できるようにします。
では、Projectビューの Assets/Projects/Scripts/sample の中から ClientScene(ClientScene.cs)を開き、
フィールド要素として以下の項目を追加してください。
public GameObject unityChan_PC; //< プレイヤープレハブ(プレハブ受け取り口)
public GameObject unityChan_NPC; //< 非プレイヤープレハブ(プレハブ受け取り口)
public static GameObject g_unityChan_PC; //< プレイヤープレハブ(グローバルオブジェクト)
public static GameObject g_unityChan_NPC; //< 非プレイヤープレハブ(グローバルオブジェクト)
public static Dictionary<UInt64, GameObject> g_CharaList = new Dictionary<UInt64, GameObject>(); //< キャラクタリスト
public static readonly object g_mutex = new object(); //< g_CharaList の排他制御用
さらに Start メソッドで、以下のような手法で(強引ですが)プレハブインスタンスをグローバル変数として使用可能にします。
// グローバル変数として利用可能に
g_unityChan_PC = unityChan_PC;
g_unityChan_NPC = unityChan_NPC;
■ unityChan_PC, unityChan_NPC にプレハブを割り当てる。
上記で追加した GameObject 型の変数 unityChan_PC および unitychan_NPC は hierarchy の Inspector から
実行前情報として値を設定することが出来ます。
これを利用して、先ほどまで作成していた2つのプレハブオブジェクトを割り当てます。
Unity の Hierarchyビューから ClientScene を選択します。
Inspector の ClientScene(Script)の欄に public の変数一覧が出ますので、
このうち、Unity Chan_PC および Unity Chan_NPC に対し、それぞれ
Asset/Projects/Prefabs に保存していた SD_unitychan_PC および SD_unitychan_NPC を
ドラッグ&ドロップで割り当てましょう。
※ これによって何が出来るか?
この組み込みによって、任意のスクリプト内で「プレイヤーキャラ/非プレイヤーキャラ」を出現させたい場合
そのキャラクタIDが把握できているのであれば
lock( ClientScene.g_mutex )
{
// charaId はいずこかで与えられる。
ClientScene.g_CharaList[charaId] = MonoBehaviour.Instantiate( ClientScene.g_unityChan_PC ) as GameObject;
}
lock( ClientScene.g_mutex )
{
// charaId はいずこかで与えられる。
ClientScene.g_CharaList[charaId] = MonoBehaviour.Instantiate( ClientScene.g_unityChan_NPC ) as GameObject;
}
という形でプレハブから生成することができ、かつその情報を ClientScene.g_CharaList で管理することが出来るようになります。