UE蓝图 Cast节点和源码

系列文章目录

UE蓝图 Cast节点和源码


文章目录

  • 系列文章目录
  • Cast节点功能
  • 一、Cast节点用法
  • 二、Cast节点使用场景
  • 三、Cast节点实现步骤
  • 四、Cast节点源码


Cast节点功能

在Unreal Engine(UE)中,Cast节点是一种蓝图系统中的节点,用于执行类型转换操作。Cast节点用于检测一个对象是否可以被转换(或“投射”)为另一种类型,并在转换成功时返回转换后的对象。

在这里插入图片描述
具体来说,当你在蓝图中使用Cast节点时,你正在尝试将一个对象转换(或投射)为另一种类型。例如,如果你有一个“玩家角色”对象,并且你想检查它是否是一个特定的“MyCharacter”类型的实例,你可以使用“Get Player Character”节点来获取玩家角色,然后使用“Cast To MyCharacter”节点来尝试将其转换为“MyCharacter”类型。如果转换成功,你就可以访问该对象的特定变量、函数和事件。
上图对应的代码如下:

 bpfv__CallFunc_GetParentActor_ReturnValue__pf = AActor::GetParentActor();bpfv__K2Node_DynamicCast_As____pf = Cast<ACharacter>(bpfv__CallFunc_GetParentActor_ReturnValue__pf);bpfv__K2Node_DynamicCast_bSuccess__pf = (bpfv__K2Node_DynamicCast_As____pf != nullptr);;if (!bpfv__K2Node_DynamicCast_bSuccess__pf){__CurrentState = -1;break;}

一、Cast节点用法

当然可以。UE Cast节点在Unreal Engine的蓝图系统中的具体用法主要涉及以下步骤:

  1. 获取对象引用:首先,你需要有一个对象引用,这通常是通过其他蓝图节点获取的。例如,你可能有一个指向某个游戏对象(如玩家角色、敌人等)的引用。

  2. 添加Cast节点:在蓝图中,你需要添加一个Cast节点。这个节点通常位于“类型转换”类别下。添加后,你将看到两个主要的输出端:一个是转换后的对象引用,另一个是表示转换是否成功的布尔值(bool)。

  3. 配置Cast节点:在Cast节点的属性窗口中,你需要指定目标类型,即你希望将对象转换成的类型。这通常是一个类名,比如MyCharacterMyComponent

  4. 连接对象引用:将你想要转换的对象引用连接到Cast节点的输入端。这通常是通过从获取对象引用的节点拖一条线到Cast节点的输入端来完成的。

  5. 使用转换后的对象:Cast节点有两个输出端。第一个输出端输出转换后的对象引用。如果转换成功,这个输出端将是非空的(即有效的)。你可以将这个输出端连接到需要该类型对象的任何节点上。

  6. 检查转换是否成功:Cast节点的第二个输出端是一个布尔值,表示转换是否成功。你可以将这个输出端连接到条件逻辑节点(如Branch节点)上,以便在转换成功时执行一段逻辑,在转换失败时执行另一段逻辑。

  7. 处理转换失败的情况:如果转换失败(即对象不能被转换为目标类型),你可能需要执行一些备选逻辑。这可以通过使用Cast节点的第二个输出端(布尔值)来实现,将其连接到一个条件节点,以便在转换失败时执行特定的操作。

二、Cast节点使用场景

UE Cast节点在蓝图系统中有多种应用场景,这些场景主要涉及到需要动态类型转换或检查的地方。以下是一些常见的UE Cast节点应用场景:

  1. 继承与多态处理:在面向对象编程中,Cast节点常用于处理继承关系。例如,当你有一个基类指针或引用,并且你想调用仅在派生类中定义的函数时,你需要先使用Cast节点将其转换为派生类类型。

  2. 接口实现检查:如果一个对象实现了某个接口,你可以使用Cast节点来检查这个对象是否确实实现了该接口,并据此执行相应的操作。

  3. 组件查询与访问:在UE中,组件通常附加到实体(如Actor)上。你可以使用Cast节点来尝试将实体转换为特定的组件类型,以便直接访问该组件的属性和方法。

  4. 动态类型识别:在某些情况下,你可能不知道对象的确切类型,但需要根据其类型执行不同的逻辑。通过使用Cast节点,你可以尝试将对象转换为多种可能的类型,并根据转换是否成功来决定执行哪段逻辑。

  5. 事件处理:在处理事件或委托时,你可能会接收到一个通用类型的参数。使用Cast节点,你可以将这个通用参数转换为更具体的类型,以便在事件处理逻辑中使用。

  6. 资源加载与转换:在加载资源时,资源可能以通用或基类形式被加载。在使用资源之前,你可能需要将其转换为正确的派生类型。

  7. 错误处理与调试:在开发过程中,Cast节点可以帮助你验证对象是否如你所期望的那样被正确创建和管理。如果Cast失败,这可能表明存在编程错误或资源管理问题。

三、Cast节点实现步骤

  • 创建输入输出引脚
		// Input - Execution PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Output - Execution PinsCreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastSucceeded);CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastFailed);// Input - Source type PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, UObject::StaticClass(), UEdGraphSchema_K2::PN_ObjectToCast);CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, *TargetType, *CastResultPinName);UEdGraphPin* BoolSuccessPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Boolean, UK2Node_DynamicCastImpl::CastSuccessPinName);
  • 注册Net
	FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));Context.NetMap.Add(Net, Term);
  • 编译
    创建转换Statement
	// Cast StatementFBlueprintCompiledStatement& CastStatement = Context.AppendStatementForNode(Node);CastStatement.Type = CastOpType;CastStatement.LHS = *CastResultTerm;CastStatement.RHS.Add(ClassTerm);CastStatement.RHS.Add(*ObjectToCast);

四、Cast节点源码


void UK2Node_DynamicCast::AllocateDefaultPins()
{const bool bReferenceObsoleteClass = TargetType && TargetType->HasAnyClassFlags(CLASS_NewerVersionExists);if (bReferenceObsoleteClass){Message_Error(FString::Printf(TEXT("Node '%s' references obsolete class '%s'"), *GetPathName(), *TargetType->GetPathName()));}ensure(!bReferenceObsoleteClass);const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());check(K2Schema != nullptr);if (!K2Schema->DoesGraphSupportImpureFunctions(GetGraph())){bIsPureCast = true;}if (!bIsPureCast){// Input - Execution PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Output - Execution PinsCreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastSucceeded);CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastFailed);}// Input - Source type PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, UObject::StaticClass(), UEdGraphSchema_K2::PN_ObjectToCast);// Output - Data Pinif (TargetType){const FString CastResultPinName = UEdGraphSchema_K2::PN_CastedValuePrefix + TargetType->GetDisplayNameText().ToString();if (TargetType->IsChildOf(UInterface::StaticClass())){CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Interface, *TargetType, *CastResultPinName);}else {CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, *TargetType, *CastResultPinName);}}UEdGraphPin* BoolSuccessPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Boolean, UK2Node_DynamicCastImpl::CastSuccessPinName);BoolSuccessPin->bHidden = !bIsPureCast;Super::AllocateDefaultPins();
}

void FKCHandler_DynamicCast::RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node)
{FNodeHandlingFunctor::RegisterNets(Context, Node);if (const UK2Node_DynamicCast* DynamicCastNode = Cast<UK2Node_DynamicCast>(Node)){UEdGraphPin* BoolSuccessPin = DynamicCastNode->GetBoolSuccessPin();// this is to support backwards compatibility (when a cast node is generating code, but has yet to be reconstructed)// @TODO: remove this at some point, when backwards compatibility isn't a concernif (BoolSuccessPin == nullptr){// Create a term to determine if the cast was successful or notFBPTerminal* BoolTerm = Context.CreateLocalTerminal();BoolTerm->Type.PinCategory = UEdGraphSchema_K2::PC_Boolean;BoolTerm->Source = Node;BoolTerm->Name = Context.NetNameMap->MakeValidName(Node, TEXT("CastSuccess"));BoolTermMap.Add(Node, BoolTerm);}}}void FKCHandler_DynamicCast::RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net)
{FBPTerminal* Term = Context.CreateLocalTerminalFromPinAutoChooseScope(Net, Context.NetNameMap->MakeValidName(Net));Context.NetMap.Add(Net, Term);
}void FKCHandler_DynamicCast::Compile(FKismetFunctionContext& Context, UEdGraphNode* Node)
{const UK2Node_DynamicCast* DynamicCastNode = CastChecked<UK2Node_DynamicCast>(Node);if (DynamicCastNode->TargetType == NULL){CompilerContext.MessageLog.Error(*LOCTEXT("BadCastNoTargetType_Error", "Node @@ has an invalid target type, please delete and recreate it").ToString(), Node);}// Self PinUEdGraphPin* SourceObjectPin = DynamicCastNode->GetCastSourcePin();UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(SourceObjectPin);FBPTerminal** ObjectToCast = Context.NetMap.Find(PinToTry);if (!ObjectToCast){ObjectToCast = Context.LiteralHackMap.Find(PinToTry);if (!ObjectToCast || !(*ObjectToCast)){CompilerContext.MessageLog.Error(*LOCTEXT("InvalidConnectionOnNode_Error", "Node @@ has an invalid connection on @@").ToString(), Node, SourceObjectPin);return;}}// Output pinconst UEdGraphPin* CastOutputPin = DynamicCastNode->GetCastResultPin();if( !CastOutputPin ){CompilerContext.MessageLog.Error(*LOCTEXT("InvalidDynamicCastClass_Error", "Node @@ has an invalid target class").ToString(), Node);return;}FBPTerminal** CastResultTerm = Context.NetMap.Find(CastOutputPin);if (!CastResultTerm || !(*CastResultTerm)){CompilerContext.MessageLog.Error(*LOCTEXT("InvalidDynamicCastClass_CompilerError", "Node @@ has an invalid target class. (Inner compiler error?)").ToString(), Node);return;}// Create a literal term from the class specified in the nodeFBPTerminal* ClassTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal);ClassTerm->Name = DynamicCastNode->TargetType->GetName();ClassTerm->bIsLiteral = true;ClassTerm->Source = Node;ClassTerm->ObjectLiteral = DynamicCastNode->TargetType;ClassTerm->Type.PinCategory = UEdGraphSchema_K2::PC_Class;UClass const* const InputObjClass  = Cast<UClass>((*ObjectToCast)->Type.PinSubCategoryObject.Get());UClass const* const OutputObjClass = Cast<UClass>((*CastResultTerm)->Type.PinSubCategoryObject.Get());const bool bIsOutputInterface = ((OutputObjClass != NULL) && OutputObjClass->HasAnyClassFlags(CLASS_Interface));const bool bIsInputInterface  = ((InputObjClass != NULL) && InputObjClass->HasAnyClassFlags(CLASS_Interface));EKismetCompiledStatementType CastOpType = KCST_DynamicCast;if (bIsInputInterface){if (bIsOutputInterface){CastOpType = KCST_CrossInterfaceCast;}else{CastOpType = KCST_CastInterfaceToObj;}}else if (bIsOutputInterface){CastOpType = KCST_CastObjToInterface;}if (KCST_MetaCast == CastType){if (bIsInputInterface || bIsOutputInterface){CompilerContext.MessageLog.Error(*LOCTEXT("InvalidClassDynamicCastClass_Error", "Node @@ has an invalid target class. Interfaces are not supported.").ToString(), Node);return;}CastOpType = KCST_MetaCast;}// Cast StatementFBlueprintCompiledStatement& CastStatement = Context.AppendStatementForNode(Node);CastStatement.Type = CastOpType;CastStatement.LHS = *CastResultTerm;CastStatement.RHS.Add(ClassTerm);CastStatement.RHS.Add(*ObjectToCast);FBPTerminal** BoolSuccessTerm = nullptr;if (UEdGraphPin* BoolSuccessPin = DynamicCastNode->GetBoolSuccessPin()){BoolSuccessTerm = Context.NetMap.Find(BoolSuccessPin);}else{BoolSuccessTerm = BoolTermMap.Find(DynamicCastNode);}	check(BoolSuccessTerm != nullptr);// Check result of cast statementFBlueprintCompiledStatement& CheckResultStatement = Context.AppendStatementForNode(Node);CheckResultStatement.Type = KCST_ObjectToBool;CheckResultStatement.LHS  = *BoolSuccessTerm;CheckResultStatement.RHS.Add(*CastResultTerm);UEdGraphPin* SuccessExecPin = DynamicCastNode->GetValidCastPin();bool const bIsPureCast = (SuccessExecPin == nullptr);if (!bIsPureCast){UEdGraphPin* FailurePin = DynamicCastNode->GetInvalidCastPin();check(FailurePin != nullptr);// Failure condition...skip to the failed outputFBlueprintCompiledStatement& FailCastGoto = Context.AppendStatementForNode(Node);FailCastGoto.Type = KCST_GotoIfNot;FailCastGoto.LHS  = *BoolSuccessTerm;Context.GotoFixupRequestMap.Add(&FailCastGoto, FailurePin);// Successful cast...hit the success output nodeFBlueprintCompiledStatement& SuccessCastGoto = Context.AppendStatementForNode(Node);SuccessCastGoto.Type = KCST_UnconditionalGoto;SuccessCastGoto.LHS  = *BoolSuccessTerm;Context.GotoFixupRequestMap.Add(&SuccessCastGoto, SuccessExecPin);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【性能测试入门必看】性能测试理论知识

一、性能测试理论知识 1、常用的七种性能测试方法 (1) 后端性能测试&#xff1a;其实&#xff0c;你平时听到的性能测试&#xff0c;大多数情况下指的是后端性能测试&#xff0c;也就是服务器端性能测试。后端性能测试&#xff0c;是通过性能测试工具模拟大量的并发用户请求&…

linux系统Grafana关联zabbix显示

Grafana关联zabbix 服务器下载浏览器配置开启zabbix插件配置zabbix数据源可视化Zabbix数据 服务器下载 grafana-cli plugins list-remote grafana-cli plugins list-remote|grep -i zabbix grafana-cli plugins install alexanderzobnin-zabbix-appsystemctl restart grafana-…

HBase 进阶

参考来源: B站尚硅谷HBase2.x 目录 Master 架构RegionServer 架构写流程MemStore Flush读流程HFile 结构读流程合并读取数据优化 StoreFile CompactionRegion Split预分区&#xff08;自定义分区&#xff09;系统拆分 Master 架构 Master详细架构 1&#xff09;Meta 表格介…

Vue | (一)Vue核心(上) | 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;Vue简介&#x1f4da;初识Vue&#x1f4da;模板语法&#x1f4da;数据绑定&#x1f4da;MVVM模型&#x1f4da;数据代理&#x1f407;回顾Object.defineproperty方法&#x1f407;何为数据代理&#x1f407;Vue中的数据代理 &#x1f4da;事件处理&#…

基于java的眼镜店仓库管理系统

源码获取&#xff0c;加V&#xff1a;qq2056908377 摘要&#xff1a; 随着电子商务的兴起&#xff0c;越来越多的商家选择在线销售他们的产品。眼镜店作为零售业的一种&#xff0c;也不例外。随着市场需求的不断增加&#xff0c;眼镜店需要更加高效的管理他们的仓库和库存&…

Mysql 权限与安全管理

0 引言 MySQL是一个多用户数据库&#xff0c;具有功能强大的访问控制系统&#xff0c;可以为不同用户指定允许的权限。MySQL用户可以分为普通用户和root用户。root用户是超级管理员&#xff0c;拥有所有权限&#xff0c;包括创建用户、删除用户和修改用户的密码等管理权限&…

LeetCode21.合并两个有序链表

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 &#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 思路 创建一个新的链表头节点&#xff08;dummyNode&#xff09;和一个…

RegExp正则表达式左限定右限定左右限定,预查询,预查寻,断言 : (?<= , (?= , (?<! , (?!

RegExp正则表达式左限定右限定左右限定,预查询,预查寻,断言 : (?< , (? , (?<! , (?! 有好多种称呼 (?< , (? , (?<! , (?! 有好多种称呼 , 我称为: 左限定, 右限定, 左否定, 右否定 (?<左限定)    (?右限定)(?<!左否定)    (?!右限定) 再…

阿里云个人建站笔记

导航 一、购买ECS服务器二、配置mysql&#xff08;一&#xff09;安装Mysql步骤一&#xff1a;安装mysql步骤二&#xff1a;配置MySQL步骤三&#xff1a;远程访问MySQL数据库 &#xff08;二&#xff09;给实例配置安全组策略&#xff08;三&#xff09;设置防火墙 一、购买ECS…

.ma1x0勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

尊敬的读者&#xff1a; 数据安全问题备受关注。而勒索病毒是其中一种最为恶劣的威胁之一。其中&#xff0c;.ma1x0勒索病毒备受人们担忧&#xff0c;因其可将用户的数据文件加密&#xff0c;并要求支付赎金以解密文件。本文将介绍.ma1x0勒索病毒的特征、预防方法以及如何恢复…

transformer-Attention is All You Need(二)

transformer中的解码器 解码器层 每个解码器层根据给定的输入向目标方向进行特征提取&#xff0c;即完成解码过程 transformer的解码器也是一个自回归模型&#xff0c;根据编码器的结果以及上一次预测的结果&#xff0c;对下一次可能出现的值进行特征表示。它也是由N层完全相同…

循环队列|超详细|数据结构学习讲解与笔记

队列元素先进先出队列只允许在线性表的一端进行操作&#xff0c;是一种操作受限的线性表 队列的基本操作 InItQueue(&Q)初始化队列&#xff0c;构造一个空队列 QEmptyQueue(Q)队列判空FullQueue(Q)队列判满EnQueue(&Q , x)入队操作DeQueue(&Q , &x)出队操作G…

OpenAI新爆款Sora,大佬们怎么看?

OpenAI新爆款Sora的热度持续发酵&#xff0c;在科技圈的刷屏阵仗都快赶上正月初五迎财神了。 智东西2月17日报道&#xff0c;这两天&#xff0c;OpenAI首款文生视频大模型Sora以黑马之姿占据AI领域话题中心&#xff0c;马斯克、杨立昆、贾扬清、Jim Fan、谢赛宁、周鸿祎、李志…

【动态规划专栏】专题一:斐波那契数列模型--------2.三步问题

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

数据结构-最短路径(Dijkstra算法与Floyd算法)

介绍 对于网图来说&#xff0c;最短路径是指两顶点之间经过的边上权值之和最少的路径&#xff0c;其路径上第一个点记为源点&#xff0c;最后一个为终点。 计算最短路径有两个经典算法&#xff0c;即迪杰斯特拉&#xff08;Dijkstra&#xff09;算法与弗洛伊德&#xff08;Fl…

unity学习(20)——客户端与服务器合力完成注册功能(2)调试注册逻辑

接着上一节的问题&#xff0c;想办法升级成具备数据库功能的服务器&#xff0c;这个是必须的。 至少在初始化要学会把文件转换为session&#xff0c;新知识&#xff0c;有挑战的。 现在是从LoginHandler.cs跳到了AccountBiz.cs的create&#xff0c;跳度还是很大的。 create函…

oauthlib,一个强大的 Python 身份校验库!

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站零基础入门的AI学习网站~。 目录 ​编辑 前言 什么是 OAuthLib&#xff1f; 安装 OAuthLib OAuthLib 的主要功能 OAuthLib 的用法 实现…

文案馆头像壁纸微信小程序源码【支持流量主】

文案馆头像壁纸微信小程序源码【支持流量主】 源码介绍&#xff1a;文案馆头像壁纸微信小程序源码是一款可以获取套图、头像、壁纸的小程序。小程序源码内置流量主功能 需求环境&#xff1a;微信小程序phpmysql 下载地址&#xff1a; https://www.changyouzuhao.cn/13453.ht…

【C语言】长篇详解,字符系列篇2-----受长度限制的字符串函数,字符串函数的使用和模拟实现【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本期系列为【【C语言】长篇详解&#xff0c;字符系列篇2-----“混杂”的字符串函数&#xff0c;字符串函数的使用和模拟实现【图文详解】&#xff0c;图文讲解各种字符串函数&#xff0c;带大家更深刻理解C语言中各种字符串函数的应用&#x…

即时设计是什么?

在过去的两年里&#xff0c;由于疫情的推动以及科学技术的不断进步&#xff0c;国内外协同办公室发展迅速。在市场的推动下&#xff0c;市场上出现了越来越多的协同办公软件&#xff0c;使工作场所的工作更加高效。 在设计领域&#xff0c;具有协同功能的软件市场似乎仍处于空…