Skip to main content

有关Impulses(脉冲)以及脚本同步问题

Impulses (脉冲)

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

概述

在 ProtoFlux 的 ExecutionContext 及其衍生内容中,执行离散动作的节点需要一个脉冲来执行。例如,复制插槽 不能随心所欲地触发——控制这样的事情是不可能的。因此,使用一个特殊的 Call 类型输入 * 来触发该动作。然后可以通过 Next 输出继续该链。

当动作节点接收到脉冲时,它会评估连接到该节点的所有非脉冲输入。这具体化了脉冲与其他节点链之间的关系:脉冲推动任务执行,而动作节点拉取其输入,输入可能再拉取它们的输入,依此类推,直到原始输入被评估。

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

脉冲可以来自多种来源。最常见的是,在构建 ProtoFlux 时,可以通过拖出脉冲输入并按 次要动作键 来创建 Call Input。脉冲也可能来自“事件”,即接收到某种信号后开始的脉冲链。这些包括但不限于:动态脉冲按钮事件Fire On True 以及 世界/物品事件

上下文 (Context)

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

上下文由原始脉冲的触发器拾取并携带,直到链完成。上下文在链的整个持续期间携带某些值,包括 本地值 (Locals) 和动作节点的输出。在其使用的特定上下文(和嵌套上下文)之外,不可能访问这些上下文敏感值的底层值。

当通过同一个“节点组”时,上下文会被保留;如果执行断开连接到不同的节点组,上下文则会丢失。节点组是以某种方式连接的所有节点,无论是通过直接连线还是通过对另一个节点的引用(例如引用变量的写入节点)。

例如,如果触发了一个动态脉冲,而该动态脉冲触发了另一个动态脉冲,且第三个动态脉冲写入本地变量,那么第一个动态脉冲触发器的 Next 路径将不会看到该更改。这是因为在第一个动态脉冲触发后,执行离开了第一个触发器的节点组,导致第二个动态脉冲不在与初始链相同的上下文中。如果第二个动态脉冲写入同一个本地变量,则所有节点组都已连接,初始 Next 路径看到该更改。

脉冲流 (Impulse flow)

脉冲流决定了脉冲如何相对于引擎运行时执行。有两种类型的脉冲流:非异步和异步。

异步脉冲链将完全在一个引擎更新(帧)中运行,在此期间引擎会暂停直到完成。如果脉冲执行了跨用户同步的动作,则仅同步初始状态与引擎更新结束时的差异。例如,如果在一个非异步脉冲链中复制并删除了大量插槽,则不会通过网络同步任何数据。

异步 (Async)

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

异步脉冲流通常与普通脉冲流相同,但增加了可以随意挂起和恢复某些执行链的灵活性。本质上,这是 ProtoFlux 在语言中使用 协程 的方式。可以通过 Delay 等节点显式挂起执行,或者隐式等待动作完成后再恢复执行,例如使用 Play One Shot And Wait 节点。

异步脉冲流能够在多个引擎更新中保留本地变量和动作节点输出,这是普通脉冲流无法做到的。

可以使用 Start Async Task 节点从普通脉冲链启动异步脉冲链。该节点实际上在 OnTriggered 处创建了一个分支的执行上下文,该上下文与触发它的上下文不同。被触发的执行上下文使用的每个值都会复制到新上下文中,但在那之后,两个上下文都无法影响对方。

相比之下,所有其他异步节点共享相同的上下文。例如,在 Delay 节点的 OnTriggered 链中修改的本地变量反映在同一节点的 Next 链中,反之亦然(如果该节点在一个上下文中被触发两次)。这就是异步脉冲流如此强大的原因。

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

参见