TiXL Lib.flow ExecRepeatedly 操作符完全指南:用 RepeatCount 与 SkipFrameCount 精确控制子图执行频率
2026/9/19 21:54:36 网站建设 项目流程

TiXL Lib.flow ExecRepeatedly 操作符完全指南:用 RepeatCount 与 SkipFrameCount 精确控制子图执行频率

【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3

ExecRepeatedly 是 TiXL(t3)实时运动图形引擎中Lib.flow流程控制库的核心操作符,用于精确控制子图(sub graph)的执行频率。本文以其官方文档与仓库源码为主线,完整讲解三个输入参数的含义、默认值与取值范围,深入剖析其执行时序与钳制逻辑,并结合ExecuteExecuteOnceLoop等兄弟操作符给出实战选型建议。读完本文,你将能在模拟加速/减速、抽帧优化、帧步进等场景中自如使用该操作符。

功能定位:控制子图的执行频率

根据官方文档,ExecRepeatedly 的作用是"控制子图被执行的频繁程度"(Controls how frequently the sub graph is being executed),并明确指出它"可用于提高或降低模拟速度"(This can be useful for increasing or slowing down simulation speeds)。在 Lib.flow 的算子目录中,它被描述为:Controls how frequently the sub graph is being executed,归属于流程控制(flow)命名空间。

这意味着它不是普通的"每帧执行一次"的开关,而是一个可编程的执行节流器:通过两个整数参数,你可以让一段子图在一帧内重复执行多次(加速模拟),也可以让它每隔若干帧才执行一次(减速模拟、节省开销)。

输入参数详解

官方文档列出了三个输入参数,结合仓库源码与默认配置,它们的完整语义如下:

参数名类型说明默认值运行时钳制范围
CommandCommand(多输入槽)要被执行/节流的子图命令,可连接多条输入null
RepeatCountInt32每次触发时子图重复执行的次数,0 表示禁用10 ~ 100
SkipFrameCountInt32触发前跳过的帧数(调用次数),实现抽帧减速00 ~ 10000

三个参数的默认值均可在序列化文件 ExecRepeatedly.t3 中确认:RepeatCount默认 1、SkipFrameCount默认 0、Command默认为空。

RepeatCount:单帧内的重复次数

  • 每次触发后,Command 子图会被连续执行RepeatCount次,从而在一帧内完成多次模拟步进,等效于加速模拟(例如把物理/粒子模拟跑得更快)。
  • 设为0时操作符直接返回,不执行任何命令,可用于临时"静音"一段子图。
  • 源码中使用RepeatCount.GetValue(context).Clamp(0, 100)将输入钳制在 0~100 之间,超出范围的数值会被安全截断。

SkipFrameCount:触发前的跳过帧数

  • 每帧(每次 Update 调用)计数器_callsSinceLastRefresh自增 1;当计数<= SkipFrameCount时操作符直接返回不执行,直到超过该值才触发一次执行并重置计数器
  • 默认0表示每帧都触发,保持与父图同步的逐帧行为。
  • 增大该值可让子图每隔 N+1 帧才执行一次,实现"抽帧"式减速与性能节省(例如低频轮询、低频刷新数据)。
  • 源码中该值被钳制在 0~10000。

执行时序与底层实现

ExecRepeatedly 的完整执行逻辑在 ExecRepeatedly.cs 的Update方法中实现。核心流程如下:

private void Update(EvaluationContext context) { _callsSinceLastRefresh++; var repeatCount = RepeatCount.GetValue(context).Clamp(0, 100); if (repeatCount <= 0) return; var skipFrames = SkipFrameCount.GetValue(context).Clamp(0, 10000); if (_callsSinceLastRefresh <= skipFrames) return; _callsSinceLastRefresh = 0; var commands = Command.CollectedInputs; // 1. 准备阶段:调用所有命令的 PrepareAction for (int i = 0; i < commands.Count; i++) commands[i].Value?.PrepareAction?.Invoke(context); // 2. 执行阶段:重复 repeatCount 次,每次遍历所有命令取 GetValue for (int repeation = 0; repeation < repeatCount; repeation++) { for (int i = 0; i < commands.Count; i++) commands[i].GetValue(context); } // 3. 清理阶段:调用所有命令的 RestoreAction for (int i = 0; i < commands.Count; i++) commands[i].Value?.RestoreAction?.Invoke(context); Command.DirtyFlag.Clear(); }

三段式命令生命周期

与 Command.cs 中定义的PrepareAction/RestoreAction委托对应,ExecRepeatedly 严格遵循"准备 → 执行 → 清理"的三段式生命周期:先通过PrepareAction完成前置准备,再按RepeatCount循环取用命令值,最后以RestoreAction恢复上下文。这种结构保证了即便重复执行多次,命令的副作用也能被正确归位。

计数器语义:触发后立即重置

值得注意的实现细节:_callsSinceLastRefresh在执行前被重置为 0,而判定条件是<= skipFrames。因此:

  • SkipFrameCount = 0时,每次调用计数为 1 > 0,每帧都执行
  • SkipFrameCount = 2时,第 1、2 次调用被跳过,第 3 次触发执行,形成"每 3 帧执行一次"的节奏;
  • 触发当帧本身也算作一次调用,因此实际执行周期为SkipFrameCount + 1帧。

触发语义:逐帧持续触发

与 ExecuteOnce.cs(仅在Trigger输入变脏时执行一次,并向外暴露OutputTrigger)不同,ExecRepeatedly 没有外部触发输入,只要计数器条件满足就会持续执行,属于节流型持续执行器而非一次性触发器。

与同族操作符的定位对比

Lib.flow流程控制家族中,ExecRepeatedly 与以下操作符承担不同职责,选型时可对照:

操作符核心职责关键输入典型用途
ExecRepeatedly控制子图执行频率RepeatCount、SkipFrameCount加速/减速模拟、抽帧优化
Execute按使能开关执行子图Command、IsEnabled分组、启停部分图(见 Execute.cs)
ExecuteOnce仅在触发时执行一次Command、Trigger初始化缓冲、重置状态(见 ExecuteOnce.cs)
Loop循环迭代子图并暴露索引/进度变量Command、Count、IndexVariable、ProgressVariable迭代绘制函数(见 Loop.cs)
  • 若只想"每帧执行"或"按开关执行",用Execute
  • 若想"只在某个信号触发时跑一次",用ExecuteOnce
  • 若想"在一帧内按变量迭代多次",用Loop
  • 若想"以可控频率反复执行"(含重复多次与抽帧两种模式),用ExecRepeatedly

典型实战场景

场景一:加速模拟

把粒子系统、弹簧动画等模拟子图接入Command,将RepeatCount设为 3~10(注意源码钳制上限 100),即可让同一帧内模拟步进多次,产生"时间加速"效果。适合用于爆炸、快速生长等需要数倍速模拟的画面。

场景二:减速 / 抽帧执行

RepeatCount保持为 1,SkipFrameCount设为 4,则子图每 5 帧才执行一次,常用于低频更新的辅助逻辑(如远程数据轮询、低优先级刷新),在不影响主渲染的前提下显著降低每帧计算开销。

场景三:结合 Command 生命周期做受控资源更新

由于 ExecRepeatedly 遵循 Prepare/Execute/Restore 生命周期,即使RepeatCount > 1,也能安全用于需要成对准备与恢复的资源更新场景,不会因多次执行破坏上下文状态。

使用建议与注意事项

  1. 合理利用钳制范围RepeatCount上限 100、SkipFrameCount上限 10000,超限值会被静默截断,设计参数动画(如用曲线驱动这两个输入)时注意范围。
  2. 组合使用:可将 ExecRepeatedly 与Loop嵌套,先节流外层频率、再在单次触发内迭代,形成"低频 + 多次"的复合节奏。
  3. 默认值即逐帧执行:新建节点时RepeatCount = 1SkipFrameCount = 0,行为等价于普通逐帧执行,可放心作为起点逐步调整。
  4. 性能权衡:加速模拟的本质是用单帧 CPU 时间换取更多模拟步进,RepeatCount过大可能拉长单帧耗时,建议结合实际帧率(TiXL 的Playback.LastFrameDuration类时序数据)逐步调试。

参考资源

  • 官方算子文档:.help/docs/operators/lib/flow/ExecRepeatedly.md、.help/docs/operators/lib/flow/README.md
  • 核心实现:Operators/Lib/Symbols/flow/ExecRepeatedly.cs
  • 默认配置:Operators/Lib/Symbols/flow/ExecRepeatedly.t3
  • 命令数据类型:Core/DataTypes/Command.cs
  • 同族操作符:Execute.cs、ExecuteOnce.cs、Loop.cs

【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询