UE 泛型蓝图

文章详细介绍了在UnrealEngine中创建泛型蓝图函数的过程,包括字符串转泛型和泛型类数据获取的实现方法,涉及到的关键函数有FstringToGeneric和ThunkGetData,以及如何处理不同类型的数据转换和内存管理。
摘要由CSDN通过智能技术生成

参考链接

参考链接

参考链接

.h

#pragma region 泛型蓝图函数

	/// <summary>
	/// 字符串转泛型
	/// </summary>
	UFUNCTION(
		BlueprintPure,
		CustomThunk,
		meta = (CompactNodeTitle = "->", CustomStructureParam = "Value"),
		Category = "Vince|Variadic")
		static void FstringToGeneric(const FString stringInfo, int32& Value);

	DECLARE_FUNCTION(execFstringToGeneric)
	{

		//读取叫做DataInfo的Fstring。虚拟机要添加对应类。
		P_GET_STRUCT_REF(FString, stringInfo);
		//告诉虚拟机我们需要读取第一个函数的参数。NULL = 不需要它来分配内存
		Stack.StepCompiledIn<FProperty>(NULL);
		//指向真实的内存地址
		void* SrcPropertyAddr = Stack.MostRecentPropertyAddress;
		//这个值怎么被赋值和导出
		FProperty* SrcProperty = CastFieldChecked<FProperty>(Stack.MostRecentProperty);
		P_FINISH;
		P_NATIVE_BEGIN;
		SrcProperty->ImportText_Direct(*stringInfo, SrcPropertyAddr, 0, 0);
		P_NATIVE_END;

	}

	/// <summary>
	/// 泛型类获取数据
	/// </summary>
	UFUNCTION(BlueprintPure,
		CustomThunk,
		meta = (CoCompactNodeTitle = "Variadic", CustomStructureParam = "Target,Item", BlueprintThreadSafe), Category = "Vince|Variadic")
		static void ThunkGetData(const int32& Target, int32& Item);
	DECLARE_FUNCTION(execThunkGetData)
	{
		Stack.MostRecentProperty = nullptr;
		Stack.StepCompiledIn<FArrayProperty>(NULL);
		void* TargetAddr = Stack.MostRecentPropertyAddress;
		FProperty* TargetProperty = CastField<FProperty>(Stack.MostRecentProperty);
		if (!TargetProperty)
		{
			Stack.bArrayContextFailed = true;
			return;
		}

		const FProperty* InnerProp = TargetProperty;
		const int32 PropertySize = InnerProp->ElementSize * InnerProp->ArrayDim;
		void* StorageSpace = FMemory_Alloca(PropertySize);
		InnerProp->InitializeValue(StorageSpace);

		Stack.MostRecentPropertyAddress = nullptr;
		Stack.MostRecentPropertyContainer = nullptr;
		Stack.StepCompiledIn<FProperty>(StorageSpace);
		const FFieldClass* InnerPropClass = InnerProp->GetClass();
		const FFieldClass* MostRecentPropClass = Stack.MostRecentProperty->GetClass();
		void* ItemPtr;
		// If the destination and the inner type are identical in size and their field classes derive from one another, then permit the writing out of the array element to the destination memory
		if (Stack.MostRecentPropertyAddress != NULL && (PropertySize == Stack.MostRecentProperty->ElementSize * Stack.MostRecentProperty->ArrayDim) &&
			(MostRecentPropClass->IsChildOf(InnerPropClass) || InnerPropClass->IsChildOf(MostRecentPropClass)))
		{
			ItemPtr = Stack.MostRecentPropertyAddress;
		}
		else
		{
			ItemPtr = StorageSpace;
		}

		P_FINISH;
		P_NATIVE_BEGIN;

		Generic_Get(TargetAddr, TargetProperty, ItemPtr);

		P_NATIVE_END;
		InnerProp->DestroyValue(StorageSpace);
	}
	static void Generic_Get(void* TargetArray, const FProperty* Prop, void* Item);
.cpp

void UVariadicBlueprintFunctionLibrary::Generic_Get(void* TargetArray, const FProperty* Prop, void* Item)
{

	if (TargetArray)
	{
		Prop->CopyCompleteValueFromScriptVM(Item, TargetArray);

	}
}
	///Set通配符
	///声明泛型Set参数时, SetParam说明符列表的泛型参数之间用”|”分隔符进行关联
	/// 
	/// 获取泛型Set Variable
	/// Stack.MostRecentProperty = nullptr;
	/// Stack.StepCompiledIn<USetProperty>(NULL);
	/// void* SetAddr = Stack.MostRecentPropertyAddress;
	/// USetProperty* SetProperty = Cast<USetProperty>(Stack.MostRecentProperty);
	/// 

	///TMap
	///
	/// 获取泛型Map Variable
	///  Stack.MostRecentProperty = nullptr;
	///  Stack.StepCompiledIn<UMapProperty>(NULL);
	///  void* SrcMapAddr = Stack.MostRecentPropertyAddress;
	///  UMapProperty* SrcMapProperty = Cast<UMapProperty>(Stack.MostRecentProperty);
	/// 

    ///数组
	//常用const TArray& ArrayName表示一个输入类型的泛型Array参数,TArray& ArrayName表示一个输出 
     类型的泛型Array参数。
	// ArrayParm说明符标识多个泛型参数变量时,变量之间需以英文逗号”,”分隔,不得包含其他字符。
	// ArrayTypeDependentParams说明符标识的多个泛型Array参数的类型相互依赖,在蓝图图表中被调用时 
     只有确定其中之一,余下泛型Array参数随之变化
	///
	/// 获取泛型Array Variable:
	/// Stack.StepCompiledIn<UArrayProperty>(NULL);
	/// void* SrcArrayAddr = Stack.MostRecentPropertyAddress;
	/// UArrayProperty* SrcArrayProperty = Cast<UArrayProperty>(Stack.MostRecentProperty);
	/// 

	/// *** 泛型 https://blog.csdn.net/weixin_56946623/article/details/123982505 ***
		/// 
		/// (1) DECLARE_FUNCTION(execFunctionName) {},FucntionName为函数声明时的函数名称。在花括号{}内部包含的代码:
		/// P_FINISH宏之前为获取函数参数的代码块、P_NATIVE_BEGIN和P_NATIVE_END宏包裹着真正执行该函数功能的被调用函数,若是泛型蓝图节点,
		/// 此处调用该函数的泛型版本(泛型函数)。若函数无返回值,可以直接调用泛型函数;若存在返回值,则应当在"="左侧定义适当的返回值类型。
		/// 如果函数具有返回值的话,用这个 *(Type*)RESULT_PARAM ,引擎版本5.0
		/// 
		/// DECLARE_FUNCTION(execFunctionName)
		//{
		// Get Parameters
		//	P_FINISH;
		//	P_NATIVE_BEGIN;
		//	*(FString*)Result = Generic_FunctionName();   // Call generic function
		//	P_NATIVE_END;
		//	}
	   /// 
	   /// (2) 当在Thunk函数体中获取多个参数时,获取的先后次序应与函数声明时变量在参数列表中出现的次序保持一致,否则在函数被调用时将引发程序崩溃。
	   ///
	  ///  (3) 在Thunk函数体中,泛型蓝图函数的参数列表中确定类型的参数(如bool / uint8 / int32 / float / FName / FString等)和泛型参数(wilcard SingleVariable / TArray / TMap / TSet)获取方式不同
	  /// 
	  ///  (4) 4.25之后UProperty改成了FProperty


	   ///P_FINISH代表参数获取完成,因此前方为获取参数,P_NATIVE_BEGIN为激活函数开始,P_NATIVE_BEGIN为激活函数结束。
	   /// 要自定义一个泛型函数,需要UFUNCTION添加CustomThunk,并声明泛型变量,DECLARE_FUNCTION中获取对应泛型数据,并调用自身真正的函数

	   ///
	   /// 获取泛型参数需要同时获取该变量地址void*和变量属性UProperty*/ UArrayProperty* / UMapProperty* / USetProperty*
	   /// 
	   /// 获取泛型Single Variable
	   /// Stack.StepCompiledIn<UStructProperty>(NULL);
	   /// void* SrcPropertyAddr = Stack.MostRecentPropertyAddress;
	   /// UProperty* SrcProperty = Cast<UProperty>(Stack.MostRecentProperty);
	   /// 
	   /// 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值