You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Photon PUN多人FPS游戏Missing Reference Exception问题求助

基于Photon PUN的多人FPS游戏Missing Reference Exception问题解决

问题描述

开发基于Photon PUN的多人FPS游戏时,单人房间运行无报错,但其他玩家加入后,代码在Physics.Raycast(playerCam.position, playerCam.forward, out hit, range)行抛出Missing Reference Exception,错误提示为“你正在访问的transform已被销毁”。已确认playerCam不为空,但问题仍未解决。

相关代码

Shoot协程代码

private IEnumerator Shoot()
{
    ammoLeft -= 1;

    animator.SetBool("fire", true);

    RaycastHit hit;
    if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, range))
    {
        // Missing Reference Expection The transform you are accessing is destroyed
        // 单人模式下正常运行
        if (hit.transform.tag == "Player" && hit.transform != null)
        {
            HealthManager HealthScript = hit.transform.gameObject.GetComponent<HealthManager>();

            if (HealthScript != null)
            {
                HealthScript.TakeDamage(damage);
            }
        }

    }

    yield return new WaitForSeconds(0.3f);

    animator.SetBool("fire", false);

    if (ammoLeft <= 0f)
    {
        StartCoroutine("Reload");
    }
}

Awake方法代码

private void Awake()
{
    if (!pv.IsMine)
    {
        Destroy(ui);
    }

    if (playerCam == null)
    {
        playerCam = FindObjectOfType<Camera>().transform;
    }

    ammoLeft = magazineSize;
    animator = GetComponent<Animator>();
}

问题分析与解决

1. 修正PlayerCam的获取逻辑

FindObjectOfType<Camera>()会遍历场景中所有激活状态的Camera,当其他玩家加入后,可能误获取到其他玩家的Camera(而其他玩家的Camera可能在本地被禁用/销毁)。建议:

  • 给本地玩家的Camera添加MainCamera标签,改用Camera.main.transform获取,确保只拿到自己的主相机:
if (playerCam == null)
{
    playerCam = Camera.main.transform;
}
  • 或者在本地玩家对象的子节点挂载专属Camera,通过GetComponentInChildren<Camera>()获取,避免跨对象查找。

2. 确保射击逻辑仅在本地玩家对象执行

Photon中,只有本地玩家的对象应该处理输入和射击逻辑,避免其他玩家的对象在本地执行无效代码。在启动Shoot协程前添加判断:

// 调用Shoot的地方增加校验
if (pv.IsMine)
{
    StartCoroutine(Shoot());
}

3. 安全访问Raycast命中对象

报错提示“transform已销毁”,实际可能是命中的对象已被销毁,但hit.transform仍残留无效引用。访问前先检查hit.collider是否存在(对象销毁后collider会被移除),并调整判断顺序:

if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, range))
{
    // 先检查collider有效性,再判断标签
    if (hit.collider != null && hit.collider.CompareTag("Player"))
    {
        HealthManager healthScript = hit.collider.GetComponent<HealthManager>();
        if (healthScript != null)
        {
            healthScript.TakeDamage(damage);
        }
    }
}

4. 检查其他玩家对象的销毁逻辑

在Awake中仅销毁非本地玩家的UI组件,不要销毁对象本身或其核心组件(如Transform、Camera)。其他玩家的对象需要保留以同步网络状态,销毁核心组件会导致引用失效。

内容的提问来源于stack exchange,提问作者Malay Joshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 18:35:28