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

Unity Photon多人游戏:非房主重连触发空引用异常

问题原因分析

异常发生在PlayerMovement.Start()方法第22行,对应代码m_camera.enabled = false;,核心原因是非房主玩家的m_camera字段未被初始化,导致空引用:

  • 你没有在代码中给m_camera赋值的逻辑(既没有在Inspector面板绑定,也没有通过代码查找);
  • 非房主玩家重新加入时,其玩家对象的m_camera为null,直接访问enabled属性触发NullReferenceException。

另外,你的摇杆查找逻辑存在性能问题:FixedUpdate中每帧调用GameObject.FindGameObjectWithTag会消耗大量性能,且同样存在找不到摇杆导致空引用的风险。

解决方案

1. 修复相机空引用问题

两种可选方式:

  • 方式一:Inspector绑定:在Unity编辑器中,将玩家对象的相机组件拖拽到PlayerMovement脚本的m_camera字段上;
  • 方式二:代码自动查找:在Start方法中通过GetComponentInChildren获取子物体上的相机,并添加空判断避免异常。

2. 优化摇杆查找逻辑

将摇杆查找从FixedUpdate移到Start,并添加空判断;推荐将MovementJoystick改为单例模式,进一步提升可靠性和性能。

3. 非本地玩家相机优化(可选)

生成玩家对象时,仅给本地玩家(PhotonView.IsMine为true)添加相机组件,非本地玩家直接不挂载相机,从根源避免空引用。

修改后的代码示例

PlayerMovement.cs

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

public class PlayerMovement : MonoBehaviour
{
    public MovementJoystick movementJoystick;
    public float playerSpeed;
    private Rigidbody2D rb;
    public Camera m_camera;
    PhotonView view;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        view = GetComponent<PhotonView>();
        
        // 自动查找子物体中的相机
        m_camera = GetComponentInChildren<Camera>();
        
        // 仅在Start中查找一次摇杆,添加空判断
        var joystickObj = GameObject.FindGameObjectWithTag("JoyStick");
        if (joystickObj != null)
        {
            movementJoystick = joystickObj.GetComponent<MovementJoystick>();
        }

        if (!view.IsMine)
        {
            // 空判断避免异常
            if (m_camera != null)
            {
                m_camera.enabled = false;
            }
        }
    }

    void FixedUpdate()
    {
        // 仅本地玩家执行移动,且确保摇杆不为空
        if(view.IsMine && movementJoystick != null)
        {
            rb.velocity = movementJoystick.joystickVec.y != 0 
                ? new Vector2(movementJoystick.joystickVec.x * playerSpeed, movementJoystick.joystickVec.y * playerSpeed) 
                : Vector2.zero;
        }
    }
}

可选:MovementJoystick单例改造

public class MovementJoystick : MonoBehaviour
{
    public static MovementJoystick Instance;
    public Vector2 joystickVec;

    void Awake()
    {
        Instance = this;
    }

    // 原有摇杆逻辑...
}

之后在PlayerMovement中直接通过MovementJoystick.Instance获取摇杆,无需再用FindGameObjectWithTag。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 14:27:59