1.UE4常用类型转换
FString 和FName相互转换
std::string和FString相互转换
FString与int float bool的相互转换
FString转换char*和FText以及FText与FName的相互转换
FString和TArray< uint8 >相互转换
这个遇到空格和换行符转换不过去(貌似)
枚举和字符串相互转换
int32转FString
int32 num = 9000;
FString IntAsString = FString::FromInt(num);
2.常用的宏
在C++中封装的函数名可以和在蓝图中调用的函数名称不同,设置方式
3.代理(绑定)
单播代理
绑定Lambda(匿名函数)的代理
绑定原生C++类的代理
绑定共享指针(智能指针)(绑定TSharedPtr指向对象的函数,即纯C++类的函数。因为纯C++类一般会使用TSharedPtr用于管理内存)
绑定静态函数
如果不是全局静态方法需要加上类名作用域
绑定线程安全的共享指针(绑定一个线程安全的TSharedPtr包裹着的纯C++类里面的函数)
绑定一个方法
绑定继承于UObject类的类里的成员函数
解除绑定
多播代理(可以绑定多个函数)
注意:多播代理上绑定的函数执行顺序是不固定的,并且多播代理是没有返回值的
绑定方式
广播方式执行
动态代理绑定的方法一定要加UFUNCTION的宏,否则绑定不成功,因为动态多播主要是提供给蓝图使用
动态单播代理(可以暴露给蓝图使用)
绑定方式
动态多播代理
绑定方式
4.XML读取(主要用的是FXmlFile和FXmlNode)
首先包含XML模块
获取平台文件管理器
判断文件是否存在
解析的XML文件
解析代码:
将解析文件放在项目的save目录下(放哪都行)
5.定义函数指针
函数指针调用
例子
#include <iostream>
using namespace std;
class test01
{
public:
int(test01::* tfun)(int, int) = NULL;
// using testf=int(*)(int, int);
int fun1(int i1, int i2)
{
return i1 + i2;
}
};
class test02
{
public:
int(test01::* tfun2)(int, int) = NULL;
int fun2(int i1, int i2)
{
return i1 + i2;
}
};
int test04(int a,int b)
{
return a + b;
}
int main()
{
test01 t1;
test02 t2;
int c;
t1.tfun = &test01::fun1;
c = (t1.*(t1.tfun))(1, 2);
cout << "c=" << c << endl;
t2.tfun2 = &test01::fun1;
c = (t1.*(t2.tfun2))(2, 5);
cout << "c=" << c << endl;
int(test01:: * testf1)(int, int) = NULL;
testf1= &test01::fun1;
c = (t1.*testf1)(7,2);
cout << "c=" << c << endl;
typedef int(test01::* P)(int, int);//声明一个函数指针的类
P p = &test01::fun1;
c = (t1.*p)(5,6);
cout << "c=" << c << endl;
int( * p1)(int, int) = NULL;
p1 = test04;
c=p1(8,1);
cout << "c=" << c << endl;
}
6.创建对象
创建和释放object对象
创建和释放Actor对象
7.在C++中用UE4蓝图的print string结点
#include "Kismet/KismetSystemLibrary.h"
void test (FString StrContent)
{
UKismetSystemLibrary::PrintString(this, StrContent);
}
打印日志(屏幕输出,同print string)
#include "Engine.h"
void test ()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, TEXT("Hello"));
}
/*
第一个参数:-1表示无需更新或刷新此消息
第二个参数:表示在屏幕上持续的时间
第三个参数:表示颜色
第四个参数:表示输出的信息
*/
7.UE4C++中的智能指针
共享指针
TSharedPtr<FunctionName,ESPMode::ThreadSafe> SharedPtr=MakeShareable(new FunctionName());//不加ESPMode::ThreadSafe是创建线程不安全的共享指针,在不涉及到线程时候用
//判断是否有效
if(SharedPtr.IsValid())
{
SharedPtr->Function();//FounctionName中的方法
}
//获取引用计数
int32 Count =SharedPtr.GetShareReferenceCount();
//解引用
FuntionName *fun=SharedPtr.Get();
//手动释放
//SharedPtr =nullptr; or
SharedPtr.Reset();
共享引用 (指针可以置空引用不可以)
//创建共享引用
TSharedRef<FuntionName>TestRef= MakeShareable(new FunctionName);//隐式转化
TSharedRef<FuntionName>TestRef1(new FunctionName);
//TSharedRef<FuntionName>TestRef1=nullptr; //错误
//不需要判断是否有效
TestRef.IsUNique();//判断是否是唯一拥有该对象;
相互转化
(1)共享引用转化成共享指针
TSharedRef<FuntionName>TestRef= MakeShareable(new FunctionName);
TSharedPtr<FunctionName>TestPtr=TestRef;
(2)共享指针转化成共享引用
TSharedPtr<FunctionName>TestPtr=MakeShareable(new FunctionName());
TSharedRef<FuntionName>TestRef= TestPtr.ToSharedRef();
(3)共享指针父子级之间的转化
class FResBase
{
public:
FResBase()
{
UE_LOG(LogTemp, Warning, TEXT("FResBase:基类构造"));
}
void TestFun()
{
UE_LOG(LogTemp, Warning, TEXT("FResBase:基类方法"));
}
~FResBase()
{
UE_LOG(LogTemp, Warning, TEXT("FResBase:基类析构"));
}
};
class FResSon :public FResBase
{
public:
FResSon()
{
UE_LOG(LogTemp, Warning, TEXT("FResSon:子类构造"));
}
void TestDeviceFun()
{
UE_LOG(LogTemp, Warning, TEXT("FResSon:子类方法"));
}
~FResSon()
{
UE_LOG(LogTemp, Warning, TEXT("FResSon:子类构造"));
}
};
{
TSharedPtr<FResBase>Res = MakeShareable(new FResSon);//多态
if (Res.IsValid())
{
Res->TestFun();
TSharedPtr<FResSon>ResSon = StaticCastSharedPtr<FResSon>(Res);//引用的话用StaticCastSharedRef
if (ResSon.IsValid())
{
ResSon->TestDeviceFun();
}
}
}
{
//去掉const属性的转化
const TSharedPtr<FResBase>ConstRes = MakeShareable(new FResSon);//多态
if (Res.IsValid())
{
TSharedPtr<FResBase>Res = ConstCastSharedPtr<FResBase>(ConstRes);//引用的话用ConstCastSharedRef
}
}
弱指针的用法
(1)弱指针不能影响强指针的引用计数
(2)在使用弱指针时,需要对其进行检测,判断其是否有效
(3)弱指针最大的用途就是解决环形引用的问题
(4)弱指针另一个作用就是,不对资源进行竞争。只能使用资源,却没有权限控制资源的生命周期
TSharedPtr
class test
{
public:
void Upadate (const TSharedPtr<ClassName>&Name);
}
class ClassName : public TSharedFromThis<ClassName>
{
public:
void Function()
{
test t1;
t1.Upadate(this->AsShared());
}
};
//普通指针转智能指针
ClassName* name=new ClassName;
TSharedPtr<ClassName> n1=name->AsShared();//转化
//or
TSharedPtr<CalssName>n1(MakeShareable(name));
8.运行时向数据表添加数据
#include "Engine/DataTable.h"
USTRUCT(BlueprintType)
struct FWarning :public FTableRowBase
{
GENERATED_USTRUCT_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
FDateTime ReactedAt;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
FString AreaID;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
FString AlertID;
};
UDataTable* WarningInfoDataTable;
FWarning* Warning = new FWarning();
int RowIndex;
TArray<FName>TableRowNames;
void AMonitorManager::AddWarningRow(FDateTime tReactedAt, FString tAreaID, FString tAlertID)
{
if(WarningInfoDataTable)
{
Warning->AlertID = tAlertID;
Warning->AreaID = tAreaID;
Warning->ReactedAt = tReactedAt;
TableRowNames = WarningInfoDataTable->GetRowNames();
RowIndex = TableRowNames.Num();
FString RowStr = FString::FromInt(RowIndex);
FName RowName = FName(*RowStr);
WarningInfoDataTable->AddRow(RowName, *Warning);
//Save DataTable
UPackage* const Package = WarningInfoDataTable->GetOutermost();
FString const PackageName = Package->GetName();
FString const PackageFileName = FPackageName::LongPackageNameToFilename(PackageName,FPackageName::GetAssetPackageExtension());
UPackage::SavePackage(Package,NULL,RF_Standalone,*PackageFileName,GError,nullptr,false,true,SAVE_NoError);
}
}
9.计算时间(日历)
int UBPFuncionLibraryBPLibrary::CalculateWeekDay(int32 y, int32 m, int32 d)
{
int Mon = 1;
int Tue = 2;
int Wed = 3;
int Thr = 4;
int Fri = 5;
int Sat = 6;
int Sun = 7;
int nList[] = { Mon,Tue,Wed,Thr,Fri,Sat,Sun };
//L"1",L"2",L"3",L"4" ,L"5",L"6",L"7"
if (m == 1 || m == 2) {
m += 12;
y--;
}
int32 iWeek = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
if (iWeek < 0 || iWeek >6)
return Wed;
return nList[iWeek];
}
int UBPFuncionLibraryBPLibrary::CalculateDaysInMonth(int32 y, int32 m)
{
int d;
int day[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
if (2 == m)
{
d = (((0 == y % 4) && (0 != y % 100) || (0 == y % 400)) ? 29 : 28);
}
else
{
d = day[m - 1];
}
return d;
}
9.JSON数据读取(插件中)
1.Time
2.String
3.Object
4.Long & Int & Double & Bool
5.Array
10.lambda表达式
int a;
int b;
[]()
{
};
//[=]是以值传递的方式获取类中变量
//[&]是以引用的方式获取类中变量
//[a,&b]以值或者引用方式获取类中指定变量
//值传递时想修改变量时要加mutable
[]()mutable
{
};
//有返回值的lambda表达式
[](int32 c,float d)mutable ->int32
{
return a+c;
};
//接受lambda表达式
auto LambdaFunc=[]()
{
};
11.获取当前物体的运行时间
float RunningTime =GetGameTimeSinceCreation();
12.写日志到文件里
#include "HAL/PlatformFilemanager.h"
#include "Runtime\Core\Public\Misc\FileHelper.h"
//写日志到文件
void FCCommonFun::WriteLog(FString StrLog /*= FString(TEXT(""))*/, FString StrFileName /*= FString(TEXT("D:/Log.txt"))*/)
{
if (StrFileName.IsEmpty())
{
StrFileName = FString(TEXT("D:/Log.txt"));
}
FString AbsoluteFilePath(*StrFileName);
IFileManager* FileManager = &IFileManager::Get();
FString TextToSave = FDateTime::Now().ToString();
uint32 WriteFlags = (uint32)(EFileWrite::FILEWRITE_Append);
TextToSave.Append("-");
TextToSave.Append(StrLog);
TextToSave.Append("\r\n");
FFileHelper::SaveStringToFile(TextToSave, *AbsoluteFilePath, FFileHelper::EEncodingOptions::AutoDetect, FileManager, WriteFlags);
}
//第二种(需要用MultiLog插件)
FString LogInfo = TEXT("");
// 日志输出
LogInfo.Append(FString::Printf(TEXT("[%d:%.2f_%.2f_%.2f %.2f ]"), Participant.id, Participant.Transform.GetLocation().X, Participant.Transform.GetLocation().Y, Participant.Transform.GetLocation().Z, Participant.courseAngle));
// 写入
UMultiLogSubsystem::AddLog(FName(TEXT("ResultConvert")), EMultiLogLevel::Info, TEXT("%s"), *LogInfo);
13.UE4解码Base64编码图片
#include <IImageWrapperModule.h>
#include <IImageWrapper.h>
#include "Http.h"
#include "Serialization/JsonSerializerMacros.h"
UTexture2D* AHomeFunction::GetLocalTexture(TArray<uint8>& ImageData)
{
UTexture2D* OutTex = NULL;
IImageWrapperModule& imageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
TSharedPtr<IImageWrapper> imageWrapper = imageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);
if (imageWrapper.IsValid() &&
imageWrapper->SetCompressed(ImageData.GetData(), ImageData.Num()))
{
TArray<uint8> uncompressedRGBA;
if (imageWrapper->GetRaw(ERGBFormat::RGBA, 8, uncompressedRGBA))
{
const TArray<FColor> uncompressedFColor = uint8ToFColor(uncompressedRGBA);
OutTex = TextureFromImage(
imageWrapper->GetWidth(),
imageWrapper->GetHeight(),
uncompressedFColor,
true);
}
}
return OutTex;
}
TArray<FColor> AHomeFunction::uint8ToFColor(const TArray<uint8> origin)
{
TArray<FColor> uncompressedFColor;
uint8 auxOrigin;
FColor auxDst;
for (int i = 0; i < origin.Num(); i++) {
auxOrigin = origin[i];
auxDst.R = auxOrigin;
i++;
auxOrigin = origin[i];
auxDst.G = auxOrigin;
i++;
auxOrigin = origin[i];
auxDst.B = auxOrigin;
i++;
auxOrigin = origin[i];
auxDst.A = auxOrigin;
uncompressedFColor.Add(auxDst);
}
return uncompressedFColor;
}
UTexture2D* AHomeFunction::TextureFromImage(const int32 SrcWidth, const int32 SrcHeight, const TArray<FColor>& SrcData, const bool UseAlpha)
{
// 创建Texture2D纹理
UTexture2D* MyScreenshot = UTexture2D::CreateTransient(SrcWidth, SrcHeight, PF_B8G8R8A8);
// 锁住他的数据,以便修改
uint8* MipData = static_cast<uint8*>(MyScreenshot->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
// 创建纹理数据
uint8* DestPtr = NULL;
const FColor* SrcPtr = NULL;
for (int32 y = 0; y < SrcHeight; y++)
{
DestPtr = &MipData[(SrcHeight - 1 - y) * SrcWidth * sizeof(FColor)];
SrcPtr = const_cast<FColor*>(&SrcData[(SrcHeight - 1 - y) * SrcWidth]);
for (int32 x = 0; x < SrcWidth; x++)
{
*DestPtr++ = SrcPtr->B;
*DestPtr++ = SrcPtr->G;
*DestPtr++ = SrcPtr->R;
if (UseAlpha)
{
*DestPtr++ = SrcPtr->A;
}
else
{
*DestPtr++ = 0xFF;
}
SrcPtr++;
}
}
// 解锁纹理
MyScreenshot->PlatformData->Mips[0].BulkData.Unlock();
MyScreenshot->UpdateResource();
return MyScreenshot;
}
//解码
FString fsImgBase64 = //base64图片码;
if (!fsImgBase64.IsEmpty())
{
TArray<uint8> arrImg;
FBase64::Decode(fsImgBase64, arrImg);
SafeBoardInfo.LmageInfo_Base64 = GetLocalTexture(arrImg);
}