婚纱网站手机网站,网站开发 前端 外包,最新新闻热点事件2023年4月,中国新闻最新消息简要系列文章目录
UE蓝图 Get节点和源码 UE蓝图 Set节点和源码 UE蓝图 Cast节点和源码 UE蓝图 分支(Branch)节点和源码 文章目录 系列文章目录一、分支节点功能二、分支节点用法三、分支节点使用场景四、分支节点实现过程五、分支节点相关源码 一、分支节点功能 在Unreal EngineUE的蓝图中Branch节点是一个非常重要的的逻辑控制节点它允许你根据某个条件Condition的真假来执行不同的逻辑路径。这个节点在编程中相当于一个if-else语句用于控制程序的流程。
在UE蓝图中使用Branch节点时你通常会连接一个布尔值Boolean到节点的Condition引脚。这个布尔值可以是来自其他节点的输出也可以是一个固定的值如true或false。然后你可以在IfTrue和IfFalse两个输出引脚上连接你想要执行的操作或逻辑。
如果Condition引脚接收到的值为true那么从IfTrue引脚引出的逻辑将会被执行。如果Condition引脚接收到的值为false那么从IfFalse引脚引出的逻辑将会被执行。
这样你就可以根据不同的条件来动态地改变你的游戏或应用程序的行为。这在制作交互式游戏、响应玩家输入、处理不同的事件场景等方面都非常有用。 二、分支节点用法
在Unreal EngineUE的蓝图中使用分支节点你需要按照以下步骤进行操作 创建分支节点首先在蓝图中右击选择“流程控制” - “分支”来创建一个分支节点。这将添加一个具有条件Condition输入和两个输出引脚True和False的节点。 连接条件输入接下来你需要将一个布尔值或表达式连接到分支节点的Condition输入引脚。这个布尔值或表达式的结果将决定分支节点执行哪个分支。 设置True分支在分支节点的True输出引脚上你可以连接任何你希望在条件为真时执行的逻辑或操作。这可以是一个函数调用、变量设置、另一个逻辑节点等。 设置False分支同样在分支节点的False输出引脚上你可以连接在条件为假时应该执行的逻辑或操作。 编译和测试完成节点设置后确保你的蓝图没有编译错误并在游戏中测试分支节点的行为。你可以通过改变连接到Condition引脚的值来验证分支是否正确执行。 调试和优化如果分支节点的行为不符合预期使用UE的调试工具来查找问题并进行相应的调整。
记住分支节点的行为完全依赖于Condition引脚的输入值。确保你的条件表达式正确无误并且连接到正确的引脚。此外分支节点通常用于控制程序的流程因此确保你的逻辑流程符合你的游戏或应用程序的需求。
三、分支节点使用场景
Unreal EngineUE蓝图中的分支节点Branch Node具有广泛的应用场景主要用于实现条件逻辑让游戏或应用程序的行为能够根据不同的条件进行变化。以下是一些具体的应用场景示例 玩家交互与决策在游戏中分支节点可以用于处理玩家的交互和决策。例如玩家面对一个选择时分支节点可以根据玩家的选择由输入事件触发来执行不同的游戏逻辑如不同的对话路径、任务结果或游戏事件。 AI行为树在AI行为树中分支节点用于决定AI角色的行为。根据环境状态、目标优先级或其他条件分支节点可以帮助AI选择最合适的行动方案如巡逻、搜寻、攻击或逃跑。 游戏事件与状态管理在游戏逻辑中分支节点可用于处理游戏事件和状态的变化。例如根据玩家的当前状态如健康值、能量水平或武器状态来执行不同的游戏逻辑如允许或禁止某些操作或触发特定的事件。 条件性任务执行在任务或剧情流程中分支节点允许开发者根据任务条件如任务状态、玩家行为或环境变量来执行不同的任务步骤或结果。这有助于创建更丰富、更灵活的剧情体验。 网络和多玩家交互在多人在线游戏中分支节点可以用于处理网络状态、玩家状态或其他玩家的行为。根据这些条件游戏可以执行不同的逻辑如同步玩家状态、处理网络延迟或处理玩家间的交互。 动态环境交互在动态环境中分支节点可用于处理与环境的交互。例如根据物体的状态如是否被破坏、是否被拾取等来执行不同的逻辑如改变环境状态、播放音效或触发其他事件。
在这些场景中分支节点的灵活性使得开发者能够根据游戏或应用程序的具体需求来创建复杂的逻辑结构从而实现更加丰富和动态的用户体验。通过组合不同的节点类型和条件判断开发者可以构建出各种复杂的条件分支逻辑。
四、分支节点实现过程
创建输入输出引脚
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 dependencyFEdGraphPinType 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 nodeUEdGraphPin* 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 GetDefaultUEdGraphSchema_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 GetDefaultUGraphEditorSettings()-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 nodes 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);
}