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

Unity跨脚本获取组件变量时触发引擎崩溃问题求助

问题根因

你的代码存在4个直接导致引擎崩溃、逻辑失效的核心问题:

  1. 语法错误直接触发编译崩溃:Food生成脚本最后一行foodobject.name = "AppleObject";存在引号不匹配问题,C#编译器解析未闭合字符串时会抛出严重语法错误,直接导致Unity编译进程崩溃。
  2. 空引用未防护引发运行时崩溃:Hunter的Update逻辑中没有判断ScannerEyes.foundobject是否为null——游戏启动初期扫描器未检测到苹果时,foundobject默认是null,直接访问.transform会每帧抛出空引用异常,异常堆栈持续堆积会直接卡死引擎。另外你写的GameObject.FindGameObjectsWithTag("Food") != null判断完全无效:该方法无论场景内是否存在对应标签物体,都会返回数组对象(无对应物体时返回长度为0的空数组,永远不会返回null),根本无法拦截空引用。
  3. 组件获取逻辑错误:你提到ScannerEyes挂载在Hunter的子对象上,但GetComponent<ScannerEyes>()只会搜索Hunter物体自身挂载的组件,不会遍历子物体,因此你拿到的组件引用本身就是null,访问null对象的属性必然触发异常。
  4. 扫描逻辑单次生效:ScannerEyes第一次扫到苹果后就会把扫描球缩为0,终止扫描流程,如果当前锁定的苹果被其他猎人吃掉/销毁,猎人会永久丢失目标,不会重新搜索新的苹果。

额外存在两个影响稳定性的问题:每帧调用GetComponent获取组件会产生不必要的性能开销;扫描扩张速度没有乘以Time.deltaTime,会导致扫描速度受帧率影响波动。


修复方案

按以下逻辑修改代码即可解决所有问题:

  1. 修复Food脚本的语法错误,补全正确的字符串引号。
  2. 在Hunter初始化阶段缓存子对象上的ScannerEyes组件引用,不要每帧重复查找。
  3. 所有访问可能为null的对象前,先做非空校验。
  4. 给ScannerEyes增加重置逻辑:锁定的苹果被销毁后,自动重启扫描流程。
  5. 移动逻辑指定使用世界坐标,避免物体自身旋转导致移动方向偏移。

修正后的Hunter脚本代码

// 缓存组件和参数
private ScannerEyes myScanner;
public Transform Target;
public float Speed = 5f;
public float StopDistance = 1f;
public int reproducerate = 0;

void Start()
{
    // GetComponentInChildren会遍历自身和所有子物体的组件,正确拿到子对象上的ScannerEyes
    myScanner = GetComponentInChildren<ScannerEyes>();
}

void Update()
{
    if (reproducerate < 1)
    {
        // 仅当扫描器找到目标、且目标未被销毁时执行移动逻辑
        if (myScanner.found && myScanner.foundobject != null)
        {
            Target = myScanner.foundobject.transform;
            Vector3 moveDir = (Target.position - transform.position).normalized;
            if (Vector3.Distance(transform.position, Target.position) > StopDistance)
            {
                // 指定Space.World保证移动方向不受物体自身旋转影响
                transform.Translate(moveDir * Time.deltaTime * Speed, Space.World);
            }
        }
    }
}

public void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Food"))
    {
        reproducerate += 1;
        Destroy(collision.gameObject);
        // 吃到苹果后重置扫描器,搜索下一个目标
        myScanner.ResetScan();
        Debug.Log(reproducerate);
    }
}

修正后的ScannerEyes脚本代码

public bool found = false;
public GameObject foundobject;
public float maxScanSize = 10f;
public float scanSpeed = 2f;
private float currentSize = 0f;

void Update()
{
    // 扫描球未到最大范围、且未找到目标时持续扩张
    if (currentSize < maxScanSize && !found) {
        transform.localScale = new Vector3(currentSize, currentSize, currentSize);
        currentSize += scanSpeed * Time.deltaTime;
    }

    if (found)
    {
        transform.localScale = Vector3.zero;
        // 锁定的目标被销毁时自动重置扫描
        if (foundobject == null)
        {
            ResetScan();
        }
    }
}

// 对外提供重置扫描的方法
public void ResetScan()
{
    found = false;
    foundobject = null;
    currentSize = 0f;
}

private void OnTriggerEnter(Collider other)
{
    // 未找到目标时才响应Food触发,避免重复覆盖目标
    if (other.gameObject.CompareTag("Food") && !found)
    {
        Debug.Log("Found target");
        foundobject = other.gameObject;
        Debug.Log("Target position: " + foundobject.transform.position);
        found = true;
    }
}

修正后的Food生成脚本代码

private GameObject foodobject;
public GameObject Foodprefab;
private float xSpawn;
private float zSpawn;

void Start()
{
    Debug.Log("Food spawner active");
    for (int i = 0; i < 2; i++){
        xSpawn = Random.Range(-4, 4);
        zSpawn = Random.Range(-4, 4);
        Debug.Log(xSpawn + " , " + zSpawn);
        foodobject = Instantiate(Foodprefab,
            new Vector3(xSpawn, 1.4f, zSpawn),
            Quaternion.identity);
        // 修复引号不匹配的语法错误
        foodobject.name = "AppleObject";
    }
}

配置注意事项
  • 确保scannereyes子对象的Collider组件勾选了Is Trigger选项,否则OnTriggerEnter事件不会触发
  • Rigidbody组件挂载在Hunter父物体上即可,不要给扫描球单独加Rigidbody,避免物理计算异常
  • 所有Apple预制体必须正确设置Food标签,否则扫描逻辑无法识别目标

内容的提问来源于stack exchange,提问作者Hymandois

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:57:11