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

Unity动画结束后物体文本不更新及循环迭代异常问题排查

问题排查与修复方案

核心问题分析

从你的代码中可以定位到几个导致循环异常、文本不更新的关键问题:

1. 数组索引越界与初始值错误

number初始值为0,Start()中第一次调用nextQuestion()时直接执行number++,导致跳过questions[0],且当number增长到等于questions或answer_keys的长度时,会触发数组越界异常,直接中断后续逻辑,循环自然无法继续。

2. 动画未等待结束就更新文本

当前代码播放动画后立刻修改胡萝卜的文本,但动画过程中可能会重置物体状态,或者你的需求是动画结束后再更新文本,这就导致文本被动画覆盖或者更新时机错误。

3. 随机索引的硬编码问题

随机索引使用Random.Range(0, 2.4f),硬编码上限如果和胡萝卜子物体数量不匹配,会导致要么重复赋值要么索引越界,破坏文本更新的逻辑。

4. 重复获取组件的冗余操作

多次重复调用GetComponent<TMP_Text>()、GetComponent<Animator>(),不仅影响性能,还可能因组件引用丢失导致空引用错误,中断文本更新流程。

修复后的完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class Bunny : MonoBehaviour 
{
    public GameObject carrots;
    public float speed;
    public float currentYrotation;

    public string[] questions, answer_keys;
    string[] answers;

    int number = 0;
    public TMP_Text question_display;
    
    // 缓存组件,避免重复获取
    private Animator carrotAnimator;
    private Rigidbody rb;

    void Start()
    {
        // 初始化缓存组件
        carrotAnimator = carrots.GetComponent<Animator>();
        rb = GetComponent<Rigidbody>();
        
        // 直接加载第一个问题,避免初始number++跳过问题
        StartCoroutine(LoadNextQuestion());
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            rb.velocity = new Vector3(0, 0, speed);
            transform.rotation = Quaternion.Euler(0, currentYrotation - 20, 0);
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            rb.velocity = new Vector3(0, 0, -speed);
            transform.rotation = Quaternion.Euler(0, currentYrotation + 20, 0);
        }
        if (Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.LeftArrow))
        {
            rb.velocity = new Vector3(0, 0, 0);
            transform.rotation = Quaternion.Euler(0, currentYrotation, 0);
        }
    }

    void OnTriggerEnter(Collider obj)
    {
        // 用引用比较替代名字判断,更可靠
        if (obj.gameObject == carrots)
        {
            var firstCarrotText = carrots.transform.GetChild(0).GetChild(0).GetComponent<TMP_Text>().text;
            if (firstCarrotText == answers[0])
            {
                print("correct");
            }
            else
            {
                print("wrong");
            }
            
            // 加载下一题前先判断是否还有题目,避免越界
            if (number < questions.Length - 1)
            {
                StartCoroutine(LoadNextQuestion());
            }
            else
            {
                print("所有题目已完成");
            }
        }
    }

    IEnumerator LoadNextQuestion()
    {
        yield return new WaitForSeconds(0.25f);
        
        // 先判断是否越界,再更新题目
        if (number >= questions.Length || number >= answer_keys.Length)
        {
            print("已无更多题目");
            yield break;
        }
        
        // 更新题目显示
        question_display.transform.parent.gameObject.SetActive(true);
        question_display.text = questions[number];

        // 播放动画并等待动画结束
        carrotAnimator.enabled = true;
        carrotAnimator.Play("carrots");
        // 等待动画完成(需确保动画状态机中"carrots"动画的名称正确)
        yield return new WaitForSeconds(carrotAnimator.GetCurrentAnimatorStateInfo(0).length);

        // 拆分答案选项
        answers = answer_keys[number].Split('|');
        
        // 清空所有胡萝卜文本
        for (int i = 0; i < carrots.transform.childCount; i++)
        {
            var textComp = carrots.transform.GetChild(i).GetChild(0).GetComponent<TMP_Text>();
            if(textComp != null) textComp.text = "";
        }
        
        // 随机分配答案,使用子物体数量作为随机上限
        for (int i = 0; i < carrots.transform.childCount; i++)
        {
            if(i >= answers.Length) break; // 避免答案数组长度不足的情况
            
            int index;
            do
            {
                index = Random.Range(0, carrots.transform.childCount);
            } while (!string.IsNullOrEmpty(carrots.transform.GetChild(index).GetChild(0).GetComponent<TMP_Text>().text));
            
            var targetText = carrots.transform.GetChild(index).GetChild(0).GetComponent<TMP_Text>();
            if(targetText != null) targetText.text = answers[i];
        }
        
        // 最后再递增number,确保当前题目正确加载后再进入下一题
        number++;
    }
}

关键修复点说明

  • 修正索引逻辑:将number++移到协程末尾,确保当前题目正常加载后再进入下一题,同时增加数组越界判断,避免崩溃。
  • 等待动画结束:通过carrotAnimator.GetCurrentAnimatorStateInfo(0).length获取动画时长,等待动画完成后再更新文本,符合你的需求。
  • 缓存组件:提前缓存Animator和Rigidbody,避免重复获取组件的性能损耗和空引用风险。
  • 动态随机范围:用carrots.transform.childCount作为随机索引的上限,适配不同数量的胡萝卜子物体。
  • 可靠的碰撞判断:用obj.gameObject == carrots替代名字判断,避免因同名物体或拼写错误导致逻辑失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:55:54