FlowCanvas官方文档翻译(三)

5. Macros 宏

宏是一组复合到一个可重用的流程脚本中的节点,可以在任何其他流程脚本中作为一个整体使用...宏,并且总是保存为项目中的.asset文件。
宏是一个非常强大的功能,组织和可重复使用的视觉脚本为您的项目,甚至与其他人轻松分享!

5.1. Creating Macros  创建宏

创建宏可以通过两种方式完成。 通过“添加节点”上下文菜单和“MACROS /创建新...”选项,或通过右键单击Unity项目面板并选择“创建/新建/宏”。 在任一情况下,将弹出一个“另存为”窗口,您可以选择在项目中保存新宏资产文件的位置。

MacroCreateContext

编辑新创建的宏可以通过在项目面板中选择它,或者双击在流程图中添加的宏来完成,在这种情况下,它将打开内联到您的流程图。
每个新创建的宏,将带有已经创建的2个非常重要的节点,那些是宏输入和宏输出。

MacroInit

正如他们建议的那样,这两个节点有定义宏具有的所有输入和输出。 点击宏输入节点,你可以通过它的节点检查器来定义宏的各种输入端口,类似的,也可以通过点击宏输出节点来完成。 在以下示例中,定义了4个不同的输入端口。 2称为“调用”和“断点”的流输入,以及2个值输入,一个是整数,另一个是布尔类型。

MacroDefine

定义新宏端口的另一种方法是将另一个节点的端口拖放到宏输入或宏输出节点之上,如下所示。 您也可以对输出端口执行相同操作,并且您可以随时重新命名端口。

MacroPromote

5.2. Using Macros 使用宏

创建宏后,可以将其添加到要使用的任何流程脚本中。 将现有宏添加到流程脚本中可以通过“添加节点”上下文菜单和“MACROS”类别下,或通过将宏文件拖放到流脚本画布中。
一旦宏被放置在流程脚本中,它的所有定义的输入和输出(如前所述)将暴露给您使用和连接。 例如,下面的宏(即使它没有真正做太多)...,

MacroDone

...在流程图中添加时,将看起来像这样。

MacroInFS

再次,双击宏节点,将打开它以供您编辑。
宏还有自己的局部变量,它只能用于宏的范围内的内部数据保存。 当然,您可以通过输入端口自由设置这些变量,或者如果需要,通过输出端口使它们暴露。

MacroBlackboard

最后,这里有一些重要的事情要记住,当使用宏。

  • 因为宏总是.asset文件,它们不能在宏的节点内分配场景对象引用,但是您可以在宏流节点输入中使用场景对象引用。
  • 一般来说,在宏中不要有事件节点是明智的。 虽然它会工作正常,它不建议作为一个工作流。
  • 宏不需要具有流量输入和输出。 您可以删除创建新宏时自动添加的宏,如果您不需要它们。

6. Creating Custom Nodes 创建自定义节点

有三种可能的方法可以在FlowCanvas中创建节点。

  • 通过反射自动。
  • 编码单工节点。
  • 编码全节点。

6.1. Creating Simplex Nodes 创建单纯形节点

创建Simplex节点是为FlowCanvas创建自定义节点的最简单和直接的方法。 为此,您需要从一个可用的Simplex节点基本类型派生。

可调行动节点

可呼叫动作节点,意在创建需要调用流信号的动作。 它们有1个流量输入,1个流量输出,最多5个值输入参数,根本没有值输出。 简单地说,你派生的通用CallableActionNode类,其中通用参数表示节点的值输入参数,然后覆盖Invoke void方法,该方法具有与您声明的通用参数相同和相同类型的多个参数。 例如。

1
2
3
4
5
6
[Category("Actions/Utility")]
public class LogValue : CallableActionNode<object>{
 public override void Invoke(object obj){
 Debug.Log(obj);
 }
}

可调用函数节点

可调用函数节点类似于上面的可调用动作,但它们总是返回1 Value输出。 该过程与之前非常相似,但是在这种情况下,第一个泛型参数表示返回值的类型,而您要重写的Invoke方法将需要返回该类型声明。 例如。

1
2
3
4
5
6
 [Category("Examples")]
 public class FindTransform : CallableFunctionNode<Transform, Transform, string>{
 public override Transform Invoke(Transform root, string name){
 return root != null? root.Find(name) : null;
 }
 }

潜在操作节点

潜在动作节点类似于之前的CallableAction节点,但在这种情况下,Invoke方法是一个IEnumerator,并被称为协程。 因此,您需要将其视为协同程序。 例如。

1
2
3
4
5
6
7
8
9
10
[Category("Actions/Utility")]
public class Wait : LatentActionNode<float>{
 public override IEnumerator Invoke(float time){
 var timer = time;
 while (timer > 0){
 timer -= Time.deltaTime;
 yield return null;
 }
 }
}

纯函数节点

纯函数节点,用于不需要任何流量信号的节点,而是在它们通过它们具有的单个值输出请求时简单地返回值。 第一个泛型参数是节点的返回类型和您需要覆盖的Invoke方法,而其余的泛型参数是要使用的函数的值输入参数。 例如。

1
2
3
4
5
6
7
[Category("Functions/Math/Floats")]
[Name("!=")]
public class FloatNotEqual : PureFunctionNode<bool, float, float>{
 public override bool Invoke(float a, float b){
 return a != b;
 }
}

6.2. Creating Full Nodes 创建完整节点

创建完整的流节点可能有点难以理解,但您可以完全访问一切,并且可以创建任何类型的节点,例如新的事件,流控制器或任何其他,虽然我个人建议这样做 仅限事件和流量控制器。
让我们举一个例子来重新创建一个FlowController节点,“SwitchBool”,实际上是一个if-then-else语句。 为此,创建一个类并从“FlowControlNode”派生,然后必须覆盖RegisterPorts方法并注册其中的端口。
使用以下方法注册端口:

FlowInput : AddFlowInput(string name, Action pointer)
name: 端口的名称。
pointer:调用此流输入时将调用的委托。

FlowOutput: AddFlowOutput(string name)
name: 端口的名称。
要执行端口,您必须在返回的FlowOutput对象上调用Call(),以及接收到的当前Flow对象。

ValueInput<T> : AddValueInput<T>(string name)
name: 端口的名称。
要获取连接到端口的值,只需调用返回的对象的.value属性。

ValueOutput<T> : AddValueOutput<T>(string name, Func<T> getter)
name: 端口的名称。
getter:将被调用以获取类型T的值的委托。

在实践中它比它听起来容易...

原文地址:https://www.cnblogs.com/yeting-home/p/6409651.html