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

Unity私有变量nextSwitch初始化异常致AI移动逻辑故障

问题分析与解决方案

问题根源

你的AIController是ScriptableObject类型,Unity会自动持久化ScriptableObject实例的字段值。也就是说,每次运行游戏时修改的nextSwitch值会被保存到对应的资源文件中,下次启动游戏时不会重新初始化回0f,而是直接读取上次运行结束时的旧值,这就导致初始值越来越大,AI需要等待很久才会切换方向。

另外,代码中同时混用了Time.time和Time.timeSinceLevelLoad,这两个时间API的定义不同:

  • Time.time:从游戏启动到当前的总时间(包含暂停时间)
  • Time.timeSinceLevelLoad:当前场景加载完成到当前的时间(不包含暂停时间)
    混用会导致时间判断逻辑出现偏差。

修复步骤

  1. 添加初始化逻辑:在ScriptableObject的OnEnable或Awake方法中重置nextSwitch,确保每次加载时都初始化正确值。
  2. 统一时间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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 19:16:04