🗑️

他人の生成したネットワークオブジェクトを削除する(PUN2)

2023/07/04に公開

はじめに

PUN2(Photon Unity Networking 2)において、ネットワークオブジェクトを削除するには通常PhotonNetwork.Destroyを使用します。
ただ、他のプレイヤーが生成したネットワークオブジェクトなど自分が所有権を持たないネットワークオブジェクトは、PhotonNetwork.Destroyだけでは削除できません。所有権を自分に移譲してからPhotonNetwork.Destroyを使用する必要があります。そこで、以下に載せる方法を試しました。

1. ネットワークオブジェクトの所有権オプションの変更

ネットワークオブジェクトにアタッチされているPhotonViewコンポーネントにおいて、Ownership Transferのオプションを変更します。デフォルトではFixedになっていますが、Takeoverに変更します。
Fixedでは、ネットワークオブジェクトの所有権は生成者が常に持ち他のプレイヤーは取得できませんが、Takeoverでは他のプレイヤーも所有権を取得できるようになります。

2. TransferOwnershipを呼び出す

ネットワークオブジェクトを削除したい時に呼び出す関数の中で、TransferOwnershipを呼び出します。これによって、所有権を移譲することができます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;

public class DestroyNetworkObject : MonoBehaviourPunCallbacks
{
    private void DestroyObj(GameObject obj)
    {
        // 引数として渡されたゲームオブジェクトのPhotonViewを取得し
        // その所有権を自分(PhotonNetwork.LocalPlayer)に移譲する
        obj.GetComponent<PhotonView>().TransferOwnership(PhotonNetwork.LocalPlayer);
    }
}

3. 所有権移譲後にネットワークオブジェクトを削除する

所有権の移譲が行われた時に呼ばれるコールバックの中で、ネットワークオブジェクトの削除を行います。
まず、スクリプトにIPunOwnershipCallbacksインターフェースを実装することで、所有権関連のコールバックを受け取ることができます。
次に、IPunOwnershipCallbacks.OnOwnershipTransferedの中に、ネットワークオブジェクトを削除する処理を追加します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;

// IPunOwnershipCallbacksを追加
public class DestroyNetworkObject : MonoBehaviourPunCallbacks, IPunOwnershipCallbacks
{
    private void DestroyObj(GameObject obj)
    {
        obj.GetComponent<PhotonView>().TransferOwnership(PhotonNetwork.LocalPlayer);
    }
    // IPunOwnershipCallbacks.OnOwnershipTransferedを実装
    void IPunOwnershipCallbacks.OnOwnershipTransfered(PhotonView targetView, Player previousOwner) 
    {
        // ネットワークオブジェクトを削除
        PhotonNetwork.Destroy(targetView.gameObject);
    }

    // 以下のメソッドも実装しないとエラーが出る
    void IPunOwnershipCallbacks.OnOwnershipTransferFailed(PhotonView targetView, Player previousOwner)
    {

    }

    void IPunOwnershipCallbacks.OnOwnershipRequest(PhotonView targetView, Player requestingPlayer) 
    {

    }
}

おわりに

以上の方法で、他のプレイヤーが生成したネットワークオブジェクトを削除することができました。
GitHubに、サンプルプロジェクトをアップしました。ランダムな位置に生成されたネットワークオブジェクトをクリックすると削除することができます。
https://github.com/ekito-station/destroy-network-object

GitHubで編集を提案

Discussion