Unity调试模式下Camera.main有值却抛出NullReferenceException如何解决
问题根因
触发空引用异常的原因和Camera.main无关:你声明的Transform _targetPos字段从未完成初始化赋值,直接访问_targetPos.position时,_targetPos本身就是null,必然抛出空引用错误。
调试时看到的返回值存在,仅代表ScreenToWorldPoint的计算结果有效,不代表你要写入position属性的_targetPos对象实例存在。
修复方案
你不需要专门声明Transform类型的字段来存储鼠标世界坐标,直接用值类型的临时变量接收计算结果即可,从根源上规避引用类型未初始化的问题,修改SetBulletRotation方法代码如下:
protected virtual void SetBulletRotation() { // 用Vector3临时变量接收坐标转换结果,无需依赖未赋值的Transform引用 Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10.0f)); _destPos = (mouseWorldPos - transform.position).normalized; State = EnumList.CreatureState.Move; float angle = Mathf.Atan2(_destPos.y, _destPos.x) * Mathf.Rad2Deg; transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward); }
如果你确实需要保留_targetPos字段持有目标点引用,必须在调用SetBulletRotation之前完成字段赋值,可选初始化方式:
- 在场景中提前创建专门的空物体作为目标点,在
Init方法中赋值:_targetPos = GameObject.Find("目标点物体名称").transform; - 运行时动态创建目标点对象再赋值:
_targetPos = new GameObject("BulletTarget").transform;
额外优化建议
- 注意生命周期执行顺序:
OnEnable的执行时机早于多数自定义初始化方法,如果子弹是通过对象池复用取出,OnEnable触发时Init可能还未执行,会重复触发空引用,优先使用上面的临时变量方案可以彻底规避时序问题。 Camera.main本质是通过Tag查找场景对象,频繁调用会产生不必要的性能开销,建议在初始化阶段缓存主相机的引用,避免每次生成子弹、每帧更新时重复查找。
内容的提问来源于stack exchange,提问作者Namk0207
相关产品推荐
相关产品推荐

