Unityでオンラインマルチプレイ対応4-キャラクターを登場させる-

今回はユーザーがサーバーに接続したら操作キャラクターをゲームの世界に登場させます。

前回でPhoton Cloudのサーバーに接続する事が出来るようになりました。

Unityでオンラインマルチプレイ対応3-ネットワーク接続処理-
Unityでマルチプレイヤーのゲームに対応する為、ネットワークに接続する為のスクリプトの作成とUIを作成していきます。

登場させるキャラクターは

Unityでオンラインマルチプレイ対応1-まずは動くキャラ作り-
UnityでPhotonCloudを使ったリアルタイムのオンライン対応をしていきます。今回はオンライン対応する前の主人公と敵キャラクターを作成していきます。

で作成したEthanになります。

スポンサーリンク

EthanにPhotonViewを取りつけプレハブにする

マルチプレイ1の記事で作成したEthanはあらかじめヒエラルキー上に配置していました。

しかしネットワーク対応する場合は自分のゲーム世界ではなくネットワーク上にキャラクターを登場させなくてはいけません。

ネットワーク上にキャラクターを登場させる為にはキャラクターにPhotonViewコンポーネントを取りつけます。

Add Component→Photon Networking→PhotonViewを選択します。

PhotonViewを取りつけたらEthanをProjectsタブのAssetsエリアにPrefabsというフォルダを作成し、さらにその中にResourcesという特殊フォルダを作成しその中にドラッグ&ドロップしてプレハブにします。

敵キャラクターもPhotonViewを取りつけ同じようにPrefabs/Resourcesフォルダの中にドラッグ&ドロップしプレハブ化しておきます。

Resourcesフォルダに入れる理由はネットワーク上にキャラクターをインスタンス化する時にResourcesフォルダにプレハブを入れる必要があるからです。

プレハブにしたEthanをネットワーク上でインスタンス化

プレハブにしたEthanをネットワークに登場させましょう。

前回ネットワークに接続する事が出来ましたが、部屋に入室したと同時にネットワーク上にキャラクターをインスタンス化します。

NetworkManagerスクリプトに処理を追加します。

OnJoinedRoom内でコルーチンをスタートさせます。

SetPlayerメソッドではPhotonNetwork.Instantiateを使ってネットワーク上にキャラクターをインスタンス化します。

PhotonNetwork.Instantiateで指定するプレハブは文字列で指定し、EthanはResourcesフォルダの直下に入れておく必要があります。

これでプレイヤーが入室した時にゲームの世界に操作キャラクターが登場する事になります。

ネットワーク上にキャラクターが登場するか確認

それでは確認してみましょう。

↑のようにアプリケーションを2つ起動した後、ログインするとEthanが登場しました。

ログインした方のキャラクターをキーボードの移動キーで動かし移動させた後、もう一方の方も同じ部屋にログインします。

最初にログインしたアプリケーションの方に別のキャラクターが登場しました!

これでマルチプレイが出来る!と単純にいけばいいんですが、最初のアプリケーションの方でキャラクターを動かすと後から登場した別のプレイヤーキャラクターも一緒に動いてしまいます。

これは自身のアプリケーションに他のキャラクターは登場したんですが、このキャラクターも自身のキャラクターと同じように移動させるCharaスクリプト等が設定されている為です。

また最初のアプリケーションでキャラを動かした後に後で起動したアプリケーションの方を見るとキャラクターが動いていません。

これは他のキャラクターのデータが自身のアプリケーションにいる他のキャラクターにシンクロしてデータを渡していないからです。

自分のキャラクター以外は動かさないようにする

自身のキャラクターと同様、他のプレイヤーのキャラクターもCharaスクリプトを持っているので一緒に動いてしまいます。

そこで自身のキャラクター以外は操作出来ないようにキャラクター操作スクリプト等を無効化させます。

EthanにNetworkPlayerCheckというスクリプトを作成し取りつけます。

NetworkPlayerCheckはPhoton.MonoBehaviourを継承して作成します。

photonView.isMineでPhotonViewが自身のものかどうかを判定し、違う場合はCharaスクリプト、ProcessAttack、Attackなど自分のキャラクター以外の操作はいらないので無効化しておきます。

これでキャラクターを操作した時に他のキャラクターが一緒に動く事はなくなります。

他のプレイヤーのデータをシンクロさせる

他のプレイヤーがキャラクターを動かした時に自分のアプリケーション内にいる他のキャラクターが動くようにします。

これをするにはキャラクターに取り付けたPhotonViewのObserved Componentsにシンクロ(同期)させるコンポーネントを設定します。

とりあえず移動値だけを反映させてみましょう。

EthanのPhotonViewのObserved Componentsに自身のTransformをドラッグ&ドロップします。

Observed ComponentsにTransformを設定

↑のように設定したらEthanのインスペクタのApplyを押しプレハブに反映し、Ethanを非表示にしておきます。

他キャラクターの移動値がシンクロするか確認する

それでは2つアプリケーションを起動しお互いのキャラクターを操作した時に相手方にいる自分のキャラクターが動くかどうか確認しましょう。

自身のキャラクターを動かすと相手方のアプリケーションでもキャラクターが移動しているのが確認出来ます。

しかし今回Observed Componentsに設定したのはTransformコンポーネントだけなので同期するのは移動値だけです。

その為、攻撃したり歩くアニメーションになったりということは同期されていません。

他キャラクターの移動値やアニメーションをスクリプトで同期させる

Observed Componentsに指定出来るのはコンポーネントなのでスクリプトも同期させる事が出来ます。

そこでキャラクターの移動値やアニメーションのフラグ等をスクリプトで同期させるようにします。

NetworkPlayerCheckスクリプトに追記していきます。

Startメソッド内で自身のキャラクターでなかったらコルーチンを使ってUpdateMoveメソッドを呼びます。

キャラクターの位置や回転を現在の値からデータとして受け取った値にLerpを使って徐々に変更します。

またアニメーションの遷移条件も受け取りアニメーション遷移もさせるようにします。

Observed Componentに設定したスクリプトではOnPhotonSerializeViewメソッドが呼ばれます。

データが読み込みであればそのstream.ReceiveNextでデータを受け取りデータのキャストをした後に変数に入れています。

データの書き込みであれば現在の位置や回転、アニメーションの操作値をSendNextを使ってデータとして送ります。

読み込みと書き込みのデータの順番は統一しておく必要があります。

これでデータの同期も出来ました。

他のキャラクターが同期されるか確認する

アプリケーションを2つ実行し、同じ部屋に入室させてください。

片方のキャラクターを移動させたり攻撃ボタンを押すともう一方のアプリケーションで他のキャラクターが同期して動いているのが確認出来ると思います。

あ・・・すでにキャラクター名が表示されてしまってますが、これは次回やる予定なので無視してください。

終わりに

いやぁとうとう他のキャラクターの同期まで出来ましたね!

こんなに簡単にマルチプレイが実現出来るようになってるんですねぇ、すごいです。

と言ってもやっぱり難しいですが・・・・(^_^;)

慣れれば当たり前になっていくんでしょうね・・・・・・(-_-)

次回はプレイヤー毎に名前を表示したり、敵を攻撃して他のキャラクターと敵の情報を共有させていきます。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます

コメント

  1. 匿名 より:

    すみません、Photon上のカメラの動きについての記事もやっていただきたいんです。

    今はTPS形式の球体座標でカメラを動かしているんですが、Photon上だと上手くいきません。

    Cameraプレファブにはターゲットとなるオブジェクトを設定してそれを中心に公転するように、Playerプレファブにはカメラを設定してそのカメラに合わせた動きをするようにプログラムを組んでいます。

    Player、CameraをInstantiateする時に一緒にそれぞれターゲット、カメラを設定するように組んではいるんですが、何故か後から入ってきたプレイヤーにカメラを持っていかれます。
    それでかれこれ3日は悩んでいるので記事を書いて頂ければ、と思います。

    長文での質問、失礼しました。

    • 細かい所がわからないんですが、カメラは操作しているプレイヤーキャラクターを中心に回転するということでカメラのターゲットは他のキャラや敵キャラをターゲットにすることはないんでしょうか?

      つまり自分専用のカメラがひとつなのか?という点。

      カメラはプレハブ化してネットワーク上に登場させているという感じになっているんですが(もしくはローカル上でインスタンス化している?)、
      カメラをキャラクターの子要素に配置してローカル座標で操作して回転させてはどうでしょうか?

      カメラは他のネットワークキャラクターが使わないと思うのでローカル上でインスタンス化するというのはどうでしょう?

      カメラをインスタンス化して操作キャラクターをターゲットにして他のネットワークキャラクターをターゲットしないような機能でいいのであれば作ってみますが。

      • 匿名 より:

        お願いします。

        カメラをキャラクターの子要素にして、とのことですがそれも試してみたんです。
        ですからこの前、「子要素が親の影響を受けないようにするにはどうすれば良いのか」を質問させて頂きました。
        ですが結局、オンライン上では上手くいかず…。

        ローカル上で、というのも同じでオンライン上にはプレイヤーが沢山いるわけですから…どうやって自キャラをカメラターゲットにすればいいのか、すらも思いつかずで…。
        自分の技術が無いだけだと思いますが…。

        ですので先程の機能を作って頂けると嬉しいです。

        • 子要素の移動に関してはlocalPositionやlocalRotationを使えば移動出来ます。
          親要素の移動で子要素が移動しないようにしたいのかと勘違いしてました。

          まぁそれはおいておきまして。

          カメラが他のキャラクターに持っていかれるというのはおそらくネットワーク上にキャラクターをインスタンス化した時に毎回カメラのターゲットにそのキャラクターを設定している為だと思います。

          なのでターゲットを設定する時に自身がインスタンス化したキャラなのか他のプレイヤーがインスタンス化したキャラなのか判断してターゲットを設定してあげればいいと思います。

          カメラをインスタンス化してやると解り辛くなるので最初からあるMain Cameraを使ってサンプルを作成してみました。

          カメラをキャラクターを支点に回転させる機能は

          http://gametukurikata.com/program/mousecharacter

          を使います。

          スクリプト名はMouseRotateですね。

          これをMain Cameraに設定します。

          そのスクリプトの中でplayerPositionというTransform型の変数を宣言しておりインスペクタで操作キャラクターを設定しそのキャラクターを追いかけたり視点を変更させたりします。

          自身の操作キャラクターもあとからネットワーク上にインスタンス化するので最初は何も設定しません。

          なのでスクリプトを変更してplayerPositionに何も設定されていない時はカメラの回転等を行わないように修正する必要があります。

          次に自身のキャラクターを動かした時に他のキャラクターを動かさないようにするスクリプトがあると思いますが、

          例えばこのページの記事のNetworkPlayerCheckスクリプトのStartメソッドの中です。

          ここでカメラのターゲットを設定すればいいと思います。

          if (!photonView.isMine) {

          の部分で自身のキャラクター以外だったらコンポーネントの無効化等をしていますが、elseの所でカメラのターゲットに自身のゲームオブジェクトのTransformを設定します。

          こうすればネットワーク上にキャラクターが登場した時に自分の操作キャラクターなのか他の人の操作キャラクターなのかを判断し、自分の操作キャラクターだった時はカメラのターゲットにTransformを指定します。

          これで他のキャラクターをネットワーク上に登場させた時はカメラのターゲットは設定しないので大丈夫だと思います。

          Youtubeにサンプルを載せました。

          https://youtu.be/N4Y-555_fx4

          カメラは自身のキャラクターのみを写すようになりました。

  2. 匿名 より:

    ありがとうございます!
    上手くいきました!