UE蓝图 分支(Branch)节点和源码

系列文章目录

UE蓝图 Get节点和源码
UE蓝图 Set节点和源码
UE蓝图 Cast节点和源码
UE蓝图 分支(Branch)节点和源码


文章目录

  • 系列文章目录
  • 一、分支节点功能
  • 二、分支节点用法
  • 三、分支节点使用场景
  • 四、分支节点实现过程
  • 五、分支节点相关源码


一、分支节点功能

在这里插入图片描述

在Unreal Engine(UE)的蓝图中,Branch节点是一个非常重要的的逻辑控制节点,它允许你根据某个条件(Condition)的真假来执行不同的逻辑路径。这个节点在编程中相当于一个if-else语句,用于控制程序的流程。

在UE蓝图中使用Branch节点时,你通常会连接一个布尔值(Boolean)到节点的Condition引脚。这个布尔值可以是来自其他节点的输出,也可以是一个固定的值(如true或false)。然后,你可以在IfTrueIfFalse两个输出引脚上连接你想要执行的操作或逻辑。

  • 如果Condition引脚接收到的值为true,那么从IfTrue引脚引出的逻辑将会被执行。
  • 如果Condition引脚接收到的值为false,那么从IfFalse引脚引出的逻辑将会被执行。

这样,你就可以根据不同的条件来动态地改变你的游戏或应用程序的行为。这在制作交互式游戏、响应玩家输入、处理不同的事件场景等方面都非常有用。


二、分支节点用法

在Unreal Engine(UE)的蓝图中使用分支节点,你需要按照以下步骤进行操作:

  1. 创建分支节点:首先,在蓝图中右击,选择“流程控制” -> “分支”来创建一个分支节点。这将添加一个具有条件(Condition)输入和两个输出引脚(True和False)的节点。

  2. 连接条件输入:接下来,你需要将一个布尔值或表达式连接到分支节点的Condition输入引脚。这个布尔值或表达式的结果将决定分支节点执行哪个分支。

  3. 设置True分支:在分支节点的True输出引脚上,你可以连接任何你希望在条件为真时执行的逻辑或操作。这可以是一个函数调用、变量设置、另一个逻辑节点等。

  4. 设置False分支:同样,在分支节点的False输出引脚上,你可以连接在条件为假时应该执行的逻辑或操作。

  5. 编译和测试:完成节点设置后,确保你的蓝图没有编译错误,并在游戏中测试分支节点的行为。你可以通过改变连接到Condition引脚的值来验证分支是否正确执行。

  6. 调试和优化:如果分支节点的行为不符合预期,使用UE的调试工具来查找问题并进行相应的调整。

记住,分支节点的行为完全依赖于Condition引脚的输入值。确保你的条件表达式正确无误,并且连接到正确的引脚。此外,分支节点通常用于控制程序的流程,因此确保你的逻辑流程符合你的游戏或应用程序的需求。

三、分支节点使用场景

Unreal Engine(UE)蓝图中的分支节点(Branch Node)具有广泛的应用场景,主要用于实现条件逻辑,让游戏或应用程序的行为能够根据不同的条件进行变化。以下是一些具体的应用场景示例:

  1. 玩家交互与决策:在游戏中,分支节点可以用于处理玩家的交互和决策。例如,玩家面对一个选择时,分支节点可以根据玩家的选择(由输入事件触发)来执行不同的游戏逻辑,如不同的对话路径、任务结果或游戏事件。

  2. AI行为树:在AI行为树中,分支节点用于决定AI角色的行为。根据环境状态、目标优先级或其他条件,分支节点可以帮助AI选择最合适的行动方案,如巡逻、搜寻、攻击或逃跑。

  3. 游戏事件与状态管理:在游戏逻辑中,分支节点可用于处理游戏事件和状态的变化。例如,根据玩家的当前状态(如健康值、能量水平或武器状态)来执行不同的游戏逻辑,如允许或禁止某些操作,或触发特定的事件。

  4. 条件性任务执行:在任务或剧情流程中,分支节点允许开发者根据任务条件(如任务状态、玩家行为或环境变量)来执行不同的任务步骤或结果。这有助于创建更丰富、更灵活的剧情体验。

  5. 网络和多玩家交互:在多人在线游戏中,分支节点可以用于处理网络状态、玩家状态或其他玩家的行为。根据这些条件,游戏可以执行不同的逻辑,如同步玩家状态、处理网络延迟或处理玩家间的交互。

  6. 动态环境交互:在动态环境中,分支节点可用于处理与环境的交互。例如,根据物体的状态(如是否被破坏、是否被拾取等)来执行不同的逻辑,如改变环境状态、播放音效或触发其他事件。

在这些场景中,分支节点的灵活性使得开发者能够根据游戏或应用程序的具体需求来创建复杂的逻辑结构,从而实现更加丰富和动态的用户体验。通过组合不同的节点类型和条件判断,开发者可以构建出各种复杂的条件分支逻辑。

四、分支节点实现过程

  • 创建输入输出引脚
public void allocateDefaultPins() {
    createPin(EGPD_Input, EdGraphSchemaK2.PC_Exec, EdGraphSchemaK2.PN_Execute);
    EdGraphPin conditionPin = createPin(EGPD_Input, EdGraphSchemaK2.PC_Boolean, EdGraphSchemaK2.PN_Condition);
    EdGraphPin truePin = createPin(EGPD_Output, EdGraphSchemaK2.PC_Exec, EdGraphSchemaK2.PN_Then);
    EdGraphPin falsePin = createPin(EGPD_Output, EdGraphSchemaK2.PC_Exec, EdGraphSchemaK2.PN_Else);
    super.allocateDefaultPins();
}
  • 调用KCHandler_Branch 注册net

  • 编译创建分支Statement

// First skip the if, if the term is false
FBlueprintCompiledStatement& SkipIfGoto = Context.AppendStatementForNode(Node);
SkipIfGoto.Type = KCST_GotoIfNot;
SkipIfGoto.LHS = *CondTerm;
Context.GotoFixupRequestMap.Add(&SkipIfGoto, ElsePin);

// Now go to the If branch
FBlueprintCompiledStatement& GotoThen = Context.AppendStatementForNode(Node);
GotoThen.Type = KCST_UnconditionalGoto;
GotoThen.LHS = *CondTerm;
Context.GotoFixupRequestMap.Add(&GotoThen, ThenPin);

五、分支节点相关源码

源码文件:
K2Node_IfThenElse.h
K2Node_IfThenElse.cpp
相关类:
KCHandler_Branch
UK2Node_IfThenElse


class FKCHandler_Branch : public FNodeHandlingFunctor
{
public:
	FKCHandler_Branch(FKismetCompilerContext& InCompilerContext)
		: FNodeHandlingFunctor(InCompilerContext)
	{
	}

	virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override
	{
		// For imperative nodes, make sure the exec function was actually triggered and not just included due to an output data dependency
		FEdGraphPinType ExpectedExecPinType;
		ExpectedExecPinType.PinCategory = UEdGraphSchema_K2::PC_Exec;

		FEdGraphPinType ExpectedBoolPinType;
		ExpectedBoolPinType.PinCategory = UEdGraphSchema_K2::PC_Boolean;


		UEdGraphPin* ExecTriggeringPin = Context.FindRequiredPinByName(Node, UEdGraphSchema_K2::PN_Execute, EGPD_Input);
		if ((ExecTriggeringPin == NULL) || !Context.ValidatePinType(ExecTriggeringPin, ExpectedExecPinType))
		{
			CompilerContext.MessageLog.Error(*LOCTEXT("NoValidExecutionPinForBranch_Error", "@@ must have a valid execution pin @@").ToString(), Node, ExecTriggeringPin);
			return;
		}
		else if (ExecTriggeringPin->LinkedTo.Num() == 0)
		{
			CompilerContext.MessageLog.Warning(*LOCTEXT("NodeNeverExecuted_Warning", "@@ will never be executed").ToString(), Node);
			return;
		}

		// Generate the output impulse from this node
		UEdGraphPin* CondPin = Context.FindRequiredPinByName(Node, UEdGraphSchema_K2::PN_Condition, EGPD_Input);
		UEdGraphPin* ThenPin = Context.FindRequiredPinByName(Node, UEdGraphSchema_K2::PN_Then, EGPD_Output);
		UEdGraphPin* ElsePin = Context.FindRequiredPinByName(Node, UEdGraphSchema_K2::PN_Else, EGPD_Output);
		if (Context.ValidatePinType(ThenPin, ExpectedExecPinType) &&
			Context.ValidatePinType(ElsePin, ExpectedExecPinType) &&
			Context.ValidatePinType(CondPin, ExpectedBoolPinType))
		{
			UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(CondPin);
			FBPTerminal** CondTerm = Context.NetMap.Find(PinToTry);

			if (CondTerm != NULL) //
			{
				// First skip the if, if the term is false
				{
					FBlueprintCompiledStatement& SkipIfGoto = Context.AppendStatementForNode(Node);
					SkipIfGoto.Type = KCST_GotoIfNot;
					SkipIfGoto.LHS = *CondTerm;
					Context.GotoFixupRequestMap.Add(&SkipIfGoto, ElsePin);
				}

				// Now go to the If branch
				{
					FBlueprintCompiledStatement& GotoThen = Context.AppendStatementForNode(Node);
					GotoThen.Type = KCST_UnconditionalGoto;
					GotoThen.LHS = *CondTerm;
					Context.GotoFixupRequestMap.Add(&GotoThen, ThenPin);
				}
			}
			else
			{
				CompilerContext.MessageLog.Error(*LOCTEXT("ResolveTermPassed_Error", "Failed to resolve term passed into @@").ToString(), CondPin);
			}
		}
	}
};

UK2Node_IfThenElse::UK2Node_IfThenElse(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

void UK2Node_IfThenElse::AllocateDefaultPins()
{
	const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();

	CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
	UEdGraphPin* ConditionPin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Boolean, UEdGraphSchema_K2::PN_Condition);
	K2Schema->SetPinAutogeneratedDefaultValue(ConditionPin, TEXT("true"));

	UEdGraphPin* TruePin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
	TruePin->PinFriendlyName =LOCTEXT("true", "true");

	UEdGraphPin* FalsePin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Else);
	FalsePin->PinFriendlyName = LOCTEXT("false", "false");

	Super::AllocateDefaultPins();
}

FText UK2Node_IfThenElse::GetNodeTitle(ENodeTitleType::Type TitleType) const
{
	return LOCTEXT("Branch", "Branch");
}

FLinearColor UK2Node_IfThenElse::GetNodeTitleColor() const
{
	return GetDefault<UGraphEditorSettings>()->ExecBranchNodeTitleColor;
}

FSlateIcon UK2Node_IfThenElse::GetIconAndTint(FLinearColor& OutColor) const
{
	static FSlateIcon Icon("EditorStyle", "GraphEditor.Branch_16x");
	return Icon;
}

FText UK2Node_IfThenElse::GetTooltipText() const
{
	return LOCTEXT("BrancStatement_Tooltip", "Branch Statement\nIf Condition is true, execution goes to True, otherwise it goes to False");
}

UEdGraphPin* UK2Node_IfThenElse::GetThenPin() const
{
	UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Then);
	check(Pin);
	return Pin;
}

UEdGraphPin* UK2Node_IfThenElse::GetElsePin() const
{
	UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Else);
	check(Pin);
	return Pin;
}

UEdGraphPin* UK2Node_IfThenElse::GetConditionPin() const
{
	UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Condition);
	check(Pin);
	return Pin;
}

FNodeHandlingFunctor* UK2Node_IfThenElse::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{
	return new FKCHandler_Branch(CompilerContext);
}

void UK2Node_IfThenElse::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that 
	// actions might have to be updated (or deleted) if their object-key is  
	// mutated (or removed)... here we use the node's class (so if the node 
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();
	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first   
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the 
	// registrar would only accept actions corresponding to that asset)
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
		check(NodeSpawner != nullptr);

		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
	}
}

FText UK2Node_IfThenElse::GetMenuCategory() const
{
	return FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::FlowControl);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/397441.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QGis软件 —— 6、QGis - 线与点相互转化操作

线转为点 1、创建一条线 2、对线用点进行分割&#xff0c;由于下图单位是"度" 那么需要对该图层做重投影。 3、对线做"重投影图层"操作 4、对线用点进行分割 点转为线 将点转为线&#xff0c;如下动图。通常用作于外出人员采集gps点后通过csv文件导入qgis&…

ChatGPT-01 用ChatGPT指令,自学任何领域的系统知识

1. 指令位置 Github仓库&#xff1a;Mr Ranedeer AI Tutor 但是需要开通chatgtp plus版本&#xff0c;并且打开代码解释器 2 使用 学习内容 开始学习 GPT甚至可以给你思考题&#xff0c;给出的答案还能进行评价 配置 通过配置表修改 深度 学习风格 沟通风格 语气风格 …

【Python机器学习】详解Python机器学习进行时间序列预测

&#x1f517; 运行环境&#xff1a;Python &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

适合tiktok运营的云手机需要满足什么条件?

TikTok作为一款全球热门的社交媒体平台&#xff0c;具有无限的市场潜力。然而&#xff0c;卖家在运营过程中常常会面临到视频0播、账号被降权、限流等问题&#xff0c;甚至可能因为多人同时使用一个IP而导致封号的风险。为了规避这些问题&#xff0c;越来越多的卖家将目光投向了…

领先一步:2024年大广赛设计趋势预测

2024年大赛已经开始&#xff01;作为最具影响力的学科竞赛项目之一&#xff0c;中国大学生好创意全国大学生广告艺术大赛&#xff08;以下简称“大广赛”&#xff09;自2005年以来已举办12届13届大赛&#xff0c;是权威机构认可的以“创意”为核心理念、以“创新”为教育目标的…

JavaScript数据类型学习脑图

字符串&#xff08;String&#xff09;、数字(Number)、布尔(Boolean)、数组(Array)、对象(Object)、空&#xff08;Null&#xff09;、未定义&#xff08;Undefined&#xff09;

红队学习笔记Day6 --->干货分享

今天看到这样的一个东西&#xff0c;好好好&#xff0c;有点恐怖&#x1f613;&#x1f613;&#x1f631;&#x1f631;&#x1f631;&#x1f631; 我就想网安是不是也有这种东西&#xff1f; 我来试试 icmp&#xff0c;RDP&#xff0c;arp&#xff0c;dhcp&#xff0c;nat&a…

Unity基于AssetBundle资源管理流程详解

在Unity游戏开发中&#xff0c;资源管理是一个非常重要的环节。随着游戏的发展&#xff0c;资源会变得越来越庞大&#xff0c;因此需要一种高效的资源管理方式来减少内存占用和加快加载速度。AssetBundle是Unity提供的一种资源打包和加载方式&#xff0c;可以将资源打包成一个独…

GIS分析-绘制土壤水分图

土壤水分是水文循环的一个重要单元,影响着地下水补给(或深层渗透)和地表径流的水量。此外,土壤水分分析在评估土地退化、荒漠化和洪水方面也发挥着至关重要的作用。土壤水分通常是在野外通过定点测量来确定的,但这种方法虽然结果准确,但却费力费钱。在本研究中,我们将通…

vue3实现瀑布流布局组件

先看效果图 直接上代码 utils.js // 用于模拟接口请求 export const getRemoteData (data 获取数据, time 2000) > {return new Promise((resolve) > {setTimeout(() > {console.log(模拟获取接口数据, data)resolve(data)}, time)}) }// 获取数组随机项 export…

App启动优化笔记 1

app大致的启动流程。有Launcher进程,system_server进程,zygote进程,APP进程。 Launcher进程:启动activity来启动应用 system_server进程:(ams是其中的一个binder):发送一个socket消息给Zygote。 zygote进程:收到消息后,fork新的进程,---》app进程启动 APP进程:…

TRIZ理论下的新能源电机革新之路

随着全球能源结构的转型和环保理念的深入人心&#xff0c;新能源电机作为绿色能源的重要组成部分&#xff0c;正受到越来越多的关注。本文将从TRIZ理论的角度出发&#xff0c;探讨新能源电机的创新与发展。 TRIZ&#xff0c;即发明问题解决理论&#xff0c;是一种创新方法论&am…

期刊LaTeX模板下载

文章目录 期刊LaTeX模板下载1.通过overleaf模板库下载2.通过期刊官网下载2.1 IEEE期刊论文LaTeX模板的查找下载2.2 Elsevier期刊论文LaTeX模板的查找下载 期刊LaTeX模板下载 IEEE期刊模板下载地址&#xff1a;https://template-selector.ieee.org/secure/templateSelector/pub…

木头姐2024 重磅产业调研与预测报告(163页)

感兴趣的小伙伴自取&#xff1a; 木头姐2024 重磅产业调研与预测报告(163页)

openGauss 5.0.0全密态数据库应用小试

前言 openGauss HCIA教材中&#xff0c;安全是一个重要的章节&#xff0c;在实际项目中&#xff0c;随着网络安全和信息安全形势的变化&#xff0c;企业也越来越重视数据库安全。去年在HALP内部进行openGauss培训时&#xff0c;安全特性就被学员们提出来要重点讲解&#xff0c…

【4.1计算机网络】TCP-IP协议簇

目录 1.OSI七层模型2.常见协议及默认端口3.TCP与UDP的区别 1.OSI七层模型 osi七层模型&#xff1a; 1.应用层 2.表示层 3.会话层 4.传输层&#xff1a;TCP为可靠的传输层协议。 5.网络层 6.数据链路层 7.物理层 2.常见协议及默认端口 3.TCP与UDP的区别 例题1. 解析&#xff1…

层级关联,审批人功能

一个需求要求选择一级&#xff0c;下方展示一级的效果 后端给了审批人数据&#xff0c;但是数据需要单独处理 <template><div class"box"><el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"…

AI新工具(20240219) Ollama Windows预览版;谷歌开源的人工智能文件类型识别系统; PopAi是您的个人人工智能工作空间

Ollama Windows preview - Ollama Windows预览版用户可以在本地创建和运行大语言模型&#xff0c;并且支持NVIDIA GPU和现代CPU指令集的硬件加速 Ollama发布了Windows预览版&#xff0c;使用户能够在原生的Windows环境中拉取、运行和创建大语言模型。该版本支持英伟达的GPU&am…

iOS整理 - 关于直播 - 搭建服务端

前言 其实本人一直都想自己简单做一套直播&#xff08;包括移动端和服务端&#xff09;的开发测试&#xff0c;但是之前一直做得比较迷茫。最近偶然间在来了灵感&#xff0c;瞬间解除了我很多疑惑。我会分享出来&#xff0c;希望大家一起研究下。稍后&#xff0c;我完整做好了…

车载氢气浓度传感器为氢能源车保驾护航

最近&#xff0c;车载氢气浓度传感器成为了一个热门话题。作为一名对科技充满热情的汽车爱好者&#xff0c;我自然也对这个话题产生了浓厚的兴趣。那么&#xff0c;车载氢气浓度传感器到底是什么&#xff1f;它又是如何工作的呢&#xff1f;下面就让我为你一一揭秘。 首先&…