Unity中NullReferenceException异常排查:炮弹发射功能失效
问题描述
开发Unity游戏炮弹发射功能时,已完成组件配置并编写PlayerAttack与Ammo脚本,代码无语法错误,但运行时抛出NullReferenceException: Object reference not set to an instance of an object异常,按教程步骤操作多次核对仍无法解决。
相关代码
PlayerAttack脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerAttack : MonoBehaviour { private float cooldownTimer = Mathf.Infinity; [SerializeField] private float attackCooldown; [SerializeField] private Transform firePoint; [SerializeField] private GameObject[] fireballs; private Animator anim; private PlayerControllert playerMovement; private void Awake() { anim = GetComponent<Animator>(); playerMovement = GetComponent<PlayerControllert>(); } private void Update() { if(Input.GetMouseButtonDown(0) && cooldownTimer > attackCooldown) { Attack(); } cooldownTimer += Time.deltaTime; } private void Attack() { anim.SetTrigger("attack"); cooldownTimer = 0; fireballs[0].transform.position = firePoint.position; fireballs[0].GetComponent<Ammo>().SetDirection(Mathf.Sign(transform.localScale.x)); } }
Ammo脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ammo : MonoBehaviour { [SerializeField] private float speed; private bool hit; private Animator anim; private BoxCollider2D boxCollider; private float direction; private void Awake() { anim.GetComponent<Animator>(); boxCollider = GetComponent<BoxCollider2D>(); } private void Update() { if (hit) return; float movementSpeed = speed * Time.deltaTime * direction; transform.Translate(movementSpeed, 0, 0); } private void OnTriggerEnter2D(Collider2D collision) { hit = true; boxCollider.enabled = false; anim.SetTrigger("explode"); } public void SetDirection(float _direction) { direction = _direction; gameObject.SetActive(true); hit = false; boxCollider.enabled = true; float localScaleX = transform.localScale.x; if (Mathf.Sign(localScaleX) != _direction) localScaleX = -localScaleX; transform.localScale = new Vector3(localScaleX, transform.localScale.y, transform.localScale.z); } private void Deactivate() { gameObject.SetActive(false); } }
组件配置说明
- Ammo组件:已挂载
Ammo脚本,设置了speed参数,包含Animator和BoxCollider2D组件 - PlayerAttack组件:已挂载
PlayerAttack脚本,配置了attackCooldown参数,指定了firePoint,并给fireballs数组赋值
异常原因及解决方法
Ammo脚本Animator赋值错误:
代码中Awake()方法里anim.GetComponent<Animator>()未将获取到的Animator组件赋值给anim变量,导致anim始终为null,触发explode动画时抛出异常。
修复:将代码改为anim = GetComponent<Animator>();PlayerAttack脚本中PlayerControllert拼写错误:
变量playerMovement的类型写成了PlayerControllert(多了一个t),若你的玩家控制脚本实际类名为PlayerController,则GetComponent<PlayerControllert>()会返回null,后续若使用该变量会触发异常。
修复:将类型改为正确的PlayerController(确保与你的玩家控制脚本类名一致)fireballs数组未正确赋值:
若Inspector中fireballs数组为空或索引0的元素未指定,Attack()方法中访问fireballs[0]会抛出空引用异常。
修复:在PlayerAttack组件的Inspector面板中,给fireballs数组添加已挂载Ammo脚本的炮弹预制体firePoint未正确赋值:
若Inspector中未指定firePoint,Attack()方法中访问firePoint.position会抛出空引用异常。
修复:在PlayerAttack组件的Inspector面板中,将场景中的发射点Transform拖入firePoint字段Animator组件缺失或参数错误:
若Player或Ammo对象未挂载Animator组件,或Animator控制器中未包含attack/explode触发参数,调用SetTrigger时会触发异常。
修复:确保对应对象挂载Animator组件,且Animator控制器中存在对应的触发参数
内容的提问来源于stack exchange,提问作者squeezed

