Unity私有变量nextSwitch初始化异常致AI移动逻辑故障
问题分析与解决方案
问题根源
你的AIController是ScriptableObject类型,Unity会自动持久化ScriptableObject实例的字段值。也就是说,每次运行游戏时修改的nextSwitch值会被保存到对应的资源文件中,下次启动游戏时不会重新初始化回0f,而是直接读取上次运行结束时的旧值,这就导致初始值越来越大,AI需要等待很久才会切换方向。
另外,代码中同时混用了Time.time和Time.timeSinceLevelLoad,这两个时间API的定义不同:
Time.time:从游戏启动到当前的总时间(包含暂停时间)Time.timeSinceLevelLoad:当前场景加载完成到当前的时间(不包含暂停时间)
混用会导致时间判断逻辑出现偏差。
修复步骤
- 添加初始化逻辑:在ScriptableObject的
OnEnable或Awake方法中重置nextSwitch,确保每次加载时都初始化正确值。 - 统一时间API:将时间判断和赋值统一使用同一个时间变量,避免逻辑错误。
修复后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "AIController", menuName = "InputController/AIController")] public class AIController : InputController { private float movement = -1f; private float switchRate = 2f; private float nextSwitch = 0f; private void OnEnable() { // 每次加载ScriptableObject时重置切换时间 nextSwitch = Time.timeSinceLevelLoad + switchRate; // 可根据需求选择是否重置初始移动方向 // movement = -1f; } public override bool RetrieveJumpInput() { return true; } public override float RetrieveMoveInput() { Debug.Log("test " + Time.timeSinceLevelLoad + " " + nextSwitch); // 统一使用Time.timeSinceLevelLoad进行时间判断 if (Time.timeSinceLevelLoad > nextSwitch) { nextSwitch = Time.timeSinceLevelLoad + switchRate; movement *= -1f; } return movement; } }
额外说明
如果希望在进入Play模式时强制重置ScriptableObject的字段,可以在Unity编辑器的Edit > Project Settings > Editor中开启Enter Play Mode Settings下的Reload Domain,不过这会增加进入Play模式的时间。更推荐在OnEnable中手动初始化需要重置的字段,这样更灵活且性能更好。
内容的提问来源于stack exchange,提问作者Joel Hempel
相关产品推荐
相关产品推荐

