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

Unity第三人称射击游戏RayCast空引用错误排查求助

第三人称射击游戏射线功能空引用错误排查与修复

问题详情

开发第三人称射击游戏时,实现从屏幕中心发射射线并以小球标记落点的功能,持续触发Object reference is not set to an instance of an object错误,报错代码行:Ray ray = cam.ScreenPointToRay(screenCenterPoint)。尝试替换为Camera.main.ScreenPointToRay后,问题仍未解决。

问题代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class Camera : MonoBehaviour
{
    public Transform orientation;
    public Transform player;
    public Transform playerObj;
    public Rigidbody rb;
    public float rotationSpeed;
    [SerializeField] private LayerMask aimColliderLayerMask = new LayerMask();
    [SerializeField] private Transform debugTransform;
    public CameraStyle currentStyle;
    UnityEngine.Camera cam;
    public Transform CombatLookAt;
    public enum CameraStyle
    {
        Basic,
        Combat
    }
    void Start()
    {
        currentStyle = CameraStyle.Combat;
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
        
    }

    // Update is called once per frame
    void Update()
    {

        Vector3 viewDir = player.position - new Vector3(transform.position.x, player.position.y, transform.position.z);
        orientation.forward = viewDir.normalized;


        if (currentStyle == CameraStyle.Basic)
        {
            float horizontalInput = Input.GetAxis("Horizontal");
            float verticalInput = Input.GetAxis("Vertical");
            Vector3 inputDir = orientation.forward * verticalInput + orientation.right * horizontalInput;


            if (inputDir != Vector3.zero)
            {
                playerObj.forward = Vector3.Slerp(playerObj.forward, inputDir.normalized, Time.deltaTime * rotationSpeed);
            }
        }
        else if (currentStyle == CameraStyle.Combat)
        {
            Vector3 dirToCombatLookAt = CombatLookAt.position - new Vector3(transform.position.x, CombatLookAt.position.y, transform.position.z);
            orientation.forward = dirToCombatLookAt.normalized;
            playerObj.forward = dirToCombatLookAt.normalized;
        }
        Vector2 screenCenterPoint = new Vector2(Screen.width / 2, Screen.height / 2);
        Ray ray = cam.ScreenPointToRay(screenCenterPoint);
        if(Physics.Raycast(ray, out RaycastHit raycastHit, 999f, aimColliderLayerMask))
        {
            transform.position = raycastHit.point;
            debugTransform.position = raycastHit.point;
        }
    } 
}

解决方案

核心原因

  1. 代码中声明的cam字段未初始化,调用其方法时触发空引用。
  2. 使用Camera.main时,场景中可能没有Camera标记为MainCamera,或存在多个标记为MainCamera的相机,导致无法正确获取。

修复方案

方案1:初始化cam字段

在Start()方法中添加代码,获取当前脚本挂载对象上的Camera组件:

void Start()
{
    currentStyle = CameraStyle.Combat;
    Cursor.lockState = CursorLockMode.Locked;
    Cursor.visible = false;
    // 初始化相机引用
    cam = GetComponent<UnityEngine.Camera>();
}

方案2:确保Camera.main有效

  • 打开场景中的相机对象,在Inspector面板的Tag下拉菜单选择MainCamera,且保证场景中仅有一个相机使用该标签。
  • 若使用Cinemachine虚拟相机,可直接获取CinemachineBrain的输出相机:
// 先在脚本中添加字段
[SerializeField] private CinemachineBrain cinemachineBrain;

void Start()
{
    currentStyle = CameraStyle.Combat;
    Cursor.lockState = CursorLockMode.Locked;
    Cursor.visible = false;
    // 获取Cinemachine输出的相机
    cam = cinemachineBrain.OutputCamera;
}

额外优化建议

  • 脚本命名冲突:当前脚本名为Camera,与Unity内置类重名,建议改为CameraController或其他名称,避免潜在的命名混淆。
  • 检查debugTransform是否已在Inspector面板赋值,防止后续出现新的空引用错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:23:13