Photon RPC传GameObject报Custom type not found错误
问题背景
使用Photon PUN进行Unity多人联机开发时,碰撞触发逻辑中调用RPC传入GameObject参数,运行时抛出序列化异常。
原实现代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using Photon.Realtime; public class FinishManager : MonoBehaviour { private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.CompareTag("Legs")) { collision.gameObject.GetComponent<PhotonView>().RPC("Win", RpcTarget.All, collision.gameObject); /*报错行*/ } } [PunRPC] public void Win(GameObject player) { PhotonNetwork.Destroy(player); } }
核心报错
Exception: Write failed. Custom type not found: UnityEngine.GameObject
错误栈最终指向RPC调用行,传入collision.gameObject参数时触发序列化失败。
问题原因
Photon PUN的RPC参数传输依赖内置序列化规则,默认不支持直接传递UnityEngine.GameObject类型,协议层无法识别该类型的序列化/反序列化逻辑,因此写入网络流时直接抛出异常。
另外原代码还存在隐藏逻辑问题:调用的是碰撞到的Legs物体挂载的PhotonView发RPC,但Win方法定义在FinishManager组件上,如果Legs物体未挂载FinishManager,就算序列化正常也会触发“找不到目标RPC方法”的错误。
修复方案
所有Photon网络物体上的PhotonView都有全局唯一、全客户端同步的ViewID(int类型,属于Photon原生支持序列化的基础类型),不需要传递GameObject实例,传递ViewID即可在所有客户端定位到目标物体。
修正后可直接运行的代码:
using UnityEngine; using Photon.Pun; public class FinishManager : MonoBehaviourPun { private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.CompareTag("Legs")) { PhotonView targetPhotonView = collision.gameObject.GetComponent<PhotonView>(); // 传递int类型的ViewID,无序列化问题 photonView.RPC("Win", RpcTarget.All, targetPhotonView.ViewID); } } [PunRPC] public void Win(int targetViewID) { // 所有客户端通过统一的ViewID找到对应网络物体 PhotonView targetView = PhotonNetwork.GetPhotonView(targetViewID); if (targetView != null) { PhotonNetwork.Destroy(targetView.gameObject); } } }
额外注意事项
- Photon RPC原生支持传参类型仅包含基础值类型(int/float/bool/string等)、Unity常用值类型(Vector2/Vector3/Quaternion等)、Photon内置类型(Player/PhotonView等),不要直接传GameObject、Transform、自定义类实例作为参数,除非你手动注册了对应类型的自定义序列化规则。
- 调用RPC时,要确保调用RPC的
PhotonView所在物体上,挂载了包含目标[PunRPC]方法的组件,否则会找不到RPC入口。 - 网络物体的销毁必须通过
PhotonNetwork.Destroy调用,不能直接用Destroy,否则无法同步销毁状态到所有客户端。
内容的提问来源于stack exchange,提问作者Bekranker
相关产品推荐
相关产品推荐

