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

Unity通过命令调用器执行画线命令时出现Camera空引用异常

问题解决:Unity命令模式调用画线时的NullReferenceException异常

核心问题分析

你遇到的异常根源是DrawLineCommand的MyLine字段未正确赋值:直接调用命令时你手动给MyLine赋了有效引用,但通过CommandInvoker调用时遗漏了这一步,导致Execute()中调用MyLine.InitLine()触发空引用。同时Line类的Update方法存在未判空的潜在问题,让你误以为是Camera的异常。

分步修复方案

1. 修复DrawLineCommand的参数传递

修改DrawLineCommand.cs,通过构造函数强制传入Line实例,从根源避免空引用:

using UnityEngine;

public class DrawLineCommand : ICommand
{
    private readonly Line _myLine;

    // 构造函数接收Line实例,确保引用有效
    public DrawLineCommand(Line line)
    {
        _myLine = line;
        Debug.Log("Draw Line Command initialized");
    }

    public void Execute()
    {
        Debug.Log("Executing line command");        
        if (_myLine == null)
        {
            Debug.LogError("Line reference is null in DrawLineCommand");
            return;
        }
        _myLine.InitLine();
    }
}

2. 正确添加命令到调用器

在添加命令时,必须传入场景中已存在的Line组件实例:

// 在任意脚本的Start/Init方法中添加命令
void Start()
{
    // 获取场景中已挂载的Line组件
    Line lineComponent = FindObjectOfType<Line>();
    if (lineComponent != null)
    {
        CommandInvoker.AddCommand(new DrawLineCommand(lineComponent));
    }
    else
    {
        Debug.LogError("场景中未找到Line组件");
    }
}

3. 修复Line类的潜在异常点

修改Line.cs,补充判空逻辑并移除不必要的try-catch:

using System.Collections.Generic;
using UnityEngine;

public class Line : MonoBehaviour
{
    private LineRenderer _lRenderer;
    private List<Vector3> _Vertices = new List<Vector3>();
    public Material material;

    private void Start()
    {
        InitLine();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 先验证Camera.main有效性
            if (Camera.main == null)
            {
                Debug.LogError("未找到标记为MainCamera的相机");
                return;
            }
            
            Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(camRay, out RaycastHit hit))
            {
                Renderer hitRenderer = hit.transform.GetComponent<Renderer>();
                // 判空后再访问name属性
                if (hitRenderer != null && hitRenderer.name == "MyGround")
                {
                    Debug.Log("点击了地面");
                    // 仅编辑器模式下使用弹窗,避免打包报错
                    #if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayDialog("提示", "点击了MyGround", "确定");
                    #endif
                }
            }
        }
    }

    public void InitLine()
    {
        _lRenderer = GetComponent<LineRenderer>();
        // 自动添加缺失的LineRenderer组件
        if (_lRenderer == null)
        {
            Debug.LogWarning("Line组件缺少LineRenderer,自动添加");
            _lRenderer = gameObject.AddComponent<LineRenderer>();
        }

        _lRenderer.positionCount = 0;
        _lRenderer.startWidth = 0.15f;
        _lRenderer.endWidth = 0.15f;
        _lRenderer.useWorldSpace = true;
        _lRenderer.numCapVertices = 50;
        // 赋值材质(如果已设置)
        if (material != null)
        {
            _lRenderer.material = material;
        }
    }
}

4. 验证Camera设置

确保场景中的相机Tag已设置为MainCamera:
选中相机对象,在Inspector面板的Tag下拉框中选择"MainCamera",确保Camera.main能正确获取到相机实例。

额外注意事项

  • 避免在非编辑器环境下使用UnityEditor.EditorUtility类,否则打包后会报错。
  • 静态队列CommandBuffer在场景切换时不会自动清空,若需要可在OnDestroy中添加清空逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:18:10