ページ

2013年12月20日金曜日

実際にPhotonCloudを使ってみる~基本編③~

第一回

第二回

最近諸々あってあまりUnityに触れません。
開発の遅れが少し心配です。

さて、第三回は、前回作成したキューブを各プレイヤーが動かせるようにしましょう。
ですがその前に、PhotonCloudによる同期について説明する必要があります。

そもそも同期とは、複数のゲーム画面で同じ処理を行う、または変数の値を等しくする、という意味です。
PhotonCloudでこれを行う場合、主に2つの方法があります。

①OnPhotonSerialize
継続的に変数を同期します。
設定により、厳密に同期するか、ざっくり同期するか選択可能です。
どちらの場合であっても、モバイル環境ではそれなりに負荷がかかることに注意です。
キャラクターの位置情報の同期などに使用することが多いです。

②RPC
リモートプレジャーコールと言うらしいです。
「リモートプレ…あぁいや、RPCか」なんてカッコつけて使いましょう。
こちらは同期というより、厳密には同じ関数を実行する、という言い方が正しいです。
その際、実行元のプレイヤーが持つ変数が渡された状態で関数が実行されるため、結果的に変数の同期もできるというわけです。
分かりにくいのでいずれ実例を含めて紹介します。
任意で同期することができるため、例えば誰かが被弾してHPが減ったとき、その情報を渡しつつ、HPバーを更新する、なんてことができます。

以上、二種類の方法がありますが、今回は移動の同期のため、上記の継続的な同期を使用します。

それではまず、移動できるように物理演算を付加し、キー入力によって動作するようにします。

新たに「moveTarget.cs」を作成し、以下のように記述します。

「moveTarget.cs」

using System.Collections;

public class moveTarget : MonoBehaviour {

private Rigidbody myRigid;
private bool upSw;
private bool downSw;
private bool leftSw;
private bool rightSw;

void Start () {
//一応リジッドボディをキャッシュ
myRigid = this.gameObject.GetComponent();
}

void Update () {
//上
if( Input.GetKey(KeyCode.UpArrow) ){
upSw = true;
}else{
upSw = false;
}
//下
if( Input.GetKey(KeyCode.DownArrow) ){
downSw = true;
}else{
downSw = false;
}
//左
if( Input.GetKey(KeyCode.LeftArrow) ){
leftSw = true;
}else{
leftSw = false;
}
//右
if( Input.GetKey(KeyCode.RightArrow) ){
rightSw = true;
}else{
rightSw = false;
}
}

void FixedUpdate(){
if(upSw){
myRigid.AddForce(Vector3.forward * 10f);
}else if(downSw){
myRigid.AddForce(Vector3.forward * -10f);
}else if(leftSw){
myRigid.AddForce(Vector3.right * -10f);
}else if(rightSw){
myRigid.AddForce(Vector3.right * 10f);
}
}

}

ざっくり解説すると、
このスクリプトがアタッチされたオブジェクトのリジッドボディを取得し、
それに対してAddForceで力を加えています。
これの制御をキーボードからのキー入力で行っているわけですね。
PhotonCloudと無関係なので、詳しくは自力で何とかしてください。

これを前回作成したプレファブにアタッチします。
その際、リジッドボディを付加することを忘れないでください。
リジッドボディのパラメータはDragを1、UseGravityをオフに、FreezePositionからYにチェックを入れて下さい。
画面を見やすくしたいので、カメラのトランスフォームを変更します。
位置をx:0, y:40, z:0に、角度をx:90, y:0, z:0と入力して下さい。



一旦ビルドして動かしてみましょう。
このスクリプトではキーボードの矢印キーに対応していますので、色々押してみてください。
動きましたか?
なにやら動けば成功です。
一度ウインドウを閉じ、今度は多重起動してみましょう。

すると、あれれ、どちらのオブジェクトも動きやがりましたね。
オブジェクトがどのプレイヤーから生成されたものなのかを判別し、 自分の物だけ動くようにしましょう。

先ほどの「moveTarget.cs」に以下のように追記します。

「moveTarget.cs」

using UnityEngine;
using System.Collections;

public class moveTarget : MonoBehaviour {

private Rigidbody myRigid;
private bool upSw;
private bool downSw;
private bool leftSw;
private bool rightSw;
private PhotonView myPV;

void Start () {
//photonViewを取得し、自分のオブジェクトでなければスクリプト停止
myPV = PhotonView.Get(this);
if(!myPV.isMine){
this.enabled = false;
}
//一応リジッドボディをキャッシュ
myRigid = this.gameObject.GetComponent();
}

《後略》


◆PhotonView.isMine
PhotonViewが自分の物であるか、他のプレイヤーの物であるかを判定します。
自分の物である場合、trueが返されます。

これを使い、自分の物でない場合はスクリプトをオフにしてしまいましょう。
もう一度多重起動して確かめていただくと、一つのオブジェクトしか動かないことが確認できるかと思います。

では、いよいよ同期に入ります。
アタッチしているPhotonViewに、同じくアタッチしているリジッドボディをドラッグします。
リジッドボディと書かれた辺りを引っ張ってみてください。



このように設定できればOKです。
PhotonViewにはトランスフォーム、リジッドボディ、スクリプトなどを格納することができ、
これが同期の対象となります。
スクリプトを同期する場合、具体的に何を同期するのか
「OnPhotonSerialize」による記述が必要です。

それでは多重起動してみましょう!
複数の実行環境で同期して動いているのが確認できたでしょうか。

今回はここまで、次回はRPCについてお話します。

例によって変な部分がありましたら是非お教え下さい。