1. 日志打印

1.1. UE_LOG

1.1.1. 普通输出

FString filePath
UE_LOG(LogTemp, Log, TEXT("Hello,World!"));
UE_LOG(LogTemp, Warning, TEXT("Hello,World!"));
UE_LOG(LogTemp, Error, TEXT("Hello,World!"));

UE_LOG(LogTemp,Log,TEXT("throttle %d"), throttle);
FString filePath
UE_LOG(LogTemp, Log, TEXT("%s"), *filePath);

1.1.2. 自定义日志类型

.h
DECLARE LOG CATEGORY EXTERN(MyLog,Log,All);
.cpp
DEFINE_LOG_CATEGORY(MyLog);
UE_LOG(MyLog,Warning,TEXT ("Success"));

输出:
MyLog:Warning:Success

1.2. 屏幕输出

// 打印至屏幕
FString screenMessage = "(AddOnScreenDebugMessage) Hello world!";
GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Green, screenMessage);

// 打印至屏幕
UKismetSystemLibrary::PrintString(this, "(UKismetSystemLibrary::PrintString) Hello world!");

1.3. FString Format

//创建FString 变量 FString::Printf
FString playerName = "User";
int32 healthValue = 100;
FString outputMessage1 = FString::Printf(TEXT("Name is %s, health value is %d"), *playerName, healthValue);
UE_LOG(LogTemp, Warning, TEXT("FStringFormatArg: %s"), *outputMessage1);

//创建FString变量 FString::Format
TArray<FStringFormatArg> args;
args.Add(FStringFormatArg(playerName));
args.Add(FStringFormatArg(healthValue));

FString outputMessage2 = FString::Format(TEXT("Name is {0}, health value is {1}"), args);
UE_LOG(LogTemp, Warning, TEXT("FString::Format: %s"), *outputMessage2);

2. FString

2.1. UE4 Source Header References

CString.h
UnrealString.h
NameTypes.h
StringConv.h (TCHAR_TO_ANSI etc)

---> CString.h
Atoi64 (string to int64)
Atod (string to double precision float)

2.2. 类型转换

2.2.1. FString To FNames

不可靠,因为FName不区分大小写,所以转换存在丢失

//字符串
FString TheString = "Hello,world";
//将FString转换为FName
FName ConvertedFString = FName(*TheString);

2.2.2. FString To FText

FString TheString = "Hello,world";
FText ConvertedFSting=FText::FromSting(TheString);

2.2.3. FString To Array[uint8]

//方法1
FString JsonStr;
TArray<uint8> content;

content.SetNum(JsonStr.Len());
memcpy(content.GetData(), TCHAR_TO_ANSI(*JsonStr), JsonStr.Len());

//方法2
FString StrData;
const TCHAR* StrPtr = *StrData;
FTCHARToUTF8 UTF8String(StrPtr);
int32 CTXSize = UTF8String.Length();

TArray<uint8> URLData;
URLData.SetNum(CTXSize);
memcpy(URLData.GetData(), UTF8String.Get(), CTXSize);

2.2.4. FString To char*

FString TheString = "Hello,world";
char* MyCharPtr = TCHAR_TO_UTF8(*MyFString);

2.2.5. FString To const char *

const char *plainText= TCHAR_TO_ANSI(*aes_content);

2.2.6. FString To TCHAR*

FString s="a";
TCHAR* t=*s;

2.2.7. FString To std::string

#include <string>

FString UE4Str = TEXT("Flowers");
std::string MyStdString = TCHAR_TO_UTF8(*UE4Str);

2.2.8. FString To bool

FString TheString = "123.021";
bool MyBool = MyFString.ToBool();

2.2.9. FString To int32

FString TheString = "123.021";
//注意,Atoi和Atof是静态函数,所以使用语法FCString::TheFunction调用它:)
int32 MyShinyNewInt = FCString::Atoi(*TheString);

2.2.10. FString To int64

FString TheString = "12312345678789561234879";
//注意,Atoi64是静态函数,所以使用语法FCString::TheFunction调用它:)
int64 MyShinyNewInt = FCString::Atoi64(*TheString);

2.2.11. FString To float

FString TheString = "123.021";
//注意,Atoi和Atof是静态函数,所以使用语法FCString::TheFunction调用它:)
float MyShinyNewFloat = FCString::Atof(*TheString);

2.2.12. FString To double

//函数方式
bool UDoubleFunction::FStringToDouble(FString str,double &num)
{
std::string numString = TCHAR_TO_UTF8(*str);
double b = atof(numString.c_str());
if (b == NULL)
{
return false;
}
num =b;
return true;
}

//直接转换
FString TheString = "123.021";
//注意,Atod是静态函数,所以使用语法FCString::TheFunction调用它:)
double MyShinyNewFloat = FCString::Atod(*TheString);

//FString转String转Double
FString str = "113.5246854";
std::string numString = TCHAR_TO_UTF8(*str);
double b = atof(numString.c_str());

2.2.13. 转换 To FString

//int
FString NewString = FString::FromInt(MyInt);
//float //double ----只能精确到小数点后6位
FString VeryCleanString = FString::SanitizeFloat(MyFloat);
//bool
FString MyFString = MyBool?TEXT("true") :TEXT("false");
//FVector
FString MyFString = MyVector.ToString();
//FVector2D
FString MyFString = MyVector2D.ToString();
//FRotator
FString MyFString = MyRotator.ToString();
//FLinearColor
FString MyFString = MyLinearColor.ToString();
//UObject
FString MyFString = (MyObj != NULL) ? MyObj->GetName() : FString(TEXT("None"));
//FMatrix
FMatrix rotationMatrix(FPlane(0,1,2,3),FPlane(4,5,6,7),FPlane(8,9,10,11),FPlane(12,13,14,15));
FString str = rotationMatrix.ToString();

2.2.14. double To FString

//直接转换:精确到小数点后6位
return FString::SanitizeFloat(numeral.dou);

//double→string→FString精确到小数点后6位
std::string Str = std::to_string(numeral.dou);
FString string = UTF8_TO_TCHAR(Str.c_str());

//输出有效位数15位
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
string str;
double d = numeral.dou;
stringstream ss;
ss << setprecision(15) << d;
str = ss.str();
FString string = UTF8_TO_TCHAR(str.c_str());

//指定小数点后几位 --注:double的有效位数只有16位,小数点算一位
double doub = 9999.1234567891011121314;
FString TimeDesc = FString::Printf(TEXT("%.15f"), doub); //9999.123456789100601

2.2.15. bytes To FString

FString fstr;
for (int i(0); i < FaceArray.Num() * 4; ++i)
{
FString tmpStr;
ByteToHex(f_arrbytes[i], tmpStr);
fstr.Append(tmpStr);
}
UE_LOG(LogTemp, Log, TEXT("%S"), *fstr);

2.2.16. FArrayReaderPtr to FString

uint8 data[512];  
FMemory::Memzero(data, 512);
FMemory::Memcpy(data, ArrayReaderPtr->GetData(), ArrayReaderPtr->Num());
FString str = ((const char*)data);

2.2.17. Array[uint8] to FString

TArray<uint8> content;  
const std::string cstr(reinterpret_cast<const char*>(content.GetData()), content.Num());
FString frameAsFString = cstr.c_str();
UE_LOG(VRSLog, Warning, TEXT("%s"), *frameAsFString);

2.2.18. FString To MD5(FString)

FString str = TEXT("someStuff");
FString md5 = FMD5::HashAnsiString();

2.2.19. FString To Ascii/Unicode

FString str = TEXT("123苹果");
int32 ascii = (int32)Source[4]; //数字代表序号
int32 ascii2 = (int32)Source.GetCharArray()[4]; //或者第二种写法

2.2.20. FString From Ascii/Unicode

FString str;
int32 ascii = 49; //1的ascii是49。 中文 中的编码是20013
str.AppendChar(Ascii); //如果ascii为20013,转换出来时中

3. FName

3.1. FName To FString

FName str = FName(TEXT("hello"));
FString fstr = str.ToString();

3.2. FName To FText

FName str = FName(TEXT("hello"));
FText = FText::FromName(str);

4. FText

4.1. FText To FString

//不可靠,在一些语言中存在损耗
FString Name = MyText.ToString();

5. TChar*

5.1. TChar* 与 char* 的互相转换

TCHAR_TO_ANSI(*str)
ANSI_TO_TCHAR(*str)
TCHAR_TO_UTF8(*str)
UTF8_TO_TCHAR(*str)

6. std::string

6.1. std::string To FString

#include <string>

std::string MyStdString = "Happy";
FString HappyString(UTF8_TO_TCHAR(MyStdString.c_str())); //可防止string的中文转换出错

6.2. To string函数

c++11标准增加了全局函数std::to_string:

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val); //只能精确到小数点后6位
string to_string (double val); //只能精确到小数点后6位
string to_string (long double val);

6.3. string To函数

6.3.1. string To int

std::string str = "123";
int n = atoi(str.c_str());
cout<<n; //123

6.3.2. double->string

//有效位数20位   ---据说待考证
char buffer[100];
double b=1245683.141592653;
int ndight=20;//有效数字位数
gcvt(b,ndight,buffer);
cout<<buffer<<endl;

//一般使用方法:只能精确到小数点后6位
#include <string>
using namespace std;
double d = 3.1415926535897932384;
string str = std::to_string(d);
cout << str << std::endl; // 3.141593

//使用stringstream,在输入流时使用setprecision设置精度,需包含头文件 <iomanip>
//精度保持到小数点后15位
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
std::stringstream ss;
ss << setprecision(15) << d;
str = ss.str();
cout << str << std::endl; // 3.14159265358979

//对于double类型,setprecision(15) 参数最大有效值为15,超过15,数据就不保证可靠了。

6.3.3. string->double

string str="1245683.141592653";
double num=atof(str.c_str());
printf("%0.9lf\n",num);

7. char*

7.1. char* To FString

FString MyFString = FString(UTF8_TO_TCHAR(MyCharPtr));

8. Json & String

8.1. FString To JsonObject

// 处理Json需要在.Build.cs中添加Json模块
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Json",
// ... add private dependencies that you statically link with here ...
}
);

//注意String中使用双引号
FString JsonStr = TEXT("{\"key\":\"value\",\"key2\":\"value2\"}");
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonStr);
FJsonSerializer::Deserialize(Reader,JsonObject);
//JsonObject就是Json

8.2. JsonObject To FString

// 处理Json需要在.Build.cs中添加Json模块
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Json",
// ... add private dependencies that you statically link with here ...
}
);

//Jdata转换为了JsonStr
FString JsonStr;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonStr);
FJsonSerializer::Serialize(Jdata.ToSharedRef(), Writer);

9. 枚举相关转换

9.1. 根据枚举值获取枚举名字

template<typename TEnum>
FString GetEnumValueAsString(const FString& Name, TEnum Value);

template<typename TEnum>
FString MHDataHandle::GetEnumValueAsString(const FString& Name, TEnum Value)
{
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, true);
if (!EnumPtr)
{
return FString("InValid");
}
return EnumPtr->GetNameStringByIndex(static_cast<int32>(Value));
}

9.2. 根据枚举名字获取枚举值

template<typename TEnum>
FString GetEnumValueAsString(const FString& Name, TEnum Value);

template<typename TEnum>
TEnum MHDataHandle::GetEnumValueFromString(const FString& Name, FString Value)
{
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, true);
if (!EnumPtr)
{
return TEnum(0);
}
return static_cast<TEnum>(EnumPtr->GetIndexByName(FName(*FString(Value))));
}

9.3. 示例代码

UENUM()
enum class EExteriorType : uint8
{
None = 0,
Hair,
Cloth,
HeadWear,
};

EExteriorType TestEnum = GetEnumValueFromString<EExteriorType>(FString("EExteriorType"), FString("Hair")); // TestEnum = EExteriorType::Hair
FString TestName = GetEnumValueAsString<EExteriorType>(FString("EExteriorType"), TestEnum); // TestName = "Hair"

10. FMemory

uint8*pdata = (uint8*)FMemory::Malloc(1024);
FMemory::Memzero(pdata, 1024);
uint32 size = (uint32)FMemory::GetAllocSize(pdata);
UE_LOG(LogTemp, Warning, TEXT("内存大小{%d}!"), size);
//LogTemp: Warning: 内存大小{1024}!

--> UE_LOG(LogTemp, Warning, TEXT("字符串长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));
//LogTemp: Warning: 字符检测大小{0}!

FString fs = TEXT("1234567890中国");
FString fn = TEXT("abcdefg人");
TCHAR*tt = fs.GetCharArray().GetData();
uint8*ptmp = (uint8*)TCHAR_TO_UTF8(tt);
int32 fslen = FCStringAnsi::Strlen((ANSICHAR*)ptmp);
UE_LOG(LogTemp, Warning, TEXT("fs len{%d},{%d}"), fslen, FCString::Strlen(tt));
//LogTemp: Warning: fs len{16},{12}

FMemory::Memcpy(pdata, ptmp, fslen);
UE_LOG(LogTemp, Warning, TEXT("copy 1 %s"), UTF8_TO_TCHAR(ptmp));
//LogTemp: Warning: copy 1 1234567890中国

UE_LOG(LogTemp, Warning, TEXT("字符串长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));
//LogTemp: Warning: 字符串长度{16}!

tt = fn.GetCharArray().GetData();
ptmp = (uint8*)TCHAR_TO_UTF8(tt);
int32 fnlen = FCStringAnsi::Strlen((ANSICHAR*)ptmp);
FMemory::Memcpy(pdata + fslen, ptmp, fnlen);
UE_LOG(LogTemp, Warning, TEXT("copy 2 %s"), UTF8_TO_TCHAR(pdata));
//LogTemp: Warning: copy 2 1234567890中国abcdefg人

UE_LOG(LogTemp, Warning, TEXT("字符串长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));

//======================================================================
FMemory::Memmove(pdata, pdata + 10, 8);
UE_LOG(LogTemp, Warning, TEXT("copy 3 %s"), UTF8_TO_TCHAR(pdata));
//LogTemp: Warning: copy 3 中国ab90中国abcdefg人

FMemory::Memzero(pdata + 8, 18);
UE_LOG(LogTemp, Warning, TEXT("copy 3 %s"), UTF8_TO_TCHAR(pdata));
//LogTemp: Warning: copy 3 中国ab

UE_LOG(LogTemp, Warning, TEXT("字符串3长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));
//LogTemp: Warning: 字符串3长度{8}!

FMemory::Memmove(pdata, pdata + 3, 5);
UE_LOG(LogTemp, Warning, TEXT("copy 4 %s"), UTF8_TO_TCHAR(pdata));
//LogTemp: Warning: copy 4 国ab?ab

UE_LOG(LogTemp, Warning, TEXT("字符串4长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));
//LogTemp: Warning: 字符串4长度{6}!

FMemory::Memzero(pdata + 5, 3);
UE_LOG(LogTemp, Warning, TEXT("copy 4 %s"), UTF8_TO_TCHAR(pdata));
//LogTemp: Warning: copy 4 国ab

UE_LOG(LogTemp, Warning, TEXT("字符串4长度{%d}!"), FCStringAnsi::Strlen((ANSICHAR*)pdata));
// //LogTemp: Warning: 字符串4长度{5}!

FMemory::Free(pdata);

11. 大小端转换

//32位的转换

Int32 swapInt32(Int32 value)
{

return ((value & 0x000000FF) << 24) |
((value & 0x0000FF00) << 8) |
((value & 0x00FF0000) >> 8) |
((value & 0xFF000000) >> 24);

}

// 64位的转换

public static UInt64 Reverse64Bytes(UInt64 value)
{

return (value & 0x00000000000000FFUL) << 56 | (value & 0x000000000000FF00UL) << 40 |
(value & 0x0000000000FF0000UL) << 24 | (value & 0x00000000FF000000UL) << 8 |
(value & 0x000000FF00000000UL) >> 8 | (value & 0x0000FF0000000000UL) >> 24 |
(value & 0x00FF000000000000UL) >> 40 | (value & 0xFF00000000000000UL) >> 56;
}

12. 通过函数名调用函数

12.1. 有返回值

template<typename... TReturns, typename... TArgs>
void InvokeFunctionByName(UObject* obj, FName functionName, TTuple<TReturns...>& outParams, TArgs&&... args)
{
if (nullptr == obj || functionName.IsNone())
return;

UClass* cls = obj->GetClass();
if (nullptr == cls)
{
return;
}

UFunction* func = cls->FindFunctionByName(functionName);
if (nullptr == func)
{
return;
}

uint8* outPramsBuffer = (uint8*)&outParams;
if (func->HasAnyFunctionFlags(FUNC_Native)) //quick path for c++ functions
{
TTuple<TArgs..., TReturns...> params(Forward<TArgs>(args)..., TReturns()...);
obj->ProcessEvent(func, &params);
//copy back out params
for (TFieldIterator<UProperty> i(func); i; ++i)
{
UProperty* prop = *i;
if (prop->PropertyFlags & CPF_OutParm)
{
void* propBuffer = prop->ContainerPtrToValuePtr<void*>(&params);
prop->CopyCompleteValue(outPramsBuffer,propBuffer);
outPramsBuffer += prop->GetSize();
}
}
return;
}

TTuple<TArgs...> inParams(Forward<TArgs>(args)...);
void* funcPramsBuffer = (uint8*)FMemory_Alloca(func->ParmsSize);
uint8* inPramsBuffer = (uint8*)&inParams;

for (TFieldIterator<UProperty> i(func); i; ++i)
{
UProperty* prop = *i;
if (prop->GetFName().ToString().StartsWith("__"))
{
//ignore private param like __WolrdContext of function in blueprint funcion library
continue;
}
void* propBuffer = prop->ContainerPtrToValuePtr<void*>(funcPramsBuffer);
if (prop->PropertyFlags & CPF_OutParm)
{
prop->CopyCompleteValue(propBuffer, outPramsBuffer);
outPramsBuffer += prop->GetSize();
}
else if (prop->PropertyFlags & CPF_Parm)
{
prop->CopyCompleteValue(propBuffer, inPramsBuffer);
inPramsBuffer += prop->GetSize();
}
}

obj->ProcessEvent(func, funcPramsBuffer); //call function
outPramsBuffer = (uint8*)&outParams; //reset to begin

//copy back out params
for (TFieldIterator<UProperty> i(func); i; ++i)
{
UProperty* prop = *i;
if (prop->PropertyFlags & CPF_OutParm)
{
void* propBuffer = prop->ContainerPtrToValuePtr<void*>(funcPramsBuffer);
prop->CopyCompleteValue(outPramsBuffer, propBuffer);
outPramsBuffer += prop->GetSize();
}
}
}

12.2. 无返回值

template<typename... TArgs>
void InvokeFunctionByName(UObject* obj, FName functionName, TArgs&&... args)
{
if (nullptr == obj || functionName.IsNone())
return;

UClass* cls = obj->GetClass();
if (nullptr == cls)
{
return;
}

UFunction* func = cls->FindFunctionByName(functionName);
if (nullptr == func)
{
return;
}

if (func->HasAnyFunctionFlags(FUNC_Native))
{
TTuple<TArgs...> inParams(Forward<TArgs>(args)...);
obj->ProcessEvent(func, &inParams);
return;
}

TTuple<TArgs...> inParams(Forward<TArgs>(args)...);
void* funcPramsBuffer = (uint8*)FMemory_Alloca(func->ParmsSize);
uint8* inPramsBuffer = (uint8*)&inParams;

for (TFieldIterator<UProperty> i(func); i; ++i)
{
UProperty* prop = *i;
if (prop->GetFName().ToString().StartsWith("__"))
{
//ignore private param like __WolrdContext of function in blueprint funcion library
continue;
}
void* propBuffer = prop->ContainerPtrToValuePtr<void*>(funcPramsBuffer);
if (prop->PropertyFlags & CPF_Parm)
{
prop->CopyCompleteValue(propBuffer, inPramsBuffer);
inPramsBuffer += prop->GetSize();
}
}
obj->ProcessEvent(func, funcPramsBuffer); //call function
}