前回:Photon Unity Networking (PUN)のチュートリアルをやってみる (1)
ルームに入室するところまではできました。今回はモンスターを動かしてみます。
モンスターデータのダウンロード
動かす対象となるモンスターデータは、AssetStoreではなく直接ダウンロードしてきます。
日本語のチュートリアルはリンクが古いようなので、英語のほうから拾ってきます。Dropboxですが登録なしでもダウンロードできます。
このunitypackageをダウンロード、インポートします。
で、インポートするといくつかの場所で、
Assets/Monstergame/Resources/Scripts/CharacterControl.js(61,9): BCE0048: Type 'UnityEngine.Component' does not support slicing.
というエラーが出てきます。どうもコードの書き方が古いみたい。
ここでAPIアップデータが実行される、または「Assets > Run API Updater...」から実行してみるとコンバートが走って解決されるのですが、実行されなかったので地道に直していくことにします…
修正した点は以下の通り。
Monstergame/Resources/Scripts/CharacterControl.js:61-65
animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever; animation[fallPoseAnimation.name].wrapMode = WrapMode.ClampForever; animation[idleAnimation.name].wrapMode = WrapMode.Loop; animation[runAnimation.name].wrapMode = WrapMode.Loop; animation[walkAnimation.name].wrapMode = WrapMode.Loop;
を
GetComponent.<Animation>()[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever; GetComponent.<Animation>()[fallPoseAnimation.name].wrapMode = WrapMode.ClampForever; GetComponent.<Animation>()[idleAnimation.name].wrapMode = WrapMode.Loop; GetComponent.<Animation>()[runAnimation.name].wrapMode = WrapMode.Loop; GetComponent.<Animation>()[walkAnimation.name].wrapMode = WrapMode.Loop;
に。
139-167行を、
//Play animation if (b_isJumping) { if (controller.velocity.y > 0 ) { animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed; animation.CrossFade(jumpPoseAnimation.name, 0.1); } else { animation[fallPoseAnimation.name].speed = fallAnimationSpeed; animation.CrossFade(fallPoseAnimation.name, 0.1); } } else { if (IsAir()) { // Fall down animation[fallPoseAnimation.name].speed = fallAnimationSpeed; animation.CrossFade(fallPoseAnimation.name, 0.1); } else { //Not fall down //If the character has no velocity or very close to 0 show idle animation if(controller.velocity.sqrMagnitude < 0.1) { animation[idleAnimation.name].speed = idleAnimationSpeed; animation.CrossFade(idleAnimation.name, 0.1); } else { //Checking if the character walk or run if (b_isRun) { animation[runAnimation.name].speed = runAnimationSpeed; animation.CrossFade(runAnimation.name, 0.1); } else { animation[walkAnimation.name].speed = walkAnimationSpeed; animation.CrossFade(walkAnimation.name, 0.1); } } } }
から
//Play animation if (b_isJumping) { if (controller.velocity.y > 0 ) { GetComponent.<Animation>()[jumpPoseAnimation.name].speed = jumpAnimationSpeed; animation.CrossFade(jumpPoseAnimation.name, 0.1); } else { GetComponent.<Animation>()[fallPoseAnimation.name].speed = fallAnimationSpeed; animation.CrossFade(fallPoseAnimation.name, 0.1); } } else { if (IsAir()) { // Fall down GetComponent.<Animation>()[fallPoseAnimation.name].speed = fallAnimationSpeed; animation.CrossFade(fallPoseAnimation.name, 0.1); } else { //Not fall down //If the character has no velocity or very close to 0 show idle animation if(controller.velocity.sqrMagnitude < 0.1) { GetComponent.<Animation>()[idleAnimation.name].speed = idleAnimationSpeed; animation.CrossFade(idleAnimation.name, 0.1); } else { //Checking if the character walk or run if (b_isRun) { GetComponent.<Animation>()[runAnimation.name].speed = runAnimationSpeed; animation.CrossFade(runAnimation.name, 0.1); } else { GetComponent.<Animation>()[walkAnimation.name].speed = walkAnimationSpeed; animation.CrossFade(walkAnimation.name, 0.1); } } } }
に。
Assets/Monstergame/Resources/Scripts/myThirdPersonController.js:362行を
animation[attackPoseAnimation.name].AddMixingTransform(buik);
から
GetComponent.<Animation>()[attackPoseAnimation.name].AddMixingTransform(buik);
に修正してやります。
そしたらようやく、自動アップデータが動いたようで、
が出てきたので「I Made a Backup. Go Ahead!」を実行。エラーが邪魔してたのかなあ。
モンスターを追加する
PUNでは、PhotonViewスクリプとを設定したオブジェクトのPrefabをResourcesから生成して、監視、同期させていくことになります。
まずはモンスターのPrefabにPhotonViewを追加。
「Assets > Monstergame > Resources > monsterprefab」を選択して、Inspectorから「Add Compornent」、「Photon View」を追加します。
そして、「observed」のところにmonsterprefabをドラッグ&ドロップ。Transformが設定されます。
次に、このPrefabから自分のインスタンスを作成します。ルームに入室したら自分のキャラクターを出現させるようにします。
RandomMacthmakerにOnJoinedRoomを追加し、さらにそこでインスタンス化。
/// <summary> /// ルームへ入室した /// </summary> public override void OnJoinedRoom() { GameObject monster = PhotonNetwork.Instantiate("monsterprefab", Vector3.zero, Quaternion.identity, 0); }
PhotonNetwork.Instantiateを使ってインスタンスを作らないと、Photonの管理にならないので注意です。
ここまでで実行してみると魔物が奈落に落ちていく。
地味に回転して仰向けになっていくのがすき。
さておき地面を作ってやらないとなんともですね。Plainだけでもいいんですがチュートリアルに倣ってテクスチャとかも貼ってみます。
地面を作成する
このあたりはPhotonとは関係ないUnity一般の作業になります。
まず「GameObject > 3D Object > Plane」で、平面を作ります。真っ白です。
このPlaneのInspectorから、positionを0,0,0に、scaleを10,1,10に設定します。
これでも奈落に落ちるのは回避できるようになったのですが、せっかくなのでここにテクスチャも貼ってみます。
チュートリアルで紹介されているアセットがもう配布していないようなので、適当な地面のテクスチャを探してきます。これはなんでもいいですが私がみつけてきたのはこれ。
で、先ほど追加したPlaneのInspectorから、「Mesh Renderer」のMaterialsを開いて、「Element 0」に、インポートした「Sand textures pack > Sand 01 > Sand pattern 01」をドラッグ&ドロップします。
そうすると見た目が変わりましたね。
これで実行しても落ちなくなりました。
うん。キモい…
でも見てると慣れてくる…これがキモカワというやつか…?
とりあえずこれでキャラクターの同期もできました。VikingのときみたくWindowsビルドをして、WindowsバイナリとEditorの実行との2クライアントでやってみると2匹に増えてると思います。
ふえた…
さらに、PhotonはAndroidなどにも対応していますので、Androidでも実行することができます。
もしAndroid端末をお持ちでしたらPCに接続して実行してみてください。(Android向けBuild設定などについては細かくなるので省略します)
3匹になっているのがおわかりいただけるだろうか…
ここまでで、Photon Serverを通して同期するキャラクターを生成するところまでできました。
ですが動かしてみるとわかるように、画面に出ているモンスター全部がキーを拾ってしまっているので、キーの操作などが全キャラクターに行ってしまっています。
だから全員が同じ動きをしてしまう。
次回はそのあたりも含めて、キャラクターの動きなどに調整を入れていきます。