UE4构建多输出执行引脚蓝图节点(同步节点与异步节点)

前言

在蓝图中,我们经常能看到一些节点具备多输出执行引脚(图一)。我们知道程序执行时,按照执行流程,根据给定的条件可以出现执行分支,在蓝图中使用Branch节点可以完成。但是在设计节点时(C++中),应该如何完成节点封装后,具备多输出执行引脚?这是问题的关键。

图一

首先,我们先认识下图一的节点

  • 普通C++中编写的蓝图函数节点,具有一个输出执行引脚
  • 注意,这是宏,在蓝图中编写,宏在构建时时可以加入多输入引脚与多输出引脚的。可直接在蓝图中产出
  • 在C++中构建的函数,具有多输出执行引脚
  • 在C++中构建的函数,具有多输出执行引脚

其中三条和四条的描述是一样,那是否它们是相同的呢?不然,第四个节点和第三个节点的最大区别在于:节点的右上角多了一个时钟标记。在蓝图中,这个标记代表节点是异步节点

所以节点三和四的最大区别在于执行时是否出现异步输出

C++中编写多输出执行引脚节点(非异步)

构建多输出执行引脚节点(同步)比较简单。

  • 构建枚举项,用来描述输出引脚名称
  • 编写函数,并标记为暴露到蓝图
  • 添加枚举参数,参数为引用方式
  • 增加导出枚举为执行引脚标记指令

构建枚举

1UENUM(BlueprintType)
2enum class EBlueprintExecNodePin : uint8
3{
4    Success,
5    Fail
6};

编写函数声明

1UFUNCTION(BlueprintCallable, meta=(ExpandEnumAsExecs="Result"))
2static void MultiExecNode(EBlueprintExecNodePin& Result);

构建函数定义

1void UMultiExecBPLibrary::MultiExecNode(EBlueprintExecNodePin& Result)
2{
3    //输出引脚,如果希望是Success,则直接赋值Result为Success,反之亦然
4    Result = EBlueprintExecNodePin::Success;
5}

C++中编写多输出执行引脚节点(异步)

异步蓝图节点构建要比其他蓝图节点编写稍微复杂些。首先在常规编码中,异步逻辑我们需要解决几个问题,第一回调函数的编写,第二在操作异步中不能释放掉调用对象,否则回调通知将会失败,第三构建异步线程,区别于当前逻辑线程。但是在蓝图中,虚幻引擎设计者简化了异步构建逻辑,将复杂性隐藏在C++中,使得我们操作的任何异步节点都非常的简单。(蓝图中是否可以构建异步节点,不在讨论范围,从角度来说,应该是不建议)

构建步骤

  • 编写C++类,继承UBlueprintAsyncActionBase类
  • 构建动态多播对象类型
  • 构建多播对象
  • 编写蓝图函数节点
  • 执行异步通知广播

编写C++类

你可以选择在创建类时继承BlueprintAsyncActionBase父类,或是在创建好的类中修改继承父类均可

图二

构建动态多播类型

动态多播代理类型构建时,可以选择带有参数,或是不带有参数。可根据实际设计意图进行设计!

1DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintAsyncNodePinResult, int32, Result);

构建多播对象

1UPROPERTY(BlueprintAssignable)
2FBlueprintAsyncNodePinResult OnSuccess;
3UPROPERTY(BlueprintAssignable)
4FBlueprintAsyncNodePinResult OnFail;

注意必须加标记宏指令,否则将无法在蓝图中被应用

编写蓝图函数节点

1UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
2static UBlueprintAsyncNode* AsyncDelay(float Delay);

BlueprintInternalUseOnly标记指令将函数对蓝图隐藏,只用于内部操作。意图:真正的蓝图异步节点是被特殊处理的,我们不能直接将此节点暴露到蓝图(大家可以尝试去掉后,将在蓝图中看到两个AsyncDelay节点),框架会将此函数进行再次设计,以提供到蓝图中使用。

现在编译就可以在蓝图中看到暴露的节点了

图三

编写异步蓝图节点当然并没有这么简单,我们只是单独阐述了过程,下篇文章(传送门)将细致讲解下如何编写异步蓝图节点

源码

头文件

 1// Fill out your copyright notice in the Description page of Project Settings.
 2 
 3#pragma once
 4 
 5#include "CoreMinimal.h"
 6#include "Kismet/BlueprintAsyncActionBase.h"
 7#include "BlueprintAsyncNode.generated.h"
 8 
 9DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBlueprintAsyncNodePinResult, int32, Result);
10/**
11 * 
12 */
13UCLASS()
14class UECPP_API UBlueprintAsyncNode : public UBlueprintAsyncActionBase
15{
16    GENERATED_BODY()
17 
18    UPROPERTY(BlueprintAssignable)
19    FBlueprintAsyncNodePinResult OnSuccess;
20    UPROPERTY(BlueprintAssignable)
21    FBlueprintAsyncNodePinResult OnFail;
22 
23    UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"))
24    static UBlueprintAsyncNode* AsyncDelay(float Delay);
25};

源文件

1// Fill out your copyright notice in the Description page of Project Settings.
2 
3#include "BlueprintAsyncNode.h"
4 
5UBlueprintAsyncNode* UBlueprintAsyncNode::AsyncDelay(float Delay)
6{
7    return nullptr;
8}

祝各位在虚幻中玩的愉快

虚幻版本 V4.21.2

文章评论