虚幻C++入门个人笔记(1)——一些基础、UE_LOG、TArray、翻译转换

工程目录文件

.vs                VS环境配置文件(不用管不要删)

Binaries       存放编译生成的结果二进制文件。该目录可以gitignore(可以忽略),每次都会生成

                        编译动态库        中间编译文件(虚幻按模块编译)(编译好的)

                        每个模块会产出一个动态库

                        当工程出了一些问题(热加载出问题),就把动态库全删掉重新生成

config                配置文件

content                内容文件夹,所有资源和蓝图等都在该目录里

intermediate        中间文件(gitignore),存放着一些临时生成的文件,有:

                           1.build的中间文件,.obj和预编译头等

                           2.UHT预处理生成的.generated.h/.cpp文件

                           3.VS.vcxproj项目文件,可通过.uproject文件生成编译生成的shader文件夹

                            4.AssetRegistryCache:Asset Registry系统的缓存文件

                          (Asset Registry可以简单理解为一个索引了所有uasset资源头信息的注册表)

                          (CachedAssetRegistry.bin文件也是如此)

saved                存储自动保存文件,其他配置文件,日志文件,引擎崩溃日志,硬件信息,烘培信息数据等。gitignore

source                源码文件夹(工程源码)

.sln                     VS启动文件

.uprojece

.VC.db

VS项目目录结构

1.Engine引擎源码文件(只读)(不完整),虚幻是开源项目我们可以直接在工程中看到引擎源码但是无法修改。如需修改需下载Git源码工程

2.Games项目工程文件(主要编写逻辑文件),我们的代码需要在此工程中编写。虚幻中采用了编译模块方式进行引擎构建,所以对于引擎来说,我们编写的内容只是一个模块,模块会被动态编译成库文件,加载到引擎中使用。Target.cs就是模块配置文件

3.Visualizers虚幻4.21加入的文件夹,VS编辑器配置文件

编译类型

状态 engine game 其他
debug(调试)(可查看信息更多,牺牲一些CPU和GPU事件来收集信息)

debug

debug 必须在编译器上加-debug参数才能反射查看代码更改
debuggame(调试游戏) release debug 适合只调试游戏代码
development(开发)(一般用这个) release release 允许编辑器发射查看代码更改
shipping(发行)(性能最优) release release 无控制台命令,统计数据和性能分析
test(测试) release release 启用了一些控制台命令,统计数据和性能分析
目标
空白 不带编辑器的一个独立可执行版本,需要提前打包烘培内容资源
editor(编辑器) 直接在编辑器里打开游戏项目
client(客户端) 多人联机项目,生成客户端版本,需要提供client target.cs文件
server(服务器) 多人联机项目,生成服务器版本,需要提供server target.cs文件

命名规则

变量命名规则

1.模板类以T作为前缀,比如TArray,TMap,TSet

2.UObject派生类都以U前缀

3.AActor派生类都以A前缀

4.SWidget派生类都以S前缀(组件)

5.全局对象使用G开头,如GEngine

6.抽象接口以I前缀

7.枚举以E开头,结构体都是以ST开头

8.bool变量以b前缀,如bPendingDestruction

9.其他的大部分以F开头,如FString,FName

10.typedef的以原型名前缀为准,如typedef TArray FArrayofMyTypes;

11.在编辑器里和C#里,类型名是去掉前缀过的

12.UHT在工作的时候需要你提供正确的前缀,所以虽然说是约定,但你也得必须遵守(编译系统怎么用到那些前缀,后续再讨论)

UE遵循帕斯卡命名法则

虚幻里没有多继承,有接口

资源命名规则

类型 前缀 说明
Level/Map L_ 关卡
Blueprint BP_ 常规蓝图
Material M_ 材质
StaticMesh S_ 静态网格体
SkeletalMesh SK_ 骨骼网格体
Texture T_ 纹理
ParticleSystem PS_ 粒子系统
WidgetBlueprint WBP_ 组件蓝图

文件夹命名规则

|--项目名称

        |-- Maps

        |-- Textures

        |-- Blueprints

        |-- Effects              (particle)

        |-- Animations

        |-- Sounds

        |-- Sources

我们建议,在引擎根目录进行细致的命名分化。以打到高效管理资产的目的,命名应遵循清晰,准确,简短的描述分类内容。尽量不要使用模糊描述。项目名称作为最顶层文件夹名称

命名规范网站

https://github.com/uejoy/ue4-style-guide

Actor相关

UE游戏世界中存在元素的根源,用来表示世界中的任何物体的高级抽象类,由Actor进行创建,Component进行行为组件,完成整个游戏世界的元素展示

Actor是一个载体,Component组件是能力

Acotr的创建方式为两种,第一种为直接在场景中编辑拖拽(静态创建),优势无需编码,更加直观简单,缺点可能影响游戏启动速度,增加场景构建负担。第二种为通过编码动态进行生成(动态创建,例如扔手雷)相对于前者复杂度上升,但可控性更强,动态生成的Actor会持有有效的操作指针,我们可以根据实际情况进行生成,更加灵活

SpawnActor函数

在蓝图中我们借助SpawnActorOfClass进行动态生成Actor,在C++中我们需要通过UWorld指针进行创建。在UWorld类中,我们可以找到多个生成Actor的函数。对于重载函数,我们根据特定的情况进行选择即可。SpawnActor函数是个工厂函数,下面地址中可以查到UWorld的相关API

http://api.unrealengine.com/INT/API/Runtime/Engine/Engine/UWorld/index.html

API——用户接口手册(描述类的结构)

生成Actor

首先我们需要获取到UWorld世界对象指针。对于每一个在场景中存在的对象,本身都具备获取UWorld指针的能力,我们只需要调用GetWorld函数即可获得UWorld对象指针。记得引入头文件(UWorld本身头文件已经在父类中被包含,所以无需额外引入)

StaticClass

合成函数,获取一个UClass指针。旨在将操作类作为一个参数进行传递(传递模板)。虚幻中除了使用模板构建对象外,还增加了映射关系,可以将类作为对象构建依据,这可以方便的将类提供给蓝图使用

注意:C++本身是编译型语言,我们在编译器中看到的文件类并不是真正的C++类,只是编译后生成的映射文件

组件的构建优于BeginPlay

删除ACTOR方式

Destroyed

LifeSpan

消亡ACTOR通知方式

Destroyed

当对象被删除时(非内存删除)进行回调操作

EndPlay

对象被彻底清除时回调,回调会进行删除类型通知

删除类型如下:

Destroyed        当Actor或Component彻底被删除时(内存中)

LevelTransition        关卡切换时删除回调(非关卡流)

EndPlayInEditor        编辑器关闭时,回调通知

RemovedFromWorld        关卡流切换被释放时调用

Quit        游戏退出时被删除回调

屏幕日志输出

借助全局变量GEngine指针调用函数AddOnScreenDebugMessage即可完成屏幕输出

例1:GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Blue, TEXT("OK"));

例2:GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Blue, TEXT("O"),true);

GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Blue, TEXT("K"),true);//OK

例3:GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Blue, TEXT("OK"),true,FVector2D(5,5));//OK放大5倍

Key如果是-1则添加新的消息,不会覆盖旧有消息

如果不是-1则更新现有消息,效率更高

bNewerOnTop当Key为-1时有效,直接添加到队列最上层

false为添加到队列最尾端

TEXT宏

虚幻中用来构建非对象型字符串的关键宏,构建结果是与平台无关的宽字符串(类似C语言字符串),借助对象FString带参构造函数TCHAR类型指针来构建FString对象字符串

各个平台的字符串格式不同,所以用TEXT宏,实质是L“字符串”,即宽字符串

编译的中文不打印的解决办法

文件里高级保存选项里面简体中文改成UTF-8带签名

没有就在工具,自定义,命令,添加命令,文件,高级保存项添加进去

头文件的注意

1.对应源文件的头文件在最顶端

2.generated头文件在最末尾

控制台日志输出

帮助我们记录数据信息,方便追溯,文件在Saved里的Log的最近的文件里,backup可以删

通过使用宏UE_LOG进行控制台日志输出(日志会写入本地缓存)。构建日志需要传入三个参数

1.日志分类(可以自定义)

        1.决定了内容输入到控制台时的分类项

2.日志类型冗余度,分为

        1.Fatal(会终止进程)致命错误

        2.Error(会终止进程)错误问题

        3.Warning(黄色)、Display(白色)、Log(白色)(较常用的日志分类项)

        4.Verbose(将日志详细信息记录到日志文档,但不向控制台输出)(比较快)

        5.VeryVerbose(将日志详细信息记录到日志文档,但不向控制台输出)

3.日志内容

自定义日志分类

分两步:声明和定义

1.声明自己日志分类

DECLARE_LOG_CATEGORY_EXTERN(CategoryName,DefaultVerbosity,CompileTimeVerbosity);

CategoryName自定义日志分类名称 Log开头

DefaultVerbosity日志默认级别,一般使用Log

CompileTimeVerbosity日志编译级别,高于此级别的不会被编译,一般用All

此操作需要在头文件中完成,并且只需要完成一次即可

此宏用来生成日志分类结构体对象,只需要在头文件中进行一次操作即可

例子1:DECLARE_LOG_CATEGORY_EXTERN(ZLog,Log,All);

2.定义日志分类

DEFINE_LOG_CATEGORY(CategoryName);

此操作必须在CPP文件中进行,只需要进行一次定义即可

例子1:DEFINE_LOG_CATEGORY(ZLog);

以上操作必须均具备方可

简化日志输出

借助宏构建红可以编写更加简单的日志输入方式

格式化日志输出

类似C语言中的printf输出,在虚幻中UE_LOG支持可变参数进行构建复杂语句格式,通过占位符,进行输入导入,用来编写更加清晰的日志语句

占位符

%d 整数输出

%f 浮点数输出

%s 输出UE类型字符串(非对象型字符串FString)

例子:UE_LOG(UE4Log,Log,TEXT("小明今年%d岁,身高%f厘米,在%s上学"),20,165.5f,TEXT("奥里给学校"))

编写带有可变参数的自定义日志

_VA_ARGS_可变参数宏,在宏中用来接收可变参数,将可变参数进行传递

可以借助此宏编写更加简单的日志输出宏

Log_Display(mes,...) UE_LOG(FLLog,Display,TEXT(msg),##_VA_ARGS_);

UE基本数据类型

为了方便跨平台,UE对于C++基本数据类型进行深度重定义,方便平台扩展特性,增加UE的移植便捷性

禁止在UE中使用C++的基本数据类型,这样会影响引擎的跨平台特性

bool代表布尔值(永远不要假设布尔值的大小),BOOL将不会进行编译

TCHAR代表字符型(永远不要假设TCHAR的大小)

uint8代表无符号字节(占1个字节)

int8代表有符号的字节(占1个字节)

uint16代表无符号“短整型”(占2个字节)

int16代表有符号“短整型”(占2个字节)

uint32代表无符号整型(占4个字节)

int32代表有符号整型(占4个字节)

uint64代表无符号“四字”(占8个字节)

int64代表有符号“四字”(占8个字节)

float代表单精度浮点型(占4个字节)

double代表双精度浮点型(占8个字节)

PTRINT一个符号整数和一个指针一样大小(用来标记指针的大小)(永远不要假设PTRINT的大小)

字符编码

编码是信息从一种形式或格式转换为另一种形式的过程,也称为计算机编程语言的代码简称编码。用预先规定的方法将文字、数字或其他对象编成数码,或将信息、数据转换成规定的电脉冲信号。编码在电子计算机、电视、遥控和通讯等方面广泛使用。解码,是编码的逆过程

文本在进行储存时会选择文本的格式。文本常用表示格式分为二进制(无格式),文本(ASCII),UTF-8,UTF-16

虚幻引擎4中的所有字符串都作为FStrings或TCHAR数组以UTF-16格式存储在内存内。大多数代码假设2个字节等于一个代码点,因此只支持基本多文种平面(BMP),这样虚幻内部编码可以更准确地描述为UCS-2。字符串以适合于当前平台的字节次序存储。

当向从磁盘序列化到程序包,或在联网期间序列化时,TCHAR字符小于0xff的字符串均存储为一串8位字节,否则存储为双字节UTF-16字符串。序列化代码可以根据需要处理任何字节次序转换

UE4中的字符类型

UE4中提供多种字符类型进行数据处理,在不同的情景下,我们需要选择不同的类型进行操作

区别:大小不同,编码方式不同,所有的文本在进行存储的时候,编译器编译阶段会根据编码类型进行转码

字符类型:

typedef FPlatformTypes::ANSICHAR        ANSICHAR;

typedef FPlatformTypes::WIDECHAR        WIDECHAR

typedef FPlatformTypes::TCHAR        TCHAR;

typedef FPlatformTypes::CHAR8        UTF8CHAR;

typedef FPlatformTypes::CHAR16        UCS2CHAR;

typedef FPlatformTypes::CHAR16        UTF16CHAR;

typedef FPlatformTypes::CHAR32        UTF32CHAR;

转码宏:

有些时候,我们需要主动的进行转码操作,这是很有必要的,虚幻中提供了一些转码操作宏,来帮助我们进行转码操作

#define TCHAR_TO_ANSI(str) (ANSICHAR*)StringCast(static_cast(str)).Get()

#define ANSI_TO_TCHAR(str) (TCHAR*)StringCast(static_cast(str)).Get()

#define TCHAR_TO_UTF8(str) (ANSICHAR*)FTCHARToUTF8((const TCHAR*)str).Get()

#define UTF8_TO_TCHAR(str) (TCHAR*)FUTF8ToTCHAR((const ANSICHAR*)str).Get()

对象字符串

1.FName,资源命名字符串,FName通过一个轻型系统使用字符串。在此系统中,特定字符串即使会被重复使用,在数据表中也只存储一次。FNames不区分大小写(大小写不是他比较的依据)。它们为不可变,无法被操作。应用:资产名称

FNames的存储系统和静态特性决定了通过键进行FNames的查找和访问速度较快。FName子系统的另一个功能是使用散列表为FName转换提供快速字符串

2.FText表示一个显式字符串,用户的显示文本都需要由FText进行处理。支持格式化文本,不提供修改函数,无法进行内容修改。UI上的文本都是FText,UI只用做一套,可以做国际化。应用:UI拿来显示文本(特性:支持被宏序列化,可以国际化操作)

3.FString,可以被操作的字符串。开销大雨其他类字符串类型。应用:最灵活,FString可以转FNames或FText,FString可以扩容、调整、变化、转化的文本存储器

FString

构建方式:

FString str=FString(TEXT("ok"));

FString str1(TEXT("ok"));

FString str2;

UELog里用FString转TCHAR

UE_LOG(LogTemp,Log,TEXT("%s"),*str);

其他数据类型转换到FString

FVector Loc(10,20,30);

Loc.ToString();

FRotator Rot(4,5,3);

Rot.ToString();

FString::SanitizeFloat(3.32f);

FString::FormatAsNumber(112323);//每3位就会,一下       112,323

FString::FromInt(5);

bool b=true;

b?TEXT("true"):TEXT("false");

FString转到整型、浮点型

FString a(TEXT("50"));

FCString::Atoi(*a);

FCString::Atof(*a);//转换到浮点型

大部分F开头的对象都有ToString的方法,可以直接输出ToString

FString比较

if(str1==str2)

{};//区分大小写

if(str1.Equals(str2,ESearchCase::IgnoreCase))

{};//忽略大小写

检查已有的字符串是否包含给定的内容

FString str1(TEXT("ABCDEFG"));

FString str2(TEXT("FG"));

if(str1.Contains(str2)){};        //查找内容,是否忽略大小写,查询方向

检查已有字符串在已有的字符串中出现的位置

str1.Find(str2)        //查找内容,是否忽略大小写,查询方向,起始位置,返回值,如果包含给定的字符串,则返回字符串出现的位置,如果不包含,返回-1

裁切

FString str(TEXT("A*B*C*D*E"));

FString Left;

FString Right;

str.Split(TEXT("*"),&Left,&Right);

Left+Right;

Left+=Right;

检查字符串是否为空

str.IsEmpty();

路径拼接符

//str=A!        Left=A        结果是A!/A

str/Left;

拼接

FString Msg=FString::Printf(TEXT("我有%02d 你有%50d"),1,123);        //我有01 你有123

FName

FName不区分大小写

构建方式

FName n1=FName(TEXT("AB"));

FName n2(TEXT("AB"));

if(n1==n2){};

*n1.ToString()

FText

用户显示文本→构建UI的信息展示

FText名称空间相同没问题,但键值不能相同

构建方式

第一种:(希望内容显示在面板上则用宏构建)

#define LOCTEXT_NAMESPACE "TEXT_UE4"        //声明text名称空间,放在文件最顶端,空间名称的主要目的是为了缩小搜索范围

FText tex=LOCTEXT("KEY","B")        //第一个参数是键值,第二个是内容,键值目的是为了帮助找到翻译的内容

#undef LOCTEXT_NAMESPACE        //将声明的空间名称宏进行释放,放在文件最末端

第二种:(希望内容显示在面板上则用宏构建)

FText tex=NSLOCTEXT("TEXT_UE4","KEY","ABC")        //提供三个参数        空间名称,键值,内容

第三种:(只是在用内容做转移或操作)

FText tex=FText::GetEmpty();

tex=tex1;

数字型数据转换成FText

FText::AsNumber(60);

FText::As好多

FText比较

FText f1=NSLOCTEXT(“UECPP”,"Key","AB");

FText f2=NSLOCTEXT("UECPP","Key","ab")

f1.EqualTo(f2);        //包含检查大小写,false

f1.EqualToCaseIgnored(f2);        //忽略大小写,true

格式化Text(拼接的目的是为了产出一个FText)

第一种方案:占位符拼接

FText ft2=NSLOCTEXT("TEXT_UE4","KEY2","b");

FText ft3=NSLOCTEXT("TEXT_UE4","KEY3","c");

FText ft1=FText::Format(NSLOCTEXT("UECPP","KEY","a+{0}+{1}"),ft2,ft3);        //a+b+c

UE_LOG(LogTemp,Log,TEXT(“%s”),*ft1.ToString());

第二种方案:参数拼接

例子1:

FFormatArgumentValue arg(f1);

FText ft1=FText::Format(NSLOCTEXT("UECPP","KEY","a+{0}"),arg); 

UE_LOG(LogTemp,Log,TEXT("%s"),*ft1.ToString());

例子2:

FFormatArgumentValue arg;

arg.Add(TEXT("name"),tex);

arg.Add(TEXT("hp"),f1);

FText ft1=FText::Format(NSLOCTEXT("UECPP","KEY","a+{name}+{hp}"),arg); 

UE_LOG(LogTemp,Log,TEXT("%s"),*ft1.ToString());

三者间的转换

FString

从FString转换到FName

FString s1(TEXT("OK"));

FName n1=FName(*s1);

FString到FText(不会参与国际化操作的翻译)

FText t1=FText::FromString(s1);

FName

FName到FString

FName n1(TEXT("name"));

FString s1=n1.ToString();

FName到FText

FText t1=FText::FromName(n1);

FText

FText到FString

FText t1=NSLOCTEXT("U","K","NAME");

FString s1=t1.ToString();

FText到FName是不存在转换的,先转换成FString,再转到FName

FString s1=t1.ToString();

FName n1=FName(*s1);

注册执行指令(只能在gamemode.h或playercontroller.h里写)

UFUNCTION(Exec)
    void SayHello(int32 Num);

收集文本国际化

UE4编辑器里        独立进程启动下

窗口——本地化控制板——从文本文件收集——添加搜索目录(source)——添加语言——选择当前VS里的文本的语言——收集文本——选择需要翻译成的语言里的编辑此语言的翻译——在平移里输入翻译的文字——保存——计算字数——编译文本

根据设定改变语言版本        独立进程启动下

项目偏好设置里的播放里的额外启动参数改为-calture=en        (英文)

=后面的在内容中的Localization——Game的文件夹里有缩写

改变资产的语言版本        独立进程启动下

增加一个文本渲染器——设置细节里的文本——本地化控制板——同上的操作

游戏中动态改变语言版本

GameMode.h文件中

UFUNCTION(Exec)
        void ChangeLan(FString Lan);        //写一个切换语言的执行指令

GameMode.cpp文件中

void ACceshiGameModeBase::ChangeLan(FString Lan)
{
    FInternationalization::Get().SetCurrentCulture(Lan);        //设置当前游戏的语言环境
}

容器

容器是方便我们存储数据的载体,在虚幻中,为我们提供了三种容器。分别是TArray,TMap,TSet。首先虚幻提供的容器都是同质容器,只能用来存储相同类型的数据。三种容器具备不同的特性,我们可以根据使用场景选择操作的容器

虚幻中的容器使用泛型特性进行构建,可以装填大部分数据类型,并且具有丰富的操作API

TArray

TArray UE中的数组

数组中的位置为0,1,2,3。数组中元素的个数为1,2,3,4

最常用的数据容器,特点速度快,内存消耗小,安全性高

TArray被称为同质容器:其所有元素均完全为相同类型,不能进行不同元素类型的混合

TArray被设计成值类型,无法被继承。不要使用new和delete进行创建销毁。元素也是数值类型,为容器拥有。TArray被销毁时元素也被销毁。从一个TArray创建新的TArray变量,将把元素复制到新的变量中,不存在共享状态(加进去的内容元素和原来的地址不同,值相同)

初始化

注意:容器在构建时,不要构建为堆对象,直接构建为栈对象。由于容器是模板类,在构建时必须指出存储数据类型

TArray Array;

Array.Init(TEXT("d"),10);        //向容器添加10个元素,元素内容是"d"

遍历

Num函数可以获取TArray当前元素个数。TArray重载了运算符[],通过位置下标可以访问到对应位置元素

例1:

for(int32 i=0;i

{

UE_LOG(LogTemp,Log,TEXT("%s"),*Array[i]);

}

例2:语法糖遍历

for(auto& s1:Array)

{

UE_LOG(LogTemp,Log,TEXT("%s"),*s1);

}

修改

Array[0]=TEXT("ss");

添加元素

Add,Emplace,AddUnique函数均可以向数组中添加元素(到末尾),元素被添加时,内存从分配器中被分配。Add和Emplace函数可达到同样的效果,但存在细微不同

Add把一个元素类型实例复制左值引用(或移动右值引用)到数组中

Emplace添加元素到容器中,Add函数调用的时Emplace函数

AddUnique向容器中加入唯一元素

Append函数可以复制普通的数组到容器中(普通数组,数组中元素的个数)

TArray Array;

Array.Add(TEXT("OK"));

Array.Add(TEXT("OK"));

Array.Emplace(TEXT("OK"));

Array.AddUnique(TEXT("ok"));        //string比较忽略大小写,如已有元素则失败返回-1,成功返回元素位置

FString Data[3]{TEXT("ed"),TEXT("ab"),TEXT("ss")};

Array.Append(Data,ARRAY_COUNT(Data));        //ARRAY_COUNT宏只能用来看普通数组的长度

//数组中OK OK OK ed ab ss

Insert允许在给定索引添加一个单一元素或元素数组的一个副本(如果插入位置超过容器大小将会报错)

Array.Insert(TEXT("A"),5);

SetNum主动设置容器的大小,如果长度大于原容器大小,空白位置将用模板类型默认对象填充。如果小于原容器大小,则超过设置大小的内容将被删除(容器的大小,是否允许缩小容器当前元素数量)

Array.SetNum(15,true);

迭代器

容器中的元素是一个一个排好队的,迭代器相当于指向每个元素的箭头,目的是获取元素,具备++特性

迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器的内容

TArray、TMap、TSet有两种迭代器,一种是可以通过迭代器修改元素内容,一种是只能读取元素不能修改元素

禁止在迭代器中修改容器的元素个数,禁止添加和移除元素

普通迭代器构建:

for(auto It=Array.CreateIterator();It;++It)        //注意++位置要放前面

{

*It;        //迭代器指向的元素内容,*It是取出元素,Array.CreatIterator()创建一个迭代器

UE_LOG(LogTemp,Log,TEXT("==%s"),**It);

}

常量迭代器构建:

for(auto It=Array.CreateConstIterator();It;++It)        //注意++位置要放前面

{

//迭代器指向的元素内容,*It是取出元素,Array.CreatConstIterator()创建一个常量迭代器

UE_LOG(LogTemp,Log,TEXT("==%s"),**It);

}

Array转成普通数组

返回类型指针,指针地址是数组中第一个元素的地址(数组进行传递的时候传递的是指针——地址)

FString* Data=Array.GetData();

常规查询函数

Array.IsValidIndex(5);        //返回布尔值,查询指定位置是否存在有效元素

Array.Last();        //返回最后的元素

Array.Last(5);        //返回倒数第5个元素

Array.Top();        //返回顶端元素,没有Top(1)这种

Array.Contains(TEXT("ok"));        //查找是否包含给定的元素并返回布尔值

Array.Find(TEXT("OK"));        //查找是否包含给定的元素并返回元素所在位置,不包含返回-1

int32 Index =0;

Array.Find(TEXT("OK"),Index);        //查询给定元素所在的位置将位置索引设置到Index,返回布尔值

常规移除函数

TArray有Reset函数,清除内容,但保留空间

Array.Remove(TEXT("OK"));        //在容器中移除给定的元素,返回移除的个数

Array.RemoveSingle(TEXT("OK"));        //在容器中移除一个给定的元素,返回移除的个数,0移除失败1移除成功

Array.RemoveAt(5);        //移除给定位置的元素

Array.Empty();        //清空容器

TMap

UE中最常用的容器,此容器是关联型容器,存储对象均有一个关联值,通过键值可以高效的进行对象访问

TMap为同质容器,存储类型必须相同,TMap也是值类型,支持常规复制、赋值和析构函数操作,以及其元素较强的所有权。映射被销毁时,其元素也将被摧毁。键类型必须为值类型,不能使用指针

Map的结构例如钥匙和锁,一把钥匙找一把锁,他们之间是一一对应的关系

构建

构建时需要选择好容器的键值类型和元素类型,添加时必须提供键值。如果添加的数据键值已经存在则会覆盖之前的添加

TMap map;        //构建容器,键值类型为FString,数据类型为int32

map.Add(TEXT("N1"),99);        //向容器中添加元素,允许添加相同键值内容,但会覆盖

map.Add(TEXT("N1"));        //允许只填入键值不添加数据元素(将使用默认数据填充)

mao[TEXT("N1")]=90;        //可以使用此方法修改数据内容,但是不能添加键值

合并TMap(值类型必须相同)

Append合并操作,传入的Map如果有和被合并的Map键值相同数据,将采取覆盖操作

map.Append(map2);        //将map2合并到map

遍历操作

注意迭代器

例1:

for(auto& Item:map)

{

//Item.Key;

//Item.Value;

}

例2:

for(auto It=map.CreateIterator();It;++It)

{

It.Key();        //获得键值

It.Value()=200;        //获得值,返回的是引用,可以在外部修改,注意语法

It->Value;        //也可以获得值

}

例3:

for(auto It=map.CreateConstIterator();It;++It)

{

It.Key;        //获得键值

It.Value();        //获得值,禁止修改

}

查询函数

map.Num();        //获取容器中元素的数量

map[TEXT("n1")];        //通过索引运算符使用键值获得引用,可以用来修改元素内容

map.Contains(TEXT("n1"));        //检查是否包含给定的键值 返回布尔值

map.Find(TEXT("n1"));        //返回键值绑定的元素指针,如果没有内容返回空,非返回引用

移除函数

TMap有Reset函数,清除内容,但保留空间

map.Rempve(TEXT("n1"));        //使用给定键值移除元素

map.Empty();

TSet

TSet也是键值容器和TMap类似,但速度快,无需提供单独的键进行关联元素,不允许有重复的键

TSet也是值类型,支持常规复制、赋值和析构函数操作,以及其元素较强的所有权。集合被销毁时,其元素也将被销毁。键类型也必须是值类型

与TArray的区别

1.TSet是KV容器

2.TSet不保证数据填充顺序

3.TSet数组存储时无法重复存储,TArray可以

构建

TSet set;        //构建TSet

set.Add(TEXT("OK"));        //添加内容

合并

TSet set2;

set.Append(set2);        //允许合并操作

遍历

例1:

for(auto&Item:set)

{

Item=TEXT("n1");        //操作元素内容

}

例2:

for(auto It=set.CreatIterator();It;++It)

{

*It=TEXT("n1");        //操作元素内容

}

例3:

for(auto It=set.CreatConstIterator();It;++It)

{

*It;        //获取内容,但禁止修改

}

查询函数

set.Num();        //获取容器中元素的数量

set.Contains(TEXT("n1"));        //检查元素中是否包含给定的键值

set.Find(TEXT("n1"));        //如果查找某一元素是否存在,建议可直接使用Find函数进行单一查找,返回找到指向元素的指针,未找到返回空

set.Array();        //将TSet容器转为TArray容器

移除函数

set.Reset();        //移除元素,但不释放空间

set.Remove(TEXT("n1"));        //移除给定的键值内容

set.Empty();        //移除所有元素,释放空间

常规性的数据存储,一般情况下我们用TArray(有谁在场景里,小队里有谁)

Array有序容器,位置关系不会变化,通过下标访问到元素

TMap关键字索引(武器镶嵌),通过键值访问到元素

TSet敏感词检查(玩家名字重复)


Array容器(数组)可以自动变化大小的容器
Map容器(映射)具有键值的同质容器(键值可以是枚举)对于元素操作需要依靠键值,键值是map的操作标签。键值类型可以是蓝图常规对象类型
元素类型必须相同,键值唯一。也就是加入相同键值元素将被覆盖
应用:背包栏(具备格子概念)技能栏(技能施放快捷键)装备槽等
Set容器(集)键值类同质容器。键值和元素相同,本身对键值操作隐藏。操作标签即为元素本身,即如果想要操作set中的内容,需要先知道元素。这与其他两种容器思考方式完全不同 只检查元素存不存在
应用:聊天辱骂过滤,创建名字敏感词检索,特殊道具持有检查等

你可能感兴趣的:(c++,ue4)