为何带NavMeshAgent的射线点击移动脚本报NullReferenceException?
问题概况
- 运行教程复制的脚本时,右键点击控制物体移动,控制台持续抛出
NullReferenceException: Object reference not set to an instance of an object。 - 已确认挂载脚本的物体带有NavMeshAgent组件,但脚本无法获取到该组件的有效引用。
- 核心诉求:排查组件存在但引用为空的原因,而非了解NullReferenceException的定义。
- 补充:物体未按预期移动到点击点,已尝试序列化字段、
this.gameObject.GetComponent<NavMeshAgent>(),问题未解决。
(图片说明:NavMeshAgent组件挂载在脚本所在的GameObject上)
原脚本代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class CharacterMovement : MonoBehaviour { NavMeshAgent agent; public float rotateSpeedMovement; float rotateVelocity; // Start is called before the first frame update void Start() { agent = gameObject.GetComponent<NavMeshAgent>(); } // Update is called once per frame void Update() { //When pressing RMB if(Input.GetMouseButtonDown(1)){ RaycastHit hit; //Checking if raycast has hit the navmesh system if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit, Mathf.Infinity)){ //have the player move to the point agent.SetDestination(hit.point); //ROTATION Quaternion rotationToLookAt = Quaternion.LookRotation(hit.point - transform.position); float rotationY = Mathf.SmoothDampAngle(transform.eulerAngles.y, rotationToLookAt.eulerAngles.y, ref rotateVelocity, rotateSpeedMovement * (Time.deltaTime * 5)); transform.eulerAngles = new Vector3 (0,rotationY,0); } } } }
可能的原因及解决步骤
脚本执行顺序异常
- 问题:CharacterMovement的
Start()方法在NavMeshAgent组件初始化前执行,导致获取不到组件。 - 解决:
- 打开
Project Settings > Script Execution Order,将CharacterMovement的执行顺序调整到NavMeshAgent之后; - 或者把获取组件的代码移到
Awake()中(Awake在组件初始化阶段运行,比Start更早)。
- 打开
- 问题:CharacterMovement的
组件/物体未激活
- 问题:NavMeshAgent组件被禁用(面板复选框未勾选),或脚本所在物体在
Start()执行时处于非激活状态(SetActive(false))。 - 解决:确保NavMeshAgent组件启用,且物体在场景启动时为激活状态。
- 问题:NavMeshAgent组件被禁用(面板复选框未勾选),或脚本所在物体在
组件不在当前物体上
- 问题:NavMeshAgent挂载在脚本物体的子物体上,而
GetComponent<NavMeshAgent>()只会查找当前物体的组件。 - 解决:
- 改用
GetComponentInChildren<NavMeshAgent>()(查找自身及所有子物体); - 或者将NavMeshAgent组件移到脚本所在的GameObject上。
- 改用
- 问题:NavMeshAgent挂载在脚本物体的子物体上,而
脚本重复挂载到无组件物体
- 问题:Hierarchy中有多个物体挂载了CharacterMovement脚本,其中某个物体没有NavMeshAgent,右键点击时触发了该脚本的代码。
- 解决:
- 在Hierarchy搜索CharacterMovement,确认所有挂载该脚本的物体都带有NavMeshAgent;
- 给脚本添加
[RequireComponent(typeof(NavMeshAgent))]特性,强制Unity自动为挂载脚本的物体添加NavMeshAgent(无组件时)。
组件被其他脚本销毁/移除
- 问题:其他脚本在
Start()之后、右键点击前,通过Destroy()或RemoveComponent()移除了NavMeshAgent。 - 解决:搜索项目中操作NavMeshAgent的代码,排查是否有意外销毁/移除组件的逻辑。
- 问题:其他脚本在
优化后的示例脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; // 强制挂载脚本时自动添加NavMeshAgent组件 [RequireComponent(typeof(NavMeshAgent))] public class CharacterMovement : MonoBehaviour { // 序列化字段允许直接在Inspector赋值,避免GetComponent的潜在问题 [SerializeField] NavMeshAgent agent; public float rotateSpeedMovement; float rotateVelocity; void Awake() { // 双重保险:如果Inspector未赋值,自动获取组件 if (agent == null) { agent = GetComponent<NavMeshAgent>(); } } void Update() { if(Input.GetMouseButtonDown(1)){ RaycastHit hit; if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit, Mathf.Infinity)){ // 先判断agent是否为空,避免触发异常 if (agent != null) { agent.SetDestination(hit.point); } Quaternion rotationToLookAt = Quaternion.LookRotation(hit.point - transform.position); float rotationY = Mathf.SmoothDampAngle(transform.eulerAngles.y, rotationToLookAt.eulerAngles.y, ref rotateVelocity, rotateSpeedMovement * (Time.deltaTime * 5)); transform.eulerAngles = new Vector3 (0,rotationY,0); } } } }
内容的提问来源于stack exchange,提问作者Tristan Littlewood
相关产品推荐
相关产品推荐

