Unreal Engine 大象无形学习笔记 (第一部分:虚幻C++编程)
Q1. 什么时候继承自UObject类,什么时候声明纯C++类?
UObject自带功能:
1. 垃圾收集:继承自UObject并被标记为UProperty的变量,会被引擎自动进行生命周期管理。
2. Reference updating 引用自动更新
3. 反射
4. 序列化:纯C++类也可以手动实现
5. Automatic updating of default property changes 自动检测默认变量的更改
6. Automatic property initialization 自动变量初始化
7. Automatic editor integration 编辑器自动交互:在Editor里可直接编辑
8. Type information available at runtime 运行时类型识别 :Cast<>
9. 网络复制:在引擎加载阶段创建Default Object,构造函数被调用时,UWorld不一定存在,GetWorld()返回值可能为空!
Q2. 什么时候继承自Actor类?
需要挂载组件时。
Q3. 什么时候继承Pawn类,什么时候继承Character类?
需要移动组件继承Character类,不需要移动逻辑,比如飞船,继承Pawn类。
Q4. 怎么创建纯C++类并被UE识别?
前缀 | 类型 | 创建对象 | 获取对象 | 内存管理 |
F | 纯C++类 | new |
delete 普通指针转换智能指针: TSharedPtr<YourClass> YourClassPtr = MakeShareable(new YourClass()); |
|
U | 继承自UObject,但不继承自Actor | NewObject<T>() | 自动垃圾回收,通过AddToRoot不被回收 | |
A | 继承自Actor | GetWorld()->SpawnActor<ActorClass>() |
for (TActorIterator<AStaticMeshActor> ActorIter(GetWorld()); ActorIter; ++ActorIter)
TArray<AActor*> OutActors;
static void GetAllActorsWithTag(const UObject* WorldContextObject, FName Tag, TArray<AActor*>& OutActors);
static void GetAllActorsWithInterface(const UObject* WorldContextObject, TSubclassOf<UInterface> Interface, TArray<AActor*>& OutActors);
APlayerController* playerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
APlayerController* playerController = GetWorld()->GetFirstPlayerController();
APawn* myPawn = Cast<ADrone>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
APawn* myPawn = GetWorld()->GetFirstPlayerController()->GetPawn();
ACharacter* myPawn = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
ACharacter* myPawn = GetWorld()->GetFirstPlayerController()->GetCharacter(); |
Destory() 只是从世界中销毁,内存还是系统自动回收 |
S | Slate控件相关类 | SNew | ||
H | HitResult相关类 |
Q7. 正则表达式
1) 添加头文件:#include "Regex.h"
2)构造函数:FRegexPattern
3)执行函数:FRegexMatcher
常用:bool FindNext()
Q8. 怎么获取游戏路径?
FPath::GameDir() //游戏根目录 FPath::FileExists() //判断文件是否存在 FPath::ConvertRelativePathToFull() //相对路径转换为绝对路径
Q9. XML与JASON怎么序列化与反序列化?
XML Parse工具:FastXML、FXmlFile
Q10.文件操作
获取路径:FPaths
读写:FPlatformFileManager
函数 | 作用 |
CopyDirectoryTree | 递归拷贝目录 |
CopyFile | 拷贝当前文件 |
CreateDirectory | 创建目录 |
CreateDirectoryTree | 创建一个目录树 |
DeleteDirectory | 删除指定目录 |
DeleteDirectoryRecursively | 递归删除指定目录 |
DeleteFile | 删除指定文件 |
MoveFile | 移动文件 |
DirectoryExists | 检查目录是否存在 |
FileExists | 检查文件是否存在 |
GetStateData | 获得文件状态信息,返回FFileStatData类型对象 |
FileSize | 获得文件大小,文件不存在返回-1 |
IterateDirectory | 遍历目录 |
OpenRead | 打开并读取文件,返回IFileHandle |
OpenWrite | 打开并写入文件 |
LoadFileToArray LoadFileToString |
将指定路径文件读取到TArray<uint8>数组 注意字符串有长度限制 |
SaveArrayToFile SaveStringToFile |
保存到指定文件 |
LoadANSITextFileToStrings |
读取ANSI编码的文本到字符串数组中 |
Q11. 读写配置文件
GConfig->SetString( //还有SetBool、SetInt、SetFloat等 TEXT("Section"), TEXT("Key"), TEXT("Value"), FPath::GameDir()/ "MyConfig.ini");
FString Result; GConfig->GetString( TEXT("Section"), TEXT("Key"), Result, FPath::GameDir()/ "MyConfig.ini");
刷新缓冲区,马上生效:GConfig->Flush();
Q12. 怎么输出UE日志?
怎么查看LOG?打包后需要在启动参数加-log,编辑器运行需要打开Window->DeveloperTools->OutputLog
语法:UE_LOG(LogMy,Warning,TEXT("show a string:%s"),*FString("test"));
日志类型 | 输出颜色 |
Log | 灰色 |
Warning | 黄色 |
Error |
红色 |
输出到游戏界面:
GEngine->AddOnDebugScreenMessage()
Q13. 怎么自定义Category?
将以下定义放在被多数源文件引用的文件里
DEFINE_LOG_CATEGORY_STATIC(LogMyCategory,Warning,All);
Q14. 虚幻引擎有哪些字符串类?
类型 | 特点 |
FName | 数据结构是哈希表,所以是唯一的,大小写不敏感,不可修改 |
FText | 数据结构是查找表,内置本地化支持,用作被显示的字符串,不可修改 |
FString | 可修改 |
Q15. 虚幻引擎怎么跨平台?
平台相关工具函数类:FPlatformMisc
eg. typedef FLinuxPlatformMisc FPlatformMisc;
Q16. 怎么转换图片类型?
图片压缩后的数据:CompressedData
图片RGBA数据无压缩:RawData
ImageWrapper = CompressedData + RawData
怎么读取硬盘里的贴图?
1 UTexture2D * FSystemToolsPublic::LoadTexture2DFromBytesAndExtension(const FString& ImagePath , uint8* InCompressedData ,int32 InCompressedSize ,int32 & OutWidth,int32 & OutHeight) 2 { 3 UTexture2D * Texture = nullptr; 4 IImageWrapperPtr ImageWrapper = GetImageWrapperByExtention(ImagePath); 5 if (ImageWrapper.IsValid() && ImageWrapper ->SetCompressed(InCompressedData , InCompressedSize))//读取压缩后的图片数据 6 { 7 const TArray <uint8>* UncompressedRGBA = nullptr; 8 if (ImageWrapper ->GetRaw(ERGBFormat::RGBA, 8,UncompressedRGBA))//获取原始图片数据 9 { 10 Texture = UTexture2D::CreateTransient(ImageWrapper ->GetWidth(), ImageWrapper ->GetHeight(), PF_R8G8B8A8); 11 if (Texture != nullptr) 12 { 13 //通过内存复制,填充原始RGB数据到贴图的数据中 14 OutWidth = ImageWrapper ->GetWidth(); 15 OutHeight = ImageWrapper ->GetHeight(); 16 void * TextureData = Texture-> 17 PlatformData ->Mips[0].BulkData. 18 Lock(LOCK_READ_WRITE); 19 FMemory::Memcpy(TextureData, 20 UncompressedRGBA ->GetData(), 21 UncompressedRGBA ->Num()); 22 Texture->PlatformData ->Mips[0]. 23 BulkData.Unlock(); 24 Texture->UpdateResource(); 25 } 26 } 27 } 28 return Texture; 29 } 30 UTexture2D * FSystemToolsPublic::LoadTexture2DFromFilePath(FString & ImagePath,int32 & OutWidth,int32 & OutHeight) 31 { 32 //文件是否存在 33 if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*ImagePath)) 34 { 35 return nullptr; 36 } 37 //读取文件资源 38 TArray <uint8 > CompressedData; 39 if (!FFileHelper::LoadFileToArray(CompressedData , *ImagePath)) 40 { 41 return nullptr; 42 } 43 return LoadTexture2DFromBytesAndExtension(ImagePath,CompressedData.GetData(), CompressedData.Num(), OutWidth,OutHeight); 44 }