Unity C# List重复存放枚举状态BasicIdle时切换卡死问题
问题根因
循环bug和枚举值为0没有关系,核心错误出在状态索引的查找逻辑上:
你使用List.FindIndex()匹配当前状态时,该方法永远只会返回列表中第一个符合匹配条件的元素索引,完全没有记录状态遍历的实际进度。
举个实际运行的例子,假设你在Inspector配置的列表顺序为[BasicIdle, PlayingWithKids, BasicIdle, Bored]:
- 初始状态在索引0的BasicIdle,等待时长结束后,FindIndex找到第一个BasicIdle的索引为0,+1得到1,切换到PlayingWithKids,运行正常
- PlayingWithKids时长结束后,FindIndex找到第一个PlayingWithKids的索引为1,+1得到2,切换到第二个BasicIdle,此时看似运行正常
- 第二个BasicIdle时长结束后,FindIndex查找BasicIdle时依然只会返回第一个匹配项的索引0,+1得到1,再次切回PlayingWithKids,之后就会一直在PlayingWithKids和第二个BasicIdle之间循环,永远走不到后面的Bored状态,和你遇到的现象完全一致。
修复方案
不需要修改枚举定义、状态切换方法和各状态的执行逻辑,只要新增一个字段单独记录当前遍历到的列表索引,不要每次靠状态值反查位置即可:
- 首先在类的成员变量区域新增索引记录字段:
// 记录当前状态在配置列表中的索引,初始值对应列表第一个元素 private int currentStateIndex = 0;
- 替换FixedUpdate中原来的索引查找逻辑,直接对记录的索引做递增即可:
private void FixedUpdate() { if (Time.timeSinceLevelLoad > prevIdleStateChangeTime + currentStateDuration) { // 直接移动到下一个状态的索引 currentStateIndex++; // 遍历到列表末尾时重置到开头 if (currentStateIndex >= availableIdleStates.Count) { currentStateIndex = 0; } changeState(availableIdleStates[currentStateIndex]); } // 下方原有的switch状态执行逻辑完全不需要改动 switch (currentIdleState) { case IdleState.BasicIdle: if (Time.timeSinceLevelLoad > subStateChangeTime + subStateDuration) { subStateChangeTime = Time.timeSinceLevelLoad; switch (randInt) { // 原有子状态逻辑保持不变 } } break; case IdleState.PlayingWithKids: if (Time.timeSinceLevelLoad > subStateChangeTime + subStateDuration) { int randInt = Random.Range(0, 3); subStateChangeTime = Time.timeSinceLevelLoad; switch (randInt) { // 原有子状态逻辑保持不变 } } break; // 其余状态的逻辑和原有结构一致即可 } }
补充说明:如果运行时存在动态增删availableIdleStates列表元素的需求,只要在修改列表后加一行校验,把currentStateIndex钳制到
0 ~ availableIdleStates.Count-1的合法区间即可,固定在Inspector配置的列表不需要额外处理。
你原来写的changeState方法逻辑没有问题,不需要做任何修改。改完之后不管你在列表里加多少次BasicIdle,都会按照配置的顺序依次执行,不会再出现卡循环的问题。
内容的提问来源于stack exchange,提问作者chana banana
相关产品推荐
相关产品推荐

