Unity C#:仅在Start()外触发NullReferenceException,Raycast行报错求助
你说已经确认enemy是实例化的,每帧打印enemy.groundCheckDistance都能拿到正确数值,但还是在这条Raycast代码触发空引用,这确实有点让人摸不着头脑,咱们一步步排查几个容易忽略的点:
先排查
transform是否意外为空
代码里用到了transform.position,如果这段脚本挂载的GameObject在运行中被销毁,或者有其他代码把transform强行置为null,也会触发空引用。你可以把打印代码改成这样,同时监控transform的状态:Debug.Log($"当前帧transform状态: {transform}, enemy检测距离: {enemy.groundCheckDistance}");看看会不会出现某帧
transform为null的情况。加个即时的
enemy空判断保险
虽然你每帧都打印了enemy的属性,但打印和Raycast执行之间有极短的时间差,如果有其他线程、异步逻辑或者Unity的消息队列在这段时间把enemy置为null,就会出现这种“打印正常但执行报错”的情况。可以在Raycast前加个判断:if (enemy == null) { Debug.LogError("Raycast前enemy突然变成null了!"); return; } RaycastHit hitInfo; if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, enemy.groundCheckDistance)) { // 你的逻辑代码 }这样如果真的出现竞态条件,能立刻捕获到。
检查
enemy.groundCheckDistance的属性实现
你说这是个数值,但如果这个属性的getter方法内部引用了其他可能为空的对象呢?比如enemy类里是这么定义的:public float groundCheckDistance { get { return this.someComponentThatMightBeNull.checkDistance; } }这种情况下,打印的时候如果
someComponentThatMightBeNull刚好不为空,但Raycast执行时它变成null了,就会触发空引用,而且报错堆栈可能会指向你的Raycast行(因为getter是在访问属性时执行的)。你可以去检查enemy类里这个属性的实现,看看有没有依赖其他可能为空的对象。试试显式初始化
hitInfo
虽然Unity的out参数允许传入未初始化的变量,但极端情况下如果hitInfo被其他代码意外赋值为null(比如之前有错误的hitInfo = null;),也可能出问题。可以在Raycast前显式初始化:RaycastHit hitInfo = new RaycastHit(); if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, enemy.groundCheckDistance))最后试试编辑器的常规排查手段
有时候Unity编辑器的缓存会搞出奇怪的问题,你可以:- 重启Unity编辑器
- 删除项目根目录的
Library文件夹,然后重新打开项目让Unity重新导入资源 - 右键点击
Assets文件夹选择Reimport All
内容的提问来源于stack exchange,提问作者Moses

