基类 DG.Tweening.Tween的源码解读

这份代码是 DOTween 引擎中最基础、最核心的抽象基类 DG.Tweening.Tween 的完整定义。

无论是单体动画 Tweener(如 DOMove)还是组合序列 Sequence,都继承自这个类。它负责定义动画的所有基本状态、回调函数、类型元数据,并实现了驱动动画生命周期的最核心方法 DoGoto。

核心结构与关键细节拆解:

1. 字段定义(成员变量)

代码中的字段可以分为四大核心类别:

  • 配置与回调:

    • timeScale、isBackwards、id、target:基础播放配置及绑定的目标(如 Transform)。

    • onPlay、onUpdate、onComplete、onKill 等:各种生命周期回调函数。

  • 对象池类型匹配元数据(与 TweenManager 联动):

    • typeofT1、typeofT2、typeofTPlugOptions:用于记录泛型 Tweener 的实际类型(如 Vector3, Vector3, VectorOptions)。上一问提到的 TweenManager 倒序扫描池子时,比对的就是这三个字段。
  • 运行时状态标记:

    • active:标识当前 Tween 是否处于活跃状态(未被销毁)。

    • activeId:在 TweenManager._activeTweens 数组中的物理索引。

    • startupDone:是否已完成首次初始化(捕获起始值/目标值)。

    • playedOnce:是否已经播放过至少一次(用于控制 onStart 回调只触发一次)。

  • 时间与进度控制:

    • duration(单次循环时长)、fullDuration(包含 loops 的总时长)、position(当前单次循环中的位置)、completedLoops(已完成的循环次数)。

2. 对象池复用机制:Reset() 方法

当动画播放结束并被 TweenManager 放入对象池(Despawn)时,会调用此方法:

  • 重置所有参数 :将 timeScale 重置为 1f,置空所有 onStart/onComplete 回调,清除 target 和 id 引用。

  • 消除 GC 分配 :清空引用避免内存泄漏,同时将数值重置,使当前对象恢复为"干净"的状态,以便下次直接取出使用,实现零 GC 循环利用。

3. 最核心的心脏逻辑:DoGoto() 静态方法

DoGoto 是 DOTween 驱动动画数值更新、计算缓动、触发回调的核心算法管线。TweenManager 在每一帧更新时都会调用此方法。

执行流程拆解:

  1. 懒加载初始化(Startup)

    复制代码
    if (!t.startupDone && !t.Startup()) return true;

    如果 Tween 是第一次运行,在此处触发 Startup(),延迟捕获 Transform 的当前起始位置(Start Value)。

  2. 首次播放回调(onStart / onPlay)

    复制代码
    if (!t.playedOnce && updateMode == UpdateMode.Update) {
        t.playedOnce = true;
        if (t.onStart != null) Tween.OnTweenCallback(t.onStart);
        if (t.onPlay != null) Tween.OnTweenCallback(t.onPlay);
    }
  3. 循环与完成状态判定

    • 计算本次更新跨过了多少次循环 (num2),用于精准触发 onStepComplete。

    • 判断当前进度是否达到了 loops 上限,更新 t.isComplete 状态。

  4. 计算 Yoyo 反弹模式

    复制代码
    bool useInversePosition = t.loopType == LoopType.Yoyo && ((t.position < t.duration) ? (t.completedLoops % 2 != 0) : (t.completedLoops % 2 == 0));

    如果是 Yoyo(往复)模式,根据当前完成的循环次数是奇数还是偶数,计算出当前帧到底应当正向插值还是反向插值。

  5. 应用实际动画数值 (ApplyTween)

    复制代码
    if (t.ApplyTween(prevPosition, num, num2, useInversePosition, updateMode, updateNotice)) return true;

    这是一个多态抽象方法。具体的子类(如 TweenerCore)在此方法中计算 Ease 曲线并赋值给物体的属性 (例如改变 transform.position)。

  6. 按顺序触发生命周期回调

    顺序为:onUpdate,``onRewind, onStepComplete(单步循环完成, onComplete(全部完成) ,onPause。

  7. AutoKill 返回判定

    复制代码
    if (t.autoKill) return t.isComplete;

    如果动画已播放完成且开启了 autoKill,返回 true。TweenManager 收到 true 后就会将此 Tween 加入回收队列(_KillList)。

4. 安全回调机制:OnTweenCallback()

用于执行用户传入的委托回调(如 .OnComplete(...)):

复制代码
if (DOTween.useSafeMode) {
    try { callback(); }
    catch (Exception ex) { Debugger.LogWarning(...); return false; }
} else {
    callback();
}
  • 安全模式(Safe Mode) :如果开启,用户回调函数报错(如空指针异常)时会被 try-catch 捕获并记录日志,防止用户的业务逻辑报错导致整个 DOTween 更新管线崩溃或游戏主循环卡死。

  • 性能模式 :关闭 Safe Mode 时直接调用,节省 try-catch 的开销。

相关推荐
WarPigs21 小时前
Unity对象不应该使用null传播的问题
unity
每日出拳老爷子2 天前
【VR】【Unity】抓走转放系列21|一天搭完门和抽屉工具槽:小场景按这个次序拼装
unity·vr·驱动·排错·snap zone
淡海水3 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
小贺儿开发3 天前
Unity 文物新生 会讲故事的文物展墙
人工智能·科技·unity·ai·视频·互动·演示
淡海水3 天前
02-03-原理篇-大对象堆
unity·c#·游戏引擎·.net·gc
WarPigs4 天前
Unity在Create菜单添加创建自定义脚本模板选项
unity
淡海水4 天前
02-01-原理篇-Mark-Sweep与变种算法
算法·unity·c#·游戏引擎·.net·gc
babywang04 天前
Unity笔记--塔防游戏中的ECS架构:从原理到实战的全面解析
unity·ecs架构
babywang05 天前
Unity笔记--AssetBundle详解
unity·游戏引擎
淡海水5 天前
01-04-认知篇-Unity内存全景
unity·c#·游戏引擎·.net·gc