Unity C#とPUN2でオンラインゲームを作る方法|Photonの所有権移譲とオブジェクト共有の基本実装

プログラミング

Unityでオンラインゲームを制作する場合、単純なキャラクター移動とは異なり、複数プレイヤー間でオブジェクトの生成や操作権限を正しく管理する必要があります。特にPhoton Unity Networking 2(PUN2)では、ネットワーク上のオブジェクト所有者を制御する仕組みを理解することが重要です。

プレイヤーごとに操作するキャラクターを生成したり、既存オブジェクトの一部だけ操作権限を渡したりする場合は、PhotonViewの所有権管理を利用します。ここでは、ボタンによる参加処理や子オブジェクトの操作権移譲を行う基本的な考え方と実装例を紹介します。

PUN2でオンラインオブジェクトを管理する基本

PUN2では、ネットワーク上に存在するゲームオブジェクトにはPhotonViewというコンポーネントを追加します。PhotonViewは、そのオブジェクトを誰が所有しているか、どのクライアントが操作できるかを管理する役割を持っています。

例えば、プレイヤーAが生成した人間オブジェクトは基本的にプレイヤーAが所有します。そのため、プレイヤーBが同じオブジェクトを操作したい場合は、OwnershipTransfer(所有権移譲)の処理が必要になります。

また、親オブジェクトと子オブジェクトで別々に操作権限を持たせたい場合は、それぞれにPhotonViewを設定する必要があります。

ボタン1で自分のキャラクターを生成する処理

最初のプレイヤーがボタン1を押した場合、自分専用の人間オブジェクトをネットワーク上に生成します。PUN2ではPhotonNetwork.Instantiateを利用して生成します。

例えば以下のような処理になります。

using Photon.Pun;
using UnityEngine;

public class PlayerSpawner : MonoBehaviourPunCallbacks
{
    public GameObject playerPrefab;

    public void CreatePlayer()
    {
        PhotonNetwork.Instantiate(playerPrefab.name, Vector3.zero, Quaternion.identity);
    }
}

この方法で生成されたオブジェクトには、自動的に生成したプレイヤーのPhotonView所有権が設定されます。

自分のオブジェクトだけを操作する移動処理

オンラインゲームでは、自分が所有していないオブジェクトを勝手に動かさないように制御します。

PhotonViewのIsMineを確認することで、現在操作可能なプレイヤーだけが入力処理を実行できます。

using Photon.Pun;
using UnityEngine;

public class PlayerMove : MonoBehaviourPun
{
    public float speed = 5f;

    void Update()
    {
        if (!photonView.IsMine)
            return;

        float x = Input.GetAxis("Horizontal");
        transform.Translate(Vector3.right * x * speed * Time.deltaTime);
    }
}

このようにすると、生成した本人だけがAキーやSキーなどの入力でキャラクターを操作できます。

既存オブジェクトの所有権を別プレイヤーへ渡す方法

PUN2では、PhotonView.TransferOwnershipを使うことで、他プレイヤーへ操作権限を渡すことができます。

例えばボタン2を押したプレイヤーが、ボールオブジェクトの操作権を取得する場合は、対象のPhotonViewに対して所有権移譲を行います。

using Photon.Pun;

public class OwnershipChanger : MonoBehaviourPun
{
    public void GetOwnership()
    {
        photonView.RequestOwnership();
    }
}

ただし、所有権移譲を使用する場合はPhotonViewのOwnership Transfer設定を変更しておく必要があります。

子オブジェクトだけを操作可能にする設計方法

質問のように、人間オブジェクトはプレイヤーAが所有したまま、子オブジェクトのボールだけをプレイヤーBが操作する場合は、親と子を別管理する設計がおすすめです。

具体的には、人間オブジェクトにはプレイヤー制御用のPhotonViewを設定し、ボールオブジェクトには別のPhotonViewを設定します。

オブジェクト 役割 所有者
人間オブジェクト キャラクター本体 ボタン1を押したプレイヤー
ボールオブジェクト 特殊操作対象 所有権を取得したプレイヤー

この構造にすると、キャラクターを作成したプレイヤーと、ボールを操作するプレイヤーを分けることができます。

PUN2で入力を分けるサンプル実装

操作するオブジェクトによって入力キーを変える場合も、所有権チェックを利用します。

using Photon.Pun;
using UnityEngine;

public class BallMove : MonoBehaviourPun
{
    public float speed = 5f;

    void Update()
    {
        if (!photonView.IsMine)
            return;

        if(Input.GetKey(KeyCode.Z))
        {
            transform.Translate(Vector3.left * speed * Time.deltaTime);
        }

        if(Input.GetKey(KeyCode.X))
        {
            transform.Translate(Vector3.right * speed * Time.deltaTime);
        }
    }
}

このようにボール側のPhotonView所有者だけがZ・Xキーで操作できるようになります。

オンラインゲーム制作で注意したいポイント

PUN2では所有権を渡しただけでは、位置情報が自動同期されない場合があります。移動するオブジェクトにはPhotonTransformViewなどの同期コンポーネントを追加する必要があります。

また、所有権移譲を頻繁に行うゲームでは、複数人が同時に操作権を要求した場合の処理も考える必要があります。

例えば対戦ゲームの場合、ボールを奪い合う処理では所有権の取得タイミングを制御しないと、プレイヤー間で表示がずれる原因になります。

まとめ

UnityとPUN2でプレイヤーごとに異なる操作を行うオンラインゲームを作る場合、重要なのはPhotonViewによる所有権管理です。

キャラクター生成はPhotonNetwork.Instantiate、操作制御はphotonView.IsMine、別プレイヤーへの操作権移譲はRequestOwnershipやTransferOwnershipを利用することで実現できます。

人間オブジェクトとボールオブジェクトを別々のネットワークオブジェクトとして管理すると、片方だけ操作権を渡すような複雑なオンラインゲームも作りやすくなります。

コメント

タイトルとURLをコピーしました