Skip to content

时间流转与太阳角系统

系统概览

Env Time-of-Day:从 env-bridge 拆出的时间流转 + 太阳角 + 环境预设动画模块(ADR-148 Phase 5 瘦身)。核心职责:envSunAngle 缓存(消除双源漂移)、time-of-day 帧 tick、预设动画过渡(2 秒 lerp)、分类预设应用。

核心职责

  • 太阳角缓存envSunAngle(模块内高频变量)+ envState.sunAngle(持久化源),经 setEnvState 中间件反向同步消除漂移
  • time-of-day tick_timeOfDayTick 每帧递增太阳角(_timeOfDaySpeed * dt),超出 [-15, 90] 时环绕
  • 预设动画applyEnvPreset(name)applyEnvPresetObject(preset),2 秒 lerp 过渡天空颜色 + 光照,期间暂停 time-of-day(_timeOfDayPaused
  • 分类预设applyEnvPresetByCategory(preset),无动画过渡,精确还原

对外 API(节选)

  • setEnvSunAngle(deg: number) — 设置太阳角 [-15, 90]
  • getEnvSunAngle(): number — 读取太阳角
  • startTimeOfDay(speed?: number) — 启动时间流转
  • stopTimeOfDay() — 停止时间流转(注销 tick 回调 + 持久化)
  • isTimeOfDayActive(): boolean — 是否激活
  • getTimeOfDaySpeed(): number / setTimeOfDaySpeed(s: number)
  • syncTimeOfDayFromEnv() — 启动时从持久化 envState 恢复
  • applyEnvPreset(name: string): boolean — 应用内置预设(带动画过渡)
  • applyEnvPresetObject(preset): boolean — 应用自定义预设对象(参数为结构兼容 EnvPreset 的内联类型 env-time-of-day.ts:257,非具名 EnvPreset
  • applyEnvPresetByCategory(preset: CategorizedEnvPreset): boolean — 应用分类预设(无过渡)

不变量

  • envSunAngle 始终钳制在 [-15, 90] 范围内,超出时环绕
  • _timeOfDayTick!envState.timeOfDayActive_timeOfDayPaused 时直接返回
  • tick 中 sunAngle 变化 ≥ AUTO_LINK_THRESHOLD_DEG 时才触发 applyEnvStateFacade(防抖动),天空色变化 ≥ 0.4 时才 dispatchEnvChange
  • 预设动画期间 _timeOfDayPaused = true,动画完成后恢复
  • applyEnvPreset 调用会取消上一帧的动画 observer(_presetAnimId 递增守卫)
  • stopTimeOfDay 注销 _unregisterTimeOfDay 后置空,防重复注销
  • 启动时调用 syncTimeOfDayFromEnv()envState.timeOfDaySpeed 恢复模块变量

与其他子系统关系

  • 依赖 env-bridge.tssetEnvState / registerEnvStateMiddleware(同步 envSunAngle 中间件)
  • 依赖 env-persist.tspersistEnvState / cancelEnvPersistTimer
  • 依赖 env-lighting.tsderiveLighting / TIME_OF_DAY_PRESETS
  • 依赖 render/lighting.ts_updateSunDisc / setLightState
  • 依赖 env-dispatcher.tsdispatchEnvChange / registerSceneTickCallback
  • env.ts 门面 re-export

验证入口

  • 命令:cd frontend && npm run test