Unity射线检测修改其他类变量:致盲AI空引用错误排查
射线检测致盲敌人AI:空引用错误修复与Bolt状态传递实现
需求
- 射线命中敌人时,将Enemy类的
isBlinded布尔值设为true - 结合可视化脚本Bolt实现状态传递
问题
- 引用敌人GameObject时触发
NullReferenceException,错误位置:Raycast.Update()(Assets/Scripts/Raycast.cs第23行) - 直接声明Enemy类变量时,无法在Inspector面板中添加敌人对象
错误代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Raycast : MonoBehaviour { [SerializeField] LayerMask enemyLayer; RaycastHit hitinfo; public GameObject enemy; void Update() { Ray ray = new Ray(transform.position, transform.TransformDirection(Vector3.forward)); Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 20, Color.red); if (Physics.Raycast(ray, out hitinfo, 100, enemyLayer)) { Debug.Log("Hit"); Debug.Log(hitinfo.collider.gameObject.name); //enemy is blinded is true enemy.GetComponent<Enemy>().isBlinded = true; Debug.Log(enemy.GetComponent<Enemy>().isBlinded); } else { Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 20, Color.green); } } }
解决方案
1. 修复空引用错误
空引用的核心原因是:代码依赖Inspector中手动赋值的enemy变量,但该变量未赋值,且射线命中的敌人对象不一定是预设的enemy。正确做法是直接从射线命中结果中获取敌人对象:
修改后的Update方法代码:
void Update() { Ray ray = new Ray(transform.position, transform.TransformDirection(Vector3.forward)); Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 20, Color.red); if (Physics.Raycast(ray, out hitinfo, 100, enemyLayer)) { Debug.Log("Hit"); Debug.Log(hitinfo.collider.gameObject.name); // 从命中对象获取Enemy组件 Enemy hitEnemy = hitinfo.collider.gameObject.GetComponent<Enemy>(); if (hitEnemy != null) { hitEnemy.isBlinded = true; Debug.Log(hitEnemy.isBlinded); } } else { Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * 20, Color.green); } }
同时,移除无用的public GameObject enemy变量,避免后续混淆。
关于直接声明Enemy类变量无法在Inspector添加的问题:Inspector仅支持直接拖拽GameObject,若要在Inspector中引用Enemy组件,需给变量添加[SerializeField]标记,再拖拽挂载了Enemy脚本的GameObject,但从射线命中结果动态获取组件的方式更可靠,无需依赖手动赋值。
2. 结合Bolt实现状态传递
方式一:事件触发传递状态
- 在Bolt中创建自定义事件
EnemyBlindedEvent,添加TargetEnemy参数(类型为GameObject) - 在代码中命中敌人时触发该事件:
if (hitEnemy != null) { hitEnemy.isBlinded = true; // 触发Bolt事件 EnemyBlindedEvent evnt = EnemyBlindedEvent.Create(); evnt.TargetEnemy = hitinfo.collider.gameObject; evnt.Send(); }
- 在Bolt状态机中添加
Event Listener节点,监听EnemyBlindedEvent,接收事件后切换敌人至致盲状态。
方式二:直接同步Bolt状态变量
- 在Bolt的Enemy状态图中添加
isBlinded布尔状态变量 - 在代码中更新该状态变量:
if (hitEnemy != null) { Entity enemyEntity = hitinfo.collider.gameObject.GetComponent<Entity>(); if (enemyEntity != null) { // 更新Bolt状态中的isBlinded enemyEntity.SetState("isBlinded", true); // 同步本地Enemy类变量 hitEnemy.isBlinded = true; } }
内容的提问来源于stack exchange,提问作者logi
相关产品推荐
相关产品推荐

