Unity Photon Pun2 硬币收集系统问题:销毁硬币时PhotonView异常
Unity Photon Pun2 硬币收集系统问题解决:销毁硬币但保留PhotonView
问题说明
开发基于Unity Photon Pun2的玩家硬币收集系统,需求为玩家收集足够硬币后生成钥匙。当前遇到核心问题:第一个硬币被销毁时,其附带的PhotonView也被一同销毁,导致收集第二个硬币时触发错误:
Illegal view ID:0 method: CollectCoin GO:Coin (2)
错误原因
当前代码中使用PhotonNetwork.Destroy(gameObject)销毁整个硬币对象,连带销毁了绑定在该对象上的PhotonView。Photon的View ID与对象强绑定,对象销毁后View ID失效,后续对该View ID的RPC调用会触发非法ID错误。此外,未对硬币添加“已收集”标记,可能导致重复触发收集逻辑。
解决方案
核心思路是不销毁整个硬币对象,仅禁用其交互和显示组件,保留PhotonView以维持RPC通信的有效性:
- 添加
isCollected标记,防止硬币被重复触发收集 - 在
DeactivateCoin中禁用碰撞体、渲染组件,而非销毁对象 - 修正玩家硬币收集逻辑的调用链路
修改后的代码
Coin 脚本
using UnityEngine; using Photon.Pun; public class Coin : MonoBehaviourPun { private bool isCollected = false; // 标记硬币是否已被收集 private void OnTriggerEnter2D(Collider2D other) { if (isCollected) return; // 已收集的硬币直接返回,不再响应触发 if (other.gameObject.CompareTag("Player")) { Debug.Log("Player collided with coin"); if (PhotonNetwork.IsMasterClient) { photonView.RPC("CollectCoin", RpcTarget.All, other.gameObject.GetComponent<PhotonView>().ViewID); } } } [PunRPC] public void CollectCoin(int playerViewID) { if (isCollected) return; isCollected = true; // 找到对应的玩家并调用收集方法 CoinCollect playerCoinCollection = PhotonView.Find(playerViewID).gameObject.GetComponent<CoinCollect>(); playerCoinCollection.CollectCoin(); photonView.RPC("DeactivateCoin", RpcTarget.All); } [PunRPC] void DeactivateCoin() { // 禁用碰撞体,防止重复触发 GetComponent<Collider2D>().enabled = false; // 禁用所有渲染组件,隐藏硬币 foreach (Renderer renderer in GetComponentsInChildren<Renderer>()) { renderer.enabled = false; } // 若有粒子特效、动画等组件,可在此一并禁用 } }
CoinCollect 脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; public class CoinCollect : MonoBehaviourPunCallbacks, IPunObservable { public GameObject keyPrefab; private int coinCount; private int playerCount; private int coinsNeeded; void Start() { // 若房间未完全初始化,可改用OnJoinedRoom回调获取玩家数量 playerCount = PhotonNetwork.PlayerList.Length; switch (playerCount) { case 1: coinsNeeded = 1; break; case 2: coinsNeeded = 2; break; case 3: coinsNeeded = 15; break; case 4: coinsNeeded = 20; break; default: Debug.LogError("Unsupported player count: " + playerCount); break; } } // 玩家收集硬币时触发 public void CollectCoin() { coinCount++; CheckCoinCount(); } private void CheckCoinCount() { if (coinCount >= coinsNeeded) { SpawnKey(); } } private void SpawnKey() { PhotonNetwork.Instantiate(keyPrefab.name, new Vector3(0, 0, 0), Quaternion.identity); } public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) { if (stream.IsWriting) { stream.SendNext(coinCount); } else { this.coinCount = (int)stream.ReceiveNext(); } } }
关键修改点
- 添加收集标记:
isCollected变量确保每个硬币仅被处理一次,避免重复RPC调用 - 替换销毁逻辑:将
PhotonNetwork.Destroy(gameObject)改为禁用组件,保留PhotonView的有效性 - 修复调用链路:在
CollectCoin中正确调用玩家的CollectCoin()方法,实现硬币计数累加
内容的提问来源于stack exchange,提问作者Hyera Hyera
相关产品推荐
相关产品推荐

