首发于 UE5
UE5/UE4通过函数名调用带参函数

UE5/UE4通过函数名调用带参函数

目标:

1. 通过函数名称,直接调用没有入参的函数;
2. 通过函数名和json字符串,直接调用带参函数;
*tips:后面会增加包含返回值的调用案例*

目标一:直接调用没有入参的函数

void CallFunctionByNameNoParam(UObject* inObj, const FString inName) {
	UClass* TempClass = inObj->GetClass();
	UFunction* TempFunc = TempClass->FindFunctionByName(*inName);
	inObj->ProcessEvent(TempFunc,NULL);

目标二:通过函数名+Json字符串,调用带参函数

思路:

1. 通过函数指针获取到参数队列,然后构造一个结构体
2. 结构体转成Json对象,通过读取和设置Json对象的方式,设置参数数值
3. 将参数结构序列化,再反序列化存储之后,作为参数传入到上面执行函数即可

问题:

1. 获取函数参数数量和名称
2. 获取函数参数属性:入参,出参,等
3. 怎么构造函数参数结构
4. 构造参数结构之后,怎么给参数结构设置我们输入的参数值
5. 函数参数数据类型:string,int,color,vector,等

原理:UE5的反射系统函数和参数的关系

//方法原型
int32 UMyClass::Func(float param1); 
UFUNCTION(BlueprintCallable)
int32 InvokeFunction(UObject* obj, FName functionName,float param1)
    struct MyClass_Func_Parms   //定义一个结构用来包装参数和返回值,就像在gen.cpp里那样
        float param1;
        int32 ReturnValue;
    UFunction* func = obj->FindFunctionChecked(functionName);
    MyClass_Func_Parms params;
    params.param1=param1;
    obj->ProcessEvent(func, &params);
    return params.ReturnValue;
int r=InvokeFunction(obj,"Func",123.f);

问题解决:

  1. 获取参数数量和参数结构尺寸
void CallFunctionByNameWithParam(UObject* inObj, const FString inName, const FString inJsonStr)
        UClass* TempClass = inObj->GetClass();
	UFunction* TempFunc=TempClass->FindFunctionByName(*inName);
	if (!TempFunc) check(false);
	uint16 TempParamsSize = TempFunc->ParmsSize;
	uint8 TempParamsNum = TempFunc->NumParms;
}

2. 把参数容器反序列化为Json对象

void CallFunctionByNameWithParam(UObject* inObj, const FString inName, const FString inJsonStr)
        UClass* TempClass = inObj->GetClass();
	UFunction* TempFunc=TempClass->FindFunctionByName(*inName);
	if (!TempFunc) check(false);
	uint16 TempParamsSize = TempFunc->ParmsSize;
	uint8 TempParamsNum = TempFunc->NumParms;
        TArray<uint8> Params;
	Params.AddUninitialized(TempParamsSize);
	TempFunc->InitializeStruct(Params.GetData());
	SharedPtr<FJsonObject> TempJsonObject = MakeShared<FJsonObject>();
	bool Ret = FJsonObjectConverter::UStructToJsonObject(TempFunc, TempFunc, TempJsonObject.ToSharedRef());
}

3. 把传入的Json字符串反序列化为Json对象

TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(inJsonStr);
TSharedPtr<FJsonObject> inJsonObject;
bool bIsOk = FJsonSerializer::Deserialize(JsonReader, inJsonObject);

4. 读取入参Json字符串构造的Json对象值给到结构反序列化的对象

//已经测试过的入参数据类型

FString
FRotator
bool
uint8
int64
double
FName
int32
FVector
FTransform
FColor
FLinearColor

//所有参数区分

/** All parameter flags */
#define CPF_ParmFlags	(CPF_Parm | CPF_OutParm | CPF_ReturnParm | CPF_ReferenceParm | CPF_ConstParm)


//UProperty属性区分:EPropertyFlags

enum EPropertyFlags : uint64
	CPF_None = 0,
	CPF_Edit					= 0x0000000000000001,	///< Property is user-settable in the editor.
	CPF_ConstParm					= 0x0000000000000002,	///< This is a constant function parameter
	CPF_BlueprintVisible				= 0x0000000000000004,	///< This property can be read by blueprint code
	CPF_ExportObject				= 0x0000000000000008,	///< Object can be exported with actor.
	CPF_BlueprintReadOnly				= 0x0000000000000010,	///< This property cannot be modified by blueprint code
	CPF_Net						= 0x0000000000000020,	///< Property is relevant to network replication.
	CPF_EditFixedSize				= 0x0000000000000040,	///< Indicates that elements of an array can be modified, but its size cannot be changed.
	CPF_Parm					= 0x0000000000000080,	///< Function/When call parameter.
	CPF_OutParm					= 0x0000000000000100,	///< Value is copied out after function call.
	CPF_ZeroConstructor				= 0x0000000000000200,	///< memset is fine for construction
	CPF_ReturnParm					= 0x0000000000000400,	///< Return value.
	CPF_DisableEditOnTemplate			= 0x0000000000000800,	///< Disable editing of this property on an archetype/sub-blueprint
	//CPF_      					= 0x0000000000001000,	///< 
	CPF_Transient   				= 0x0000000000002000,	///< Property is transient: shouldn't be saved or loaded, except for Blueprint CDOs.
	CPF_Config      				= 0x0000000000004000,	///< Property should be loaded/saved as permanent profile.
	//CPF_						= 0x0000000000008000,	///< 
	CPF_DisableEditOnInstance			= 0x0000000000010000,	///< Disable editing on an instance of this class
	CPF_EditConst   				= 0x0000000000020000,	///< Property is uneditable in the editor.
	CPF_GlobalConfig				= 0x0000000000040000,	///< Load config from base class, not subclass.
	CPF_InstancedReference				= 0x0000000000080000,	///< Property is a component references.
	//CPF_						= 0x0000000000100000,	///<
	CPF_DuplicateTransient				= 0x0000000000200000,	///< Property should always be reset to the default value during any type of duplication (copy/paste, binary duplication, etc.)
	//CPF_						= 0x0000000000400000,	///< 
	//CPF_    					= 0x0000000000800000,	///< 
	CPF_SaveGame					= 0x0000000001000000,	///< Property should be serialized for save games, this is only checked for game-specific archives with ArIsSaveGame
	CPF_NoClear					= 0x0000000002000000,	///< Hide clear (and browse) button.
	//CPF_  					= 0x0000000004000000,	///<
	CPF_ReferenceParm				= 0x0000000008000000,	///< Value is passed by reference; CPF_OutParam and CPF_Param should also be set.
	CPF_BlueprintAssignable				= 0x0000000010000000,	///< MC Delegates only.  Property should be exposed for assigning in blueprint code
	CPF_Deprecated  				= 0x0000000020000000,	///< Property is deprecated.  Read it from an archive, but don't save it.
	CPF_IsPlainOldData				= 0x0000000040000000,	///< If this is set, then the property can be memcopied instead of CopyCompleteValue / CopySingleValue
	CPF_RepSkip					= 0x0000000080000000,	///< Not replicated. For non replicated properties in replicated structs 
	CPF_RepNotify					= 0x0000000100000000,	///< Notify actors when a property is replicated
	CPF_Interp					= 0x0000000200000000,	///< interpolatable property for use with cinematics
	CPF_NonTransactional				= 0x0000000400000000,	///< Property isn't transacted
	CPF_EditorOnly					= 0x0000000800000000,	///< Property should only be loaded in the editor
	CPF_NoDestructor				= 0x0000001000000000,	///< No destructor
	//CPF_						= 0x0000002000000000,	///<
	CPF_AutoWeak					= 0x0000004000000000,	///< Only used for weak pointers, means the export type is autoweak
	CPF_ContainsInstancedReference		        = 0x0000008000000000,	///< Property contains component references.
	CPF_AssetRegistrySearchable			= 0x0000010000000000,	///< asset instances will add properties with this flag to the asset registry automatically
	CPF_SimpleDisplay				= 0x0000020000000000,	///< The property is visible by default in the editor details view
	CPF_AdvancedDisplay				= 0x0000040000000000,	///< The property is advanced and not visible by default in the editor details view
	CPF_Protected					= 0x0000080000000000,	///< property is protected from the perspective of script
	CPF_BlueprintCallable				= 0x0000100000000000,	///< MC Delegates only.  Property should be exposed for calling in blueprint code
	CPF_BlueprintAuthorityOnly			= 0x0000200000000000,	///< MC Delegates only.  This delegate accepts (only in blueprint) only events with BlueprintAuthorityOnly.
	CPF_TextExportTransient				= 0x0000400000000000,	///< Property shouldn't be exported to text format (e.g. copy/paste)
	CPF_NonPIEDuplicateTransient		        = 0x0000800000000000,	///< Property should only be copied in PIE
	CPF_ExposeOnSpawn				= 0x0001000000000000,	///< Property is exposed on spawn
	CPF_PersistentInstance				= 0x0002000000000000,	///< A object referenced by the property is duplicated like a component. (Each actor should have an own instance.)
	CPF_UObjectWrapper				= 0x0004000000000000,	///< Property was parsed as a wrapper class like TSubclassOf<T>, FScriptInterface etc., rather than a USomething*
	CPF_HasGetValueTypeHash				= 0x0008000000000000,	///< This property can generate a meaningful hash value.
	CPF_NativeAccessSpecifierPublic		        = 0x0010000000000000,	///< Public native access specifier
	CPF_NativeAccessSpecifierProtected	        = 0x0020000000000000,	///< Protected native access specifier
	CPF_NativeAccessSpecifierPrivate	        = 0x0040000000000000,	///< Private native access specifier
	CPF_SkipSerialization				= 0x0080000000000000,	///< Property shouldn't be serialized, can still be exported to text
};

//访问我们需要的参数类型和名称

for (TFieldIterator<FProperty> i(TempFunc); i; ++i)
    FProperty* TempParam = *i;
    FString TempType = TempParam->GetCPPType();
    UE_LOG(LogTemp, Warning, TEXT("Current param Type is  ==%s"), *TempType);
    const FString One_Param = TempParam->GetNameCPP();
    UE_LOG(LogTemp, Warning, TEXT("Current param Name is  ==%s"), *One_Param);
}

//把入参Json字符串构造的对象值,赋值给参数对象数组

需要注意FVector和FRotator参数的读取方式
for (TFieldIterator<FProperty> i(TempFunc); i; ++i)
    FProperty* TempParam = *i;
    FString TempType = TempParam->GetCPPType();
    UE_LOG(LogTemp, Warning, TEXT("Current param Type is  ==%s"), *TempType);
    const FString One_Param = TempParam->GetNameCPP();
    if (TempParam->PropertyFlags & CPF_Parm)
        if (TempType.Equals("bool")){
            bool TempValue = inJsonObject->GetBoolField(One_Param);
            TempJsonObject->SetBoolField(One_Param, TempValue);
        }else if (TempType.Equals("FString")){
            FString TempValue = inJsonObject->GetStringField(One_Param);
            TempJsonObject->SetStringField(One_Param, TempValue);
        }else if (TempType.Equals("int32")) {
            int32 TempValue = inJsonObject->GetNumberField(One_Param);
            TempJsonObject->SetNumberField(One_Param, TempValue);
        }else if (TempType.Equals("int64")) {
            int64 TempValue = inJsonObject->GetNumberField(One_Param);
            TempJsonObject->SetNumberField(One_Param, TempValue);
        }else if (TempType.Equals("FVector")) {
            FVector TempValue;
            TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
            TempValue.X = TempObj->GetNumberField("X");
            TempValue.Y = TempObj->GetNumberField("Y");
            TempValue.Z = TempObj->GetNumberField("Z");
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("X", TempValue.X);
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("Y", TempValue.Y);
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("Z", TempValue.Z);
        }else if (TempType.Equals("FRotator")) {
            FRotator TempValue;
            TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
            TempValue.Roll = TempObj->GetNumberField("Roll");
            TempValue.Pitch= TempObj->GetNumberField("Pitch");
            TempValue.Yaw= TempObj->GetNumberField("Yaw");
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("Roll", TempValue.Roll);
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("Pitch", TempValue.Pitch);
            TempJsonObject->GetObjectField(One_Param)->SetNumberField("Z", TempValue.Yaw);
        }else if (TempType.Equals("FTransform")){
        }else if (TempType.Equals("FColor")) {
        }else if (TempType.Equals("FLinearColor")) {
        }else if (TempType.Equals("FName")) {
        }else if (TempType.Equals("double")) {
        }else if (TempType.Equals("uint8")) {
    }

5. 序列化已经有了值的Json对象,然后调用即可

TArray<uint8> ParamsContainer;
FMemoryWriter Writer(ParamsContainer);
TSharedRef<TJsonWriter<UCS2CHAR>> JsonWriter = TJsonWriter<UCS2CHAR>::Create(&Writer);
FJsonSerializer::Serialize(TempJsonObject.ToSharedRef(), JsonWriter);
FMemoryReader Reader(ParamsContainer);
FJsonStructDeserializerBackend DeserializerBackend(Reader);
FStructDeserializer::Deserialize(Params.GetData(), *TempFunc, DeserializerBackend);
inObj->ProcessEvent(TempFunc, Params.GetData());
Params.Empty();
Reader.Close();
Writer.Close();

6.测试结果

遗留问题:

1. 每次修改蓝图函数之后,保存,调用,会直接崩溃:可能原因,重新保存会导致反射系统重新编译函数,和上次函数调用的参数结构出现冲突
2.再函数体里面print输出之前没法添加append,但是事件可以

补充解决上面问题

.cpp

调用蓝图中普通带参的函数内容
测试截图,字符串是json格式
//SetActorScale3D
  "NewScale3D": {
    "X": 100.0,
    "Y": 200.0,
    "Z": 300.0
//SetActorHiddenInGame
  "bNewHidden":true
}


void UOpenAPICoreSystem::CallFunctionByNameWithParam(UObject* inObj, const FString inName, const FString inJsonStr) {
	UFunction* TempFunc = nullptr;
	UClass* TempClass = nullptr;
	UClass* Super = nullptr;
	uint16 TempParamsSize=0;
	uint8 TempParamsNum = 0;
	TempClass = inObj->GetClass();
	TempFunc = TempClass->FindFunctionByName(*inName);
	//开始遍历参数写入到Json数据里面
	TempParamsSize = TempFunc->ParmsSize;
	TempParamsNum = TempFunc->NumParms;
	if (TempParamsNum & 0)
		CallFunctionByNameNoParam(inObj, inName);
	else {
		TArray<uint8> Params;
		Params.AddUninitialized(TempParamsSize);
		TempFunc->InitializeStruct(Params.GetData());
		TSharedPtr<FJsonObject> TempJsonObject = MakeShared<FJsonObject>();
		for (TFieldIterator<FProperty> it(TempFunc); it; ++it) {
			FProperty* p = *it;
			if (p->PropertyFlags & CPF_Parm) {
				TempJsonObject->SetField(p->GetNameCPP(), NULL);
		if (TempJsonObject)
			//将输入的参数转换为Json对象,方便读取之后,给函数赋值
			TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(inJsonStr);
			TSharedPtr<FJsonObject> inJsonObject;
			bool bIsOk = FJsonSerializer::Deserialize(JsonReader, inJsonObject);
			if (bIsOk) {
				//遍历函数参数,获取参数名称和类型
				FString    inStr
				FRotator   inRot
				uint8		inByte
				int64		inInt64
				double		infloat
				FName		inName
				int32		inInt
				FVector		inVec
				FTransform	inTrans
				FColor		inColor
				FLinearColor
				for (TFieldIterator<FProperty> i(TempFunc); i; ++i)
					FProperty* TempParam = *i;
					FString TempType = TempParam->GetCPPType();
					UE_LOG(LogTemp, Warning, TEXT("Current param Type is  ==%s"), *TempType);
					const FString One_Param = TempParam->GetNameCPP();
					if (TempParam->PropertyFlags & CPF_Parm)
						if (TempType.Equals("bool")){
							bool TempValue = inJsonObject->GetBoolField(One_Param);
							TempJsonObject->SetBoolField(One_Param, TempValue);
						}else if (TempType.Equals("FString")){
							FString TempValue = inJsonObject->GetStringField(One_Param);
							TempJsonObject->SetStringField(One_Param, TempValue);
						}else if (TempType.Equals("int32")) {
							int32 TempValue = inJsonObject->GetNumberField(One_Param);
							TempJsonObject->SetNumberField(One_Param, TempValue);
						}else if (TempType.Equals("int64")) {
							int64 TempValue = inJsonObject->GetNumberField(One_Param);
							TempJsonObject->SetNumberField(One_Param, TempValue);
						}else if (TempType.Equals("FVector")) {
							TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
							TSharedPtr<FJsonObject> VecObject = MakeShared<FJsonObject>();
							VecObject->SetNumberField("X", TempObj->GetNumberField("X"));
							VecObject->SetNumberField("Y", TempObj->GetNumberField("Y"));
							VecObject->SetNumberField("Z", TempObj->GetNumberField("Z"));
							TempJsonObject->SetObjectField(One_Param, VecObject);
						}else if (TempType.Equals("FRotator")) {
							TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
							TSharedPtr<FJsonObject> VecObject = MakeShared<FJsonObject>();
							VecObject->SetNumberField("Roll", TempObj->GetNumberField("Roll"));
							VecObject->SetNumberField("Pitch",TempObj->GetNumberField("Pitch"));
							VecObject->SetNumberField("Yaw",  TempObj->GetNumberField("Yaw"));
							TempJsonObject->SetObjectField(One_Param, VecObject);
						}else if (TempType.Equals("FTransform")){
						}else if (TempType.Equals("FColor")) {
						}else if (TempType.Equals("FLinearColor")) {
						}else if (TempType.Equals("FName")) {
						}else if (TempType.Equals("double")) {
						}else if (TempType.Equals("uint8")) {
						UE_LOG(LogTemp, Warning, TEXT("Current param is ==%s"), *TempParam->GetNameCPP());
					else if (TempParam->PropertyFlags & CPF_ReturnParm) {
		TArray<uint8> ParamsContainer;
		FMemoryWriter Writer(ParamsContainer);
		TSharedRef<TJsonWriter<UCS2CHAR>> JsonWriter = TJsonWriter<UCS2CHAR>::Create(&Writer);
		FJsonSerializer::Serialize(TempJsonObject.ToSharedRef(), JsonWriter);
		FMemoryReader Reader(ParamsContainer);
		FJsonStructDeserializerBackend DeserializerBackend(Reader);
		FStructDeserializer::Deserialize(Params.GetData(), *TempFunc, DeserializerBackend);
		inObj->ProcessEvent(TempFunc, Params.GetData());	
}

调用带有引用参数的函数

k2_setActorLocation
{
    "NewLocation": {
        "X": 100.0,
        "Y": 200.0,
        "Z": 300.0
    "bsweep": false,
    "SweepHitResult": "",
    "btelepot": false
void UOpenAPICoreSystem::CallFunctionByNameWithParam(UObject* inObj, const FString inName, const FString inJsonStr) {
    UFunction* TempFunc = nullptr;
    UClass* TempClass = nullptr;
    UClass* Super = nullptr;
    uint16 TempParamsSize=0;
    uint8 TempParamsNum = 0;
    TempClass = inObj->GetClass();
    TempFunc = TempClass->FindFunctionByName(*inName);
    if (!TempFunc) 
        Super = TempClass->GetSuperClass();
        TempFunc=Super->FindFunctionByName(*inName);
        if (!TempFunc) {
            bool Out = true;
            int times = 0;
            while (Out && times < 1024) {
                Super = Super->GetSuperClass();
                TempFunc = Super->FindFunctionByName(*inName);
                ++times;
                if (TempFunc) {
                    Out = false;
    //开始遍历参数写入到Json数据里面
    TempParamsSize = TempFunc->ParmsSize;
    TempParamsNum = TempFunc->NumParms;
    if (TempParamsNum & 0)
        CallFunctionByNameNoParam(inObj, inName);
    else {
        TArray<uint8> Params;
        Params.AddUninitialized(TempParamsSize);
        TempFunc->InitializeStruct(Params.GetData());
        TSharedPtr<FJsonObject> TempJsonObject = MakeShared<FJsonObject>();
        if (TempJsonObject)
            //将输入的参数转换为Json对象,方便读取之后,给函数赋值
            TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(inJsonStr);
            TSharedPtr<FJsonObject> inJsonObject;
            bool bIsOk = FJsonSerializer::Deserialize(JsonReader, inJsonObject);
            if (bIsOk) {
                //遍历函数参数,获取参数名称和类型
FString    inStr
FRotator   inRot
uint8		inByte
int64		inInt64
double		infloat
FName		inName
int32		inInt
FVector		inVec
FTransform	inTrans
FColor		inColor
FLinearColor
FHitResult
                for (TFieldIterator<FProperty> i(TempFunc); i; ++i)
                        FProperty* TempParam = *i;
                        FString TempType = TempParam->GetCPPType();
                        UE_LOG(LogTemp, Warning, TEXT("Current param Type is  ==%s"), *TempType);
                        const FString One_Param = TempParam->GetNameCPP();
                        if (TempParam->PropertyFlags & CPF_Parm)
                            if (TempType.Equals("bool")){
                                bool TempValue = inJsonObject->GetBoolField(One_Param);
                                TempJsonObject->SetBoolField(One_Param, TempValue);
                                continue;
                            }else if (TempType.Equals("FString")){
                                FString TempValue = inJsonObject->GetStringField(One_Param);
                                TempJsonObject->SetStringField(One_Param, TempValue);
                                continue;
                            }else if (TempType.Equals("int32")) {
                                int32 TempValue = inJsonObject->GetNumberField(One_Param);
                                TempJsonObject->SetNumberField(One_Param, TempValue);
                                continue;
                            }else if (TempType.Equals("int64")) {
                                int64 TempValue = inJsonObject->GetNumberField(One_Param);
                                TempJsonObject->SetNumberField(One_Param, TempValue);
                                continue;
                            }else if (TempType.Equals("FVector")) {
                                TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
                                TSharedPtr<FJsonObject> VecObject = MakeShared<FJsonObject>();
                                VecObject->SetNumberField("X", TempObj->GetNumberField("X"));
                                VecObject->SetNumberField("Y", TempObj->GetNumberField("Y"));
                                    VecObject->SetNumberField("Z", TempObj->GetNumberField("Z"));
                                    TempJsonObject->SetObjectField(One_Param, VecObject);
                                    continue;
                                    }else if (TempType.Equals("FRotator")) {
                                    TSharedPtr<FJsonObject> TempObj = inJsonObject->GetObjectField(One_Param);
                                    TSharedPtr<FJsonObject> VecObject = MakeShared<FJsonObject>();
                                    VecObject->SetNumberField("Roll", TempObj->GetNumberField("Roll"));
                                    VecObject->SetNumberField("Pitch",TempObj->GetNumberField("Pitch"));
                                    VecObject->SetNumberField("Yaw",  TempObj->GetNumberField("Yaw"));
                                    TempJsonObject->SetObjectField(One_Param, VecObject);
                                    continue;
                                    }else if (TempType.Equals("FTransform")){
                                    continue;
                                    }else if (TempType.Equals("FColor")) {
                                    continue;
                                    }else if (TempType.Equals("FLinearColor")) {
                                    continue;
                                    }else if (TempType.Equals("FName")) {
                                    continue;
                                    }else if (TempType.Equals("double")) {
                                    continue;
                                    }else if (TempType.Equals("uint8")) {
                                    continue;
                                    else if (TempType.Equals("FHitResult")) {
                                    FHitResult Result;
                                    Result.Init();
                                    TSharedPtr<FJsonObject> ResultJsonObject = MakeShared<FJsonObject>();
                                    FJsonObjectConverter::UStructToJsonObject(FHitResult::StaticStruct(), &Result, ResultJsonObject.ToSharedRef());
                                    TempJsonObject->SetObjectField(One_Param, ResultJsonObject);
                                    continue;
                                    UE_LOG(LogTemp, Warning, TEXT("Current param is ==%s"), *TempParam->GetNameCPP());
                                    else if (TempParam->PropertyFlags & CPF_ReturnParm) {
                                    TArray<uint8> ParamsContainer;
                                    FMemoryWriter Writer(ParamsContainer);
                                    TSharedRef<TJsonWriter<UCS2CHAR>> JsonWriter = TJsonWriter<UCS2CHAR>::Create(&Writer);
                                    FJsonSerializer::Serialize(TempJsonObject.ToSharedRef(), JsonWriter);