Skip to main content

Impulses(脉冲)

Impulses (脉冲)

Impulses(脉冲),有时也被称为 Calls(调用),是 ProtoFlux ExecutionContext(执行上下文)中的离散动作,也是构建程序时两种基本链路类型之一。与通常彼此连续的节点输入输出链相反,脉冲沿着脉冲链推动任务执行,这非常像传统的 命令式编程

概览 (Overview)

在 ProtoFlux 的 ExecutionContext 及其衍生环境中,执行离散动作的节点需要一个脉冲来执行。例如,Duplicate Slot(复制插槽)不能想触发就触发——这样将无法控制。因此,使用一个类型为 Call 的特殊输入端口 * 来触发该动作。然后,该链路可以通过 Next 输出端继续延伸。

当一个动作节点接收到一个脉冲时,它会评估连接到该节点的所有“非脉冲”输入。这确立了脉冲与其他节点链路之间的关系:脉冲“推动”任务执行,而动作节点“拉取”它们的输入(这些输入可能又会拉取它们的输入,依此类推,直到可以评估原始输入为止)。

默认情况下,脉冲在 ProtoFlux 中是本地运行时(Local Runtime)的。但是,如果以任何方式与 FrooxEngineData Model(数据模型)进行交互,它们执行的动作将在用户之间同步。这包括但不限于:Write(写入)到一个非驱动的 SyncField(同步字段)、管理 Slots(插槽),以及设置非驱动的 Dynamic Variables(动态变量)。

脉冲可以来自多种来源。最常见的是,在构建 ProtoFlux 时,可以通过拖出脉冲输入并按下 Secondary(副按键)来创建一个 Call Input(调用输入)。脉冲也可以来自 Events(事件),或者在接收到某种信号后开始的脉冲链。这些包括但不限于 Dynamic Impulses(动态脉冲)、Button Events(按钮事件)、Fire On True 事件以及 World/Item Events(世界/物品事件)。

上下文 (Context)

脉冲依附于 ExecutionContext(执行上下文)的一个特定实例。这不要与 ProtoFlux 中的广义 Contexts(上下文)概念混淆,因为所有脉冲都来自 ExecutionContext,这里的上下文特指脉冲所看到的特定数值和变量

上下文由原始脉冲的触发器拾取,并在链路完成之前一直携带。上下文在整个链路期间携带某些值,包括 Local Values(局部值)和动作节点的输出。在它们被使用的特定上下文(以及嵌套上下文)之外,是不可能访问这些上下文敏感值的底层数据的。

当脉冲在同一个 Node Group(节点组)中传递时,上下文会被保留;如果与不同的节点组断开执行连接,上下文则会丢失。节点组是指所有通过某种方式连接在一起的节点,无论是通过直接的连线连接,还是通过对另一个节点的引用(例如 Write 节点引用变量)。

示例说明:

例如,如果一个 Dynamic Impulse(动态脉冲)被触发,而该动态脉冲又触发了另一个动态脉冲,这第三个动态脉冲写入了一个 Local(局部变量),那么第一个动态脉冲触发器的 Next 路径将无法看到这个更改。

这是因为在第一个动态脉冲被触发后,执行离开了第一个触发器的节点组,导致第二个动态脉冲不在初始链路的同一个上下文中。

但是,如果第二个动态脉冲写入的是同一个 Local(且通过连线或引用保持了节点组连接),那么所有节点组都是连接的,初始的 Next 路径将会看到这个更改。

脉冲流 (Impulse flow)

脉冲流决定了脉冲如何相对于引擎的运行时进行执行。有两种类型的脉冲流:非异步(Non-async)异步(Async)

一个非异步脉冲链将在一次引擎更新(Update)中完全运行完毕,期间会阻塞引擎直到完成。如果脉冲执行了在用户之间同步的动作,只有引擎更新结束时与初始状态的差异(Delta)会被同步。例如,如果在一次非异步脉冲链中复制并移除了大量插槽,网络上将不会同步任何数据(因为结果互相抵消了)。

异步 (Async)

当一个动作有可能需要多次引擎更新才能完成时,就需要使用 Async(异步)脉冲流。否则,节点链将抛出异常并拒绝执行。

异步脉冲流通常与普通脉冲流相同,但增加了可以随意挂起(Suspend)恢复(Resume)特定执行链的灵活性。本质上,这是 ProtoFlux 在语言中使用 协程 的方式。你可以使用诸如 Delay(延迟)之类的节点显式挂起执行,或者在恢复执行之前隐式等待动作完成,例如使用 Play One Shot And Wait 节点。

异步脉冲流能够在多次引擎更新中保留局部变量(Locals)和动作节点的输出,这在普通脉冲流中是不可能做到的。

  • Start Async Task(启动异步任务): 可以使用 Start Async Task 节点从普通脉冲链启动异步脉冲链。该节点实际上在 OnTriggered 处创建了一个分支的(Branched)ExecutionContext,该上下文与其触发源的上下文不同。触发它的 ExecutionContext 使用的每个值都会被复制到新上下文中,但在那之后,两个上下文都无法影响对方。
  • 共享上下文的异步节点: 相比之下,所有其他异步节点都共享相同的上下文。例如,在 Delay 节点的 OnTriggered 链中修改的局部变量将会反映在该节点的 Next 链中,反之亦然。这就是异步脉冲流如此强大的原因。

如果使用 ProtoFlux 处理大量数据,使用异步脉冲流并将执行分散到多个帧中可能是理想的选择,因为这可以防止执行时出现巨大的帧率卡顿(尽管总耗时会稍微长一点)。

参见 (See Also)