Skip to content

Navigation Menu

Sign in
Sign up

fix(story-player): backgroundtween 实现 ease/loop 参数并移植 DOTween 曲线 - #358

Draft
daflyinbed wants to merge 1 commit into
refactor/story-player-tween-infra from
fix/story-player-backgroundtween
Draft

fix(story-player): backgroundtween 实现 ease/loop 参数并移植 DOTween 曲线 #358
daflyinbed wants to merge 1 commit into
refactor/story-player-tween-infra from
fix/story-player-backgroundtween

Conversation

@daflyinbed

@daflyinbed daflyinbed commented Aug 24, 2026
edited
Loading

Copy link
×ばつ次数,每周期从 From 重放);runtime 读取 `loop`(缺省 false)传入 renderer,`setBackgroundTween` 映射为 `loops: loop ? -1 : 1`。生产语料 0 命中,前瞻对齐,由单测锁定。 ### 3. `loop && block` 告警未移植(P2) - **native 行为**:LogError(保留 native 拼写错误)后照常执行并卡死。 - **前端行为(修复前)**:既无告警也无死循环。 - **改法**:runtime 在 `block && loop` 时发 `invalid_parameter` warning,消息保留 native 原文(含 "intinity lop" 拼写错误),随后照常执行(阻塞的无限循环 await 永不 resolve,与 native 卡死一致;语料 0 命中)。 ### 4. 无背景时的守卫行为(P2,维持现状 + 补注释) - **native 行为**:`_foreImage` 是 panel 序列化字段、永远存在,即使无背景图 tween 照跑,`block=true` 会空转阻塞满 duration。 - **前端行为(修复前)**:`setBackgroundTween` 开头无背景即 return,`block=true` 也立即返回。 - **改法**:不动行为(实际脚本中 backgroundtween 前必有 background,属理论分支),在守卫处补注释说明 native 行为与 Web 适配的理由。 ### 未改动项 - 位移/缩放合并为单条 tween(P3):同 ease 同时长下与 native 两条独立 DOTween 逐帧等价(实现 #1 后 eased 进度仍同步推进)。 - 跨命令终止时机(P3):与 `background` review 的同一处修复(旧背景 tween 活到下次交叉淡入结束才被杀),归 background 命令的修复范围,本 PR 不碰。 ## 验证用剧情文件 生产剧情文件位于本地 `torappu/storage/asset/gamedata/latest/story`: | 文件 | 行号 | 参数 | 验证项 | | --- | --- | --- | --- | | `obt/main/level_st_15-02.txt` | 520 | `ease="OutQuad"`(语料共 68 处,最高频) | #1 缓出曲线(中点 0.75 而非 0.5) | | `obt/main/level_main_11-04_end.txt` | 64 | `ease="InOutCubic"`, `block=true` | #1 InOut 三次曲线 | | `activities/act53side/level_act53side_06_beg.txt` | 290 | `ease="6"`(ordinal = OutQuad) | #1 整数串按 ordinal 解析 | | `obt/memory/story_chen2_1_1.txt` | 9 | `ease="1"`(ordinal = Linear) | #1 ordinal 与 Linear 缺省等价 | | `activities/act51side/level_act51side_03_end.txt` | 76 | `ease="InQuart"` | #1 缓入四次曲线 | | `obt/memory/story_kroos_1_1.txt` | 132 | `ease="InOutSine"`, `block=true` | #1 InOut 正弦 | | `obt/memory/story_mizuki_1_1.txt` | 515 | `ease="OutFlash"` | #1 Flash 曲线(默认参数退化为 2t-t2,直译 `Flash.EaseOut` @ 0x184143640) | | `loop` 参数 | — | 语料 0 命中 | #2/#3 为前瞻对齐,由单测锁定:`tests/runtime.spec.ts` "maps backgroundtween ease and loop and warns on loop with block"(参数映射 + 告警)、`tests/tweenRunner.spec.ts` "replays from the start on every Restart loop cycle" / "never completes an infinite loop while alive"(Restart 回放与无限循环)、`tests/tweenEase.spec.ts`(曲线值/ordinal/大小写敏感/Flash 退化) | ## 测试 - `pnpm test`:22 个文件 235 用例全过(基线 222,新增 13:曲线解析与抽查 6、TweenRunner ease/loops 4、runtime 映射与告警 1、renderer options 传递 2)。 - `pnpm exec vue-tsc -b`:通过。 - `pnpm exec eslint <全部改动文件>`:通过(无 error/warning)。" data-view-component="true"> Copy Markdown
Contributor

重组说明(2026年09月04日):本 PR 已 rebase 到共享 tween 基建 #407(DOTween ease 曲线库 + TweenRunner ease/loop 选项),分支中的内联曲线表已移除;冲突的 main 新变更(如 face overlay imports)一并解决。#407 合并后本 PR 自动回到 main 基线。

本 PR 修复 StoryPlayer 对 AVG backgroundtween 命令移植中的可选参数缺失(ease / loop),并新增可复用的 DOTween 缓动曲线库。依据是对明日方舟官服客户端(2.7.61 / build 2761,Unity IL2CPP)GameAssembly.dll 的逆向分析,关键结论在下文直接给出,不依赖外部文档。

背景:native 的 backgroundtween 可选参数(2.7.61 逆向结论,IDA 复核)

  • Torappu.AVG.AVGImagePanel._ExecuteImageTween @ 0x183e57560(注册于 BackgroundPanel.GetExecutors() @ 0x183e68f00,2.7.61 已去除 XOR 混淆、参数 key 均为明文)在 duration/block/8 个 *From/*To 键之外还读取两个可选参数:
    • ease:DotNetExtensionMethods.GetEnum<Ease>(param, "ease", 默认立即数 1 = Ease.Linear, ignoreCase: false) @ 0x183e579ef。枚举名按大小写敏感匹配,整数串按 ordinal 解析(ease="6" = OutQuad);解析失败回落 Linear。随后 SetEase(ease) 同时作用于 DOLocalMove 与 DOScale 两条 tween。
    • loop:GetBool(param, "loop", false) @ 0x183e579f2,喂给 SetLoops(2*!loop - 1):true → -1 即无限循环(DOTween 默认 Restart 类型,每轮回 From 重放,OnComplete 永不触发),false → 1 单次。
  • loop && effectiveBlock 告警:if (effectiveBlock && loop) → DLog.LogError("Loop and block both true when tween background! Will cause intinity lop!") @ 0x183e57a1e(拼写错误为 native 原样),打完日志继续执行,并因无限循环的 OnComplete(FinishCommand) 永不触发而卡死。
  • 曲线本体是内嵌 DOTween:DG.Tweening.Core.Easing.EaseManager.Evaluate @ 0x184140b40(Robert Penner 方程;超枚举域的数值走 default 分支 = OutQuad 抛物线,INTERNAL_Zero 恒 1),Bounce/Flash 辅助类 @ 0x18413fb50-0x1841438a0。游戏版 Ease 枚举(dump 骨架反编译)为 Unset=0 ... InOutBounce=31, Flash=32, InFlash=33, OutFlash=34, InOutFlash=35, INTERNAL_Zero=36, INTERNAL_Custom=37
  • Flash 曲线细节(定点反编译 Flash.EaseIn/EaseOut/EaseInOut/Ease/WeightedEase):与 Elastic/Back 不同,Flash 实现对 overshootOrAmplitude/period 不做哨兵替换,因此 SetEase(Ease) 的库级默认(-1 / 0)会原样进入公式——每段波退化为平面二次曲线(OutFlash 即 2t-t2)。前端按公式带默认值直译,自动得到同一结果。
  • 其余语义(本 PR 未改动,复核确认已正确移植):duration 不乘 animateRatio/不走 CalculateFadetime;effectiveBlock = duration > 0 && block;duration <= 0 即时 Complete 到 To;From/To 缺省回落当前 transform 值;无效 key(image/fadetime/x/y 等)不被消费。

修复内容

1. ease 参数未实现(P1)

  • native 行为:GetEnum<Ease>("ease", 默认 1=Linear) + DOTween SetEase;生产语料中 85 次显式使用(OutQuad 68、InOutCubic 9、"6"=OutQuad 5、"1"=Linear 4、InQuart 2、InOutSine 2、OutFlash 1)。
  • 前端行为(修复前):BackgroundTweenInput 无 ease 字段,TweenRunner 恒线性插值;非 Linear 值(如 InSine=2/OutQuad)被错误渲染成线性。
  • 改法:
    • 新增 engine/rendering/core/DotweenEase.ts:DOTween 全套曲线(Linear...InOutBounce + Flash/InFlash/OutFlash/InOutFlash + INTERNAL 两项),dotweenEaseCurve(ease) 按 GetEnum 语义解析(名字大小写敏感、数字串按 ordinal、超枚举域 ordinal 保持 Evaluate default 的 OutQuad 抛物线、解析失败回落 Linear)。
    • TweenRunner.run() 增加可选 options.ease(每循环周期对原始进度应用曲线)。
    • runtime 读取 ease(缺省 "Linear")传入 renderer;setBackgroundTween 解析曲线后交给 TweenRunner,同一 eased 进度同时插值位移与缩放(= 两条 DOTween 同 ease 同时长,逐帧等价)。

2. loop 参数未实现(P2)

  • native 行为:SetLoops(2*!loop-1):true → -1 无限 Restart 循环(每轮回 From 重放)。
  • 前端行为(修复前):完全忽略,恒单次。
  • 改法:TweenRunner.run() 增加可选 options.loops(DOTween 语义:1=单次,负数=无限 Restart,有限次数=×ばつ次数,每周期从 From 重放);runtime 读取 loop(缺省 false)传入 renderer,setBackgroundTween 映射为 loops: loop ? -1 : 1。生产语料 0 命中,前瞻对齐,由单测锁定。

3. loop && block 告警未移植(P2)

  • native 行为:LogError(保留 native 拼写错误)后照常执行并卡死。
  • 前端行为(修复前):既无告警也无死循环。
  • 改法:runtime 在 block && loop 时发 invalid_parameter warning,消息保留 native 原文(含 "intinity lop" 拼写错误),随后照常执行(阻塞的无限循环 await 永不 resolve,与 native 卡死一致;语料 0 命中)。

4. 无背景时的守卫行为(P2,维持现状 + 补注释)

  • native 行为:_foreImage 是 panel 序列化字段、永远存在,即使无背景图 tween 照跑,block=true 会空转阻塞满 duration。
  • 前端行为(修复前):setBackgroundTween 开头无背景即 return,block=true 也立即返回。
  • 改法:不动行为(实际脚本中 backgroundtween 前必有 background,属理论分支),在守卫处补注释说明 native 行为与 Web 适配的理由。

未改动项

  • 位移/缩放合并为单条 tween(P3):同 ease 同时长下与 native 两条独立 DOTween 逐帧等价(实现 Create ISEvent.ts #1 后 eased 进度仍同步推进)。
  • 跨命令终止时机(P3):与 background review 的同一处修复(旧背景 tween 活到下次交叉淡入结束才被杀),归 background 命令的修复范围,本 PR 不碰。

验证用剧情文件

生产剧情文件位于本地 torappu/storage/asset/gamedata/latest/story:

文件 行号 参数 验证项
obt/main/level_st_15-02.txt 520 ease="OutQuad"(语料共 68 处,最高频) #1 缓出曲线(中点 0.75 而非 0.5)
obt/main/level_main_11-04_end.txt 64 ease="InOutCubic", block=true #1 InOut 三次曲线
activities/act53side/level_act53side_06_beg.txt 290 ease="6"(ordinal = OutQuad) #1 整数串按 ordinal 解析
obt/memory/story_chen2_1_1.txt 9 ease="1"(ordinal = Linear) #1 ordinal 与 Linear 缺省等价
activities/act51side/level_act51side_03_end.txt 76 ease="InQuart" #1 缓入四次曲线
obt/memory/story_kroos_1_1.txt 132 ease="InOutSine", block=true #1 InOut 正弦
obt/memory/story_mizuki_1_1.txt 515 ease="OutFlash" #1 Flash 曲线(默认参数退化为 2t-t2,直译 Flash.EaseOut @ 0x184143640)
loop 参数 语料 0 命中 #2/#3 为前瞻对齐,由单测锁定:tests/runtime.spec.ts "maps backgroundtween ease and loop and warns on loop with block"(参数映射 + 告警)、tests/tweenRunner.spec.ts "replays from the start on every Restart loop cycle" / "never completes an infinite loop while alive"(Restart 回放与无限循环)、tests/tweenEase.spec.ts(曲线值/ordinal/大小写敏感/Flash 退化)

测试

  • pnpm test:22 个文件 235 用例全过(基线 222,新增 13:曲线解析与抽查 6、TweenRunner ease/loops 4、runtime 映射与告警 1、renderer options 传递 2)。
  • pnpm exec vue-tsc -b:通过。
  • pnpm exec eslint <全部改动文件>:通过(无 error/warning)。

native 2.7.61(backgroundtween executor 即 AVGImagePanel._ExecuteImageTween
@ 0x183e57560): ease 经 GetEnum<Ease>(默认 Linear) 解析,loop 喂
SetLoops(2*!loop-1)(true→无限 Restart 循环),loop+block 触发 native 原样
拼写错误的 intinity lop 告警后继续执行。
ease 曲线与 TweenRunner ease/loop 选项由共享 tween 基建提供
(refactor/story-player-tween-infra)。
StarHeartHunt force-pushed the fix/story-player-backgroundtween branch from b6cddbd to 912daee Compare September 7, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /