UE4笔记1
Unreal note
参照Unreal官方文档 C++编程教程
网址:https://docs.unrealengine.com/latest/CHN/Programming/Tutorials/index.html
/*---------------------------------------------------基础类介绍---------------------------------------------------------------*/
虚幻基础类:
Unreal对象 :UObject 虚幻中大部分类都继承于此类
/*---------------------------------------------------编程风格---------------------------------------------------------------*/
派生自Actor的类前缀为A,如AController
派生自"对象(UObject)"的类前缀为 U,如 UComponent。
"枚举"的前缀为E,如 EFortificationType。
"接口(interface)" 类的前缀通常为 I,如 IAbilitySystemInterface。
"模板(template)" 类的前缀为 T,如 TArray。
派生自 SWidget(Slate UI)的类前缀为 S,如 SButton。
其余类的前缀均为 字母 F ,如 FVector。
因为不同平台基础类型的尺寸不同,如 short、int 和 long,UE4 提供了以下类型,可用作替代品:
int8/uint8 :8 位带符号/不带符号 整数
int16/uint16 :16 位带符号/不带符号 整数
int32/uint32 :32 位带符号/不带符号 整数
int64/uint64 :64 位带符号/不带符号整数
标准 浮点 (32-bit) 和 双倍(64-bit)类型也支持浮点数。
详情可查看URL : https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Math/TNumericLimits/index.html
打印log记录 : 使用UE_LOG()宏
/*----------------------------------------------------字符串处理-----------------------------------------------------------------*/
字符串处理使用FString,类似于std::string
使用 TEXT() 宏可新建一个 FString:
FString MyStr = TEXT("Hello, Unreal 4!").
除了FString,还有一个FText可使用,其功能与FString相似,但是是用于本地化文本的。
使用 NSLOCTEXT 宏可新建一个 FText。此宏拥有默认语言的命名空间、键和一个数值。例如:
Text MyText = NSLOCTEXT("Game UI", "Health Warning Message", "Low Health!")
FName 将经常反复出现的字符串保存为辨识符,以便在对比时节约内存和 CPU 时间。
FName文档:
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/UObject/FName/index.html
TCHAR : 宽字符版
UE4 字符串在后台使用 TCHAR 阵列将数据保存在 UTF-16 编码中。使用返回 TCHAR 的重载解引用运算符可以访问原始数据。
类似于std::string::c_str();
FChar:窄字符版
/*---------------------------------------------------容器类(全部是模板类)---------------------------------------------------------------*/
与std里面的容器相似,但是此处多出了许多功能
TArray:
用法:
TArray<AActor*> ActorArray = GetActorArrayFromSomewhere();
// 告知当前 ActorArray 中保存的元素(AActors)数量。
int32 ArraySize = ActorArray.Num();
/*--------------------------------------分割线------------------------------------------*/
// TArrays 从零开始(第一个元素在索引 0 处)
int32 Index = 0;
/*--------------------------------------分割线------------------------------------------*/
// 尝试获取在给定索引处的元素
TArray* FirstActor = ActorArray[Index];
/*--------------------------------------分割线------------------------------------------*/
// 在阵列末端添加一个新元素
AActor* NewActor = GetNewActor();
ActorArray.Add(NewActor);
/*--------------------------------------分割线------------------------------------------*/
// 只有元素不在阵列中时,才在阵列末端添加元素
ActorArray.AddUnique(NewActor); // 不会改变阵列,因为 NewActor 已被添加
/*--------------------------------------分割线------------------------------------------*/
// 移除阵列中所有 NewActor 实例
ActorArray.Remove(NewActor);
/*--------------------------------------分割线------------------------------------------*/
// 移除特定索引处的元素
// 索引上的元素将被下调一格,以填充空出的位置
ActorArray.RemoveAt(Index);
/*--------------------------------------分割线------------------------------------------*/
// RemoveAt 的高效版,但无法保持元素的排序
ActorArray.RemoveAtSwap(Index);
/*--------------------------------------分割线------------------------------------------*/
// 移除阵列中的所有元素
ActorArray.Empty();
注解(重要):
1、需注意:TArray 是当前唯一能被标记为 UPROPERTY 的容器类。这意味着无法复制、保存其他容器类,或对其元素进行垃圾回收。
2、如果想要保存在里面的元素自动清理垃圾,比如容器里面保存的是指针,可以在上面加上一个宏 UPROPERTY,
这将假定 TArray 被标记为 UPROPERTY,并存储 UObject 派生的指针。具体示例如下所示:
UPROPERTY()
TArray<AActor*> actorArray;
TMap:
它是键值对的集合,与std::map相似。
具体API文档URL:
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Containers/TMapBase/index.html
TSet:
TSet 保存唯一值的合集,与 std::set 相似。TArray 通过 AddUnique 和 Contains 方法可用作集。然而 TSet 可更快实现这些操作,
但无法像 TArray 那样将它们用作 UPROPERTY。TSet 不会像 TArray 那样将元素编入索引。
示例:
TSet<AActor*> ActorSet = GetActorSetFromSomewhere();
int32 Size = ActorSet.Num();
// 如集尚未包含元素,则将其添加到集
AActor* NewActor = GetNewActor();
ActorSet.Add(NewActor);
// 检查元素是否已包含在集中
if (ActorSet.Contains(NewActor))
{
// ...
}
// 从集移除元素
ActorSet.Remove(NewActor);
// 从集移除所有元素
ActorSet.Empty();
// 创建包含 TSet 元素的 TArray
TArray<AActor*> ActorArrayFromSet = ActorSet.Array();
迭代器:
void RemoveDeadEnemies(TSet<AEnemy*>& EnemySet)
{
// 从集的开头开始迭代到集的末端
for (auto EnemyIterator = EnemySet.CreateIterator(); EnemyIterator; ++EnemyIterator)
{
// * 运算符获得当前的元素
AEnemy* Enemy = *EnemyIterator;
if (Enemy.Health == 0)
{
// RemoveCurrent 由 TSets 和 TMaps 支持
EnemyIterator.RemoveCurrent();
}
}
}
// 将迭代器移回一个元素
--EnemyIterator;
// 以一定偏移前移或后移迭代器,此处的偏移为一个整数
EnemyIterator += Offset;
EnemyIterator -= Offset;
// 获得当前元素的索引
int32 Index = EnemyIterator.GetIndex();
// 将迭代器重设为第一个元素
EnemyIterator.Reset();
For-each 循环
迭代器很实用,但如果只希望在每个元素之间循环一次,则可能会有些累赘。每个容器类还支持 for each 风格的语法在元素上进行循环。
TArray 和 TSet 返回每个元素,而 TMap 返回一个键值对。
// TArray
TArray<AActor*> ActorArray = GetArrayFromSomewhere();
for (AActor* OneActor :ActorArray)
{
// ...
}
// TSet - 和 TArray 相同
TSet<AActor*> ActorSet = GetSetFromSomewhere();
for (AActor* UniqueActor :ActorSet)
{
// ...
}
// TMap - 迭代器返回一个键值对
TMap<FName, AActor*> NameToActorMap = GetMapFromSomewhere();
for (auto& KVP :NameToActorMap)
{
FName Name = KVP.Key;
AActor* Actor = KVP.Value;
// ...
}
着色器开发文档:
https://docs.unrealengine.com/latest/CHN/Programming/Rendering/ShaderDevelopment/index.html
界面设计使用UMG(Unreal Motion Graphics)
参考文档:
https://docs.unrealengine.com/latest/CHN/Engine/UMG/index.html
除此之外,还有Slate用户界面框架
参考文档:
https://docs.unrealengine.com/latest/CHN/Programming/Slate/Architecture/index.html
/*-----------------------------------------------调试时使用断言------------------------------------------------------------*/
断言:
check(expression);
check(Mesh != nullptr);
check(bWasInitialized && "Did you forget to call Init()?");
checkf(expression, ...);
checkf() 宏允许您将一个表达式断言为 true,并在调试时打印有帮助的额外信息。在编译行为方面,它和 check() 行为相同。
checkf(WasDestroyed, TEXT( "Failed to destroy Actor %s (%s)"), *Actor->GetClass()->GetName(), *Actor->GetActorLabel());
checkf( TCString<ANSICHAR>::Strlen( Key ) >= KEYLENGTH( AES_KEYBITS ), TEXT( "AES_KEY needs to be at least %d characters" ), KEYLENGTH( AES_KEYBITS ) );
verify(expression);
启用 DO_CHECK 后,此宏的行为与 check() 完全相同。然而 DO_CHECK 被禁用后表达式仍然在执行。
可使用它确认变量的指定符合假设。
verifyf(expression, ...);
verify() 宏固定执行表达式,verifyf() 也是如此。和 checkf(); 一样,它通过额外的调试信息停止执行
verifyf(Module_libeay32, TEXT("Failed to load DLL %s"), *DLLToLoad);
/*-----------------------------------------------动画播放------------------------------------------------------------*/
//此处摘录于:http://blog.csdn.net/JustinReynard/article/details/44153911
UE4的动画通知和UE3的通知其实在本质上是一样的,但是在UE4 更多的时候使用BP进行了封装,
不像UE3的时候直接在Pawn的代码中直接调用。
UE4允许在每个动画的时间帧上添加我们需要执行动画通知。
UE4的动画通知主要分为两类:
Notify和Notify State.
下面简单的比较比较一下两种通知不一样的地方。
Notify,属于单帧的概念。什么是单帧呢?就是角色动画上的一帧,没有时间段的概念。
比如说在这个动画执行到1/4的地方播放一个声音,我们就可以Notify。
Notify State 它有三个通知的函数:
Notify Start: 这个通知序列刚进入时调用
NotifyEnd: 这个通知序列结束时调用
NotifyTick :在这个通知执行过程中每Tick都会调用的函数。这个可以理解为不断回调的函数或者更新函数。
BlendSpace和BlendSpaceID的却别:
BlendSpaceID 只有一个轴的动画混合空间,这而BlendSpace是一个包含两个轴的动画混合空间