You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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实现状态传递

方式一:事件触发传递状态

  1. 在Bolt中创建自定义事件EnemyBlindedEvent,添加TargetEnemy参数(类型为GameObject)
  2. 在代码中命中敌人时触发该事件:
if (hitEnemy != null)
{
    hitEnemy.isBlinded = true;
    // 触发Bolt事件
    EnemyBlindedEvent evnt = EnemyBlindedEvent.Create();
    evnt.TargetEnemy = hitinfo.collider.gameObject;
    evnt.Send();
}
  1. 在Bolt状态机中添加Event Listener节点,监听EnemyBlindedEvent,接收事件后切换敌人至致盲状态。

方式二:直接同步Bolt状态变量

  1. 在Bolt的Enemy状态图中添加isBlinded布尔状态变量
  2. 在代码中更新该状态变量:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 00:20:30