Unityでネットワーク通信(2) - アニメーションを同期させてみた -

前回の課題は次の2つ。
1.アニメーションが同期されない。
2.同じユニティちゃんをホスト・クライアントどちらからでも操作できてしまう。

というわけで、今回はこれらを解決してみる。

そもそも、NetworkViewはObservedプロパティに設定したコンポーネントに関するデータを同期する。
自分の環境では、NetworkViewをunitychanオブジェクトにアタッチした時点で、Transformコンポーネントが自動的に設定されていた。

f:id:tomcky:20140728231517p:plain

そのためTransformに関するデータ、つまり移動のみが同期され、アニメーションは同期されなかったというわけらしい。

ということは、もう1つNetworkViewをアタッチしてAnimationコンポーネントを設定する、っていうのが解決アプローチとしてありそうだが、Remote Procedure Call(RPC)っていう仕組みを使った方が簡単そうだったので、そちらで試してみる。

RPCは遠隔の処理をネットワークを介して呼び出す仕組みのことで、これを使ってAnimatorに対してパラメータをセットしている関数を呼び出してやればよい。

なので、ユニティちゃんをコントロールするためのスクリプト内に記述されている、

anim.SetFloat("Spped", v);
anim.SetFloat("Direction", h);
resetCollider();

といった関数を、

[RPC]
void SendSpeedFloat(string name, float value) {
  anim.SetFloat(name, value);
}
[RPC]
void SendDirectionFloat(string name, float value) {
  anim.SetFloat(name, value);
}
[RPC]
void SendResetCollider() {
  resetCollider();
}

といった感じで、RPCで呼び出せるように関数として準備してやったうえで、代わりに呼び出してやる。

//anim.SetFloat("Spped", v);
networkView.RPC("SendSpeedFloat", RPCMode.All, "Speed", v);
//anim.SetFloat("Direction", h);
networkView.RPC("SendDirectionFloat", RPCMode.All, "Direction", h);
// resetCollider();
networkView.RPC("SendResetCollider", RPCMode.All);

これでOK。さっそく実行してみる。あれ、エラーでた。。。

Can't send RPC function since no connection was started.

接続されていないときはRPCが呼ばれないようにしないといけないのか。

どうするかなーって色々試してみたのだけど、NetworkView.isMineを使ってみたら良い感じだったので、これでいく。
NetworkView.isMineは、アタッチされたオブジェクトがどこで生成されたかを判別できるものであり、ホスト側で生成されたオブジェクトの場合、ホスト側でのisMineはtrueに、クライアント側でのisMineはfalseになる。
で、これはネットワーク接続されていない場合はfalseになるようで、今回はそれを利用して、RPCの呼び出しをif(NetworkView.isMine){...}で囲ってやることでエラーを回避することにした。

で、先の説明からもわかるとおり、isMineを使えばホスト・クライアントの区別をつけることができるので、ホスト・クライアント区別なくユニティちゃんを動かせてしまう問題も解決できる。
というか、むしろこのためにisMineを普通は使うんだと思う。

さて、というわけなのでFixedUpdate関数のはじめから終わりまでif文で囲ってやればいいか。ちょっと安直だけど。。。

void FixedUpdate() {
  if(networkView.isMine) {
    ...
    //anim.SetFloat("Spped", v);
    networkView.RPC("SendSpeedFloat", RPCMode.All, "Speed", v);
    //anim.SetFloat("Direction", h);
    networkView.RPC("SendDirectionFloat", RPCMode.All, "Direction", h);
    ...
    // resetCollider();
    networkView.RPC("SendResetCollider", RPCMode.All);
  }
}

これで、エラーが解消されて、アニメーションを無事同期できるようになり、さらにホスト側からのみ動かせるようになりましたー。

...次は何しようかな。