UE蓝图 Cast节点和源码

news2024/11/27 8:45:09

系列文章目录

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 Pin
		CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
		// Output - Execution Pins
		CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastSucceeded);
		CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastFailed);
		// Input - Source type Pin
	CreatePin(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 Statement
	FBlueprintCompiledStatement& 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 Pin
		CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);

		// Output - Execution Pins
		CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastSucceeded);
		CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_CastFailed);
	}

	// Input - Source type Pin
	CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, UObject::StaticClass(), UEdGraphSchema_K2::PN_ObjectToCast);

	// Output - Data Pin
	if (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 concern
		if (BoolSuccessPin == nullptr)
		{
			// Create a term to determine if the cast was successful or not
			FBPTerminal* 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 Pin
	UEdGraphPin* 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 pin
	const 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 node
	FBPTerminal* 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 Statement
	FBlueprintCompiledStatement& 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 statement
	FBlueprintCompiledStatement& 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 output
		FBlueprintCompiledStatement& FailCastGoto = Context.AppendStatementForNode(Node);
		FailCastGoto.Type = KCST_GotoIfNot;
		FailCastGoto.LHS  = *BoolSuccessTerm;
		Context.GotoFixupRequestMap.Add(&FailCastGoto, FailurePin);

		// Successful cast...hit the success output node
		FBlueprintCompiledStatement& SuccessCastGoto = Context.AppendStatementForNode(Node);
		SuccessCastGoto.Type = KCST_UnconditionalGoto;
		SuccessCastGoto.LHS  = *BoolSuccessTerm;
		Context.GotoFixupRequestMap.Add(&SuccessCastGoto, SuccessExecPin);
	}
}

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

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

相关文章

重磅!2024年中科院预警期刊名单发布,24本上榜!预警原因公开

2024年中科院预警期刊名单 2月19日&#xff0c;2024年中科院预警期刊名单正式发布&#xff01; 名单分析&#xff1a; 2024年版本的《国际期刊预警名单&#xff08;试行&#xff09;》共24本期刊&#xff0c;较2023年版本的28本减少了4本&#xff0c;今年的24本期刊中&#…

AI专题:AI浪潮,海外日新月异,国内奋力追赶

今天分享的是AI系列深度研究报告&#xff1a;《AI专题&#xff1a;AI浪潮&#xff0c;海外日新月异&#xff0c;国内奋力追赶》。 &#xff08;报告出品方&#xff1a;方正证券&#xff09; 报告共计&#xff1a;24页 来源&#xff1a;人工智能学派 智算三方面奠基生产力革…

推荐12个超级哇塞的工具

今天分享 12 个完全免费的软件工具&#xff0c;包括 5 个电脑软件和 7 个在线工具&#xff0c;每一个都是自己用心挑选&#xff0c;每一个都是良心免费&#xff0c;让你惊艳。 1 WinFR界面版 WinFR界面版是一款基于微软官方命令行工具 Windows File Recovery 的图形界面工具…

网络原理 - HTTP/HTTPS(2)

HTTP请求 认识URL URL基本格式 平时我们俗称的"网址"其实就是说的URL(Uniform Resource Locator统一资源定位符). (还有一个唯一资源标识符,称为uri,严格来说,uri范围比url广). 互联网上的每一个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该…

【Java】文件类 和 I/O流详解

文章目录 一. 文件概述二. 文件类File1. 构造方法和常用普通方法2. 4种获取路径方法的比较 三. I/O流1. 流的概念2. FileReader和FileWriter3. FileInputStream和FileOutputStream4. 带有缓冲功能的I/O流&#xff08;处理流&#xff09;关闭流资源的另一种方法&#xff08;推荐…

three.js 3D可视化地图

threejs地图 可视化地图——three.js实现 this.provinceInfo document.getElementById(provinceInfo); // 渲染器 this.renderer new THREE.WebGLRenderer({antialias: true }); this.renderer.setSize(window.innerWidth, window.innerHeight); this.container.appendChild…

应如何看待用AI写论文一事? AI写论文有助科研还是助长作弊?

自大语言模型问世后&#xff0c;许多高校学生都在悄悄利用ChatGPT等AI&#xff08;人工智能&#xff09;写作软件代写论文&#xff0c;或者用AI辅助论文写作&#xff0c;如罗列提纲、润色语言、降低重复率等。 国内类似ChatGPT的AI写作软件并不少见。在各大等网站上&#xff0…

如何构建企业专属GPT

大语言模型&#xff08;LLM&#xff09;具有令人印象深刻的自然语言理解和生成能力&#xff0c; 2022年11月底OpenAI发布了ChatGPT&#xff0c;一跃成为人工智能AI领域的现象级应用。但由于LLM的训练数据集主要来源于互联网数据&#xff0c;企业私域信息并未被LLM所训练&#x…

品牌如何写出与用户同频的文案?媒介盒子告诉你

文案作为直面消费者的第一前线&#xff0c;承担了品牌与受众的沟通角色。文案运用同频去讲故事&#xff0c;能够更好地与用户产生共鸣。讲好品牌故事能提高用户对品牌的忠诚度&#xff1b;讲好用户故事能够增强用户的信赖感&#xff0c;那么如何写出同频文案呢&#xff1f;接下…

新零售模式太好用了!怎么做的?教你现学现用

随着科技的不断发展&#xff0c;零售行业也在经历着翻天覆地的变革。新零售模式的兴起为传统零售带来了全新的机遇与挑战。 在这个数字化时代&#xff0c;自动售货机作为新零售的一种创新形式&#xff0c;正逐渐改变着消费者购物的方式。 客户案例 智能零售超市 在城市繁华的…

七部门重磅发文!未来产业创新该如何发展?

1 月 29 日&#xff0c;工业和信息化部、教育部、科学技术部、交通运输部、文化和旅游部、国务院国有资产监督管理委员会、中国科学院等七部门联合发布《关于推动未来产业创新发展的实施意见》&#xff08;以下简称《实施意见》&#xff09;&#xff0c;前瞻布局未来产业。未来…

安防监控平台EasyCVR升级之后添加通道进行播放,提示“请确认播放协议配置选项”是什么原因?

智慧安防平台EasyCVR能在复杂的网络环境中&#xff08;专网、局域网、广域网、VPN、公网等&#xff09;将前端海量的设备进行统一集中接入与视频汇聚管理&#xff0c;平台可支持的接入协议包括&#xff1a;国标GB28181、RTSP/Onvif、RTMP&#xff0c;以及厂家的私有协议与SDK&a…

TCP流量控制+拥塞控制

流量控制&#xff1a; 目标&#xff1a;流量控制主要解决的是发送方和接收方之间处理能力的不匹配问题。它的目的是确保发送方不会发送数据过快&#xff0c;以至于接收方无法及时接收并处理这些数据&#xff0c;从而避免数据包在网络中堆积和丢失。实现方式&#xff1a;在TCP协…

CSS杂记

1 在需要文本过长&#xff0c;需要该文本自动换行时 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><div style"width:400px;background-color: #dcdcdc;height: auto…

完整的 vue-router 导航解析流程

在Vue.js中&#xff0c;vue-router是一个官方提供的路由管理器&#xff0c;它能够帮助我们实现页面之间的无缝切换和导航。 本文将深入探讨vue-router的导航解析流程&#xff0c;并通过示例代码演示如何使用vue-router实现完整的导航过程。 首先&#xff0c;让我们来了解一下…

【ARMv8M Cortex-M33 系列 8 -- RT-Thread 移植 posix pthread】

文章目录 RT-Thread POSIX PthreadRT-Thread Pthread 相关宏定义RT-Thread libc 初始化RT-Thread Pthread 测试 RT-Thread POSIX Pthread pthread是POSIX&#xff08;Portable Operating System Interface&#xff09;标准定义的一套线程相关的API&#xff0c;全称为POSIX Thr…

TSINGSEE智能分析网关V4的AI算法在消防场景中有哪些应用?

随着科技的不断创新和发展&#xff0c;人工智能已经成为现代社会的重要组成部分。除了在交通、医疗、电力等领域得到了广泛应用外&#xff0c;人工智能在消防领域也有着广泛的应用。AI烟火识别算法作为TSINGSEE青犀视频AI智能分析网关V4的重要组成部分&#xff0c;在城市消防领…

2024年关于电池的欧盟新要求CE 标志并有欧盟负责人

2024年关于电池的欧盟新要求如下&#xff1a; 关于电池的欧盟新要求 2024年&#xff0c;欧盟计划针对在欧盟和北爱尔兰销售的所有独立电池和商品内含电池推出欧盟电池法规。此法规要求所 有符合条件的电池都必须带有CE 标志并有欧盟负责人。 如果您使用亚马逊物流(FBA)且位于欧…

Linux-ls命令

目录 ls&#xff1a;查看目录下文件/文件夹 ls -l&#xff1a;列表显示文件 ls -a&#xff1a;显示所有文件正常情况下‘ . ’开头的文件是隐藏的 ls -la&#xff1a;以列表形式显示所有文件包括隐藏文件 ls -lt&#xff1a;按时间倒序查看文件 ls -R&#xff1a;递归方式…

Rocky Linux 下载安装

一、VMware Workstation下载安装 1、安装教程 VMware Workstation下载安装&#xff08;含密钥&#xff09; 二、VMware Workstation 创建虚拟机 1、创建教程 VMware Workstation 创建虚拟机 三、Rocky Linux 下载 1、下载官网 RockyLinux.org 2、选择X86架构_64位系统_DVD镜…