UE4筆記1
Unreal note
參照Unreal官方文檔 C++編程教程
網(wǎng)址:https://docs.unrealengine.com/latest/CHN/Programming/Tutorials/index.html
/*---------------------------------------------------基礎(chǔ)類介紹---------------------------------------------------------------*/
虛幻基礎(chǔ)類:
Unreal對象 :UObject 虛幻中大部分類都繼承于此類
?
/*---------------------------------------------------編程風(fēng)格---------------------------------------------------------------*/
派生自Actor的類前綴為A,如AController
派生自"對象(UObject)"的類前綴為 U,如 UComponent。
"枚舉"的前綴為E,如 EFortificationType。
"接口(interface)" 類的前綴通常為 I,如 IAbilitySystemInterface。
"模板(template)" 類的前綴為 T,如 TArray。
派生自 SWidget(Slate UI)的類前綴為 S,如 SButton。
其余類的前綴均為 字母 F ,如 FVector。
因為不同平臺基礎(chǔ)類型的尺寸不同,如 short、int 和 long,UE4 提供了以下類型,可用作替代品:
int8/uint8 :8 位帶符號/不帶符號 整數(shù)
int16/uint16 :16 位帶符號/不帶符號 整數(shù)
int32/uint32 :32 位帶符號/不帶符號 整數(shù)
int64/uint64 :64 位帶符號/不帶符號整數(shù)
標(biāo)準(zhǔn) 浮點 (32-bit) 和 雙倍(64-bit)類型也支持浮點數(shù)。
詳情可查看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。此宏擁有默認(rèn)語言的命名空間、鍵和一個數(shù)值。例如:
Text MyText = NSLOCTEXT("Game UI", "Health Warning Message", "Low Health!")
FName 將經(jīng)常反復(fù)出現(xiàn)的字符串保存為辨識符,以便在對比時節(jié)約內(nèi)存和 CPU 時間。
FName文檔:
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/UObject/FName/index.html
TCHAR : 寬字符版
UE4 字符串在后臺使用 TCHAR 陣列將數(shù)據(jù)保存在 UTF-16 編碼中。使用返回 TCHAR 的重載解引用運算符可以訪問原始數(shù)據(jù)。
類似于std::string::c_str();
FChar:窄字符版
/*---------------------------------------------------容器類(全部是模板類)---------------------------------------------------------------*/
與std里面的容器相似,但是此處多出了許多功能
TArray:
用法:
TArray<AActor*> ActorArray = GetActorArrayFromSomewhere();
// 告知當(dāng)前 ActorArray 中保存的元素(AActors)數(shù)量。
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);
/*--------------------------------------分割線------------------------------------------*/
// 移除特定索引處的元素
// 索引上的元素將被下調(diào)一格,以填充空出的位置
ActorArray.RemoveAt(Index);
/*--------------------------------------分割線------------------------------------------*/
// RemoveAt 的高效版,但無法保持元素的排序
ActorArray.RemoveAtSwap(Index);
/*--------------------------------------分割線------------------------------------------*/
// 移除陣列中的所有元素
ActorArray.Empty();
注解(重要):
1、需注意:TArray 是當(dāng)前唯一能被標(biāo)記為 UPROPERTY 的容器類。這意味著無法復(fù)制、保存其他容器類,或?qū)ζ湓剡M行垃圾回收。
2、如果想要保存在里面的元素自動清理垃圾,比如容器里面保存的是指針,可以在上面加上一個宏 UPROPERTY,
這將假定 TArray 被標(biāo)記為 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 可更快實現(xiàn)這些操作,
但無法像 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();
// 創(chuàng)建包含 TSet 元素的 TArray
TArray<AActor*> ActorArrayFromSet = ActorSet.Array();
迭代器:
void RemoveDeadEnemies(TSet<AEnemy*>& EnemySet)
{
? ? // 從集的開頭開始迭代到集的末端
? ? for (auto EnemyIterator = EnemySet.CreateIterator(); EnemyIterator; ++EnemyIterator)
? ? {
? ? ? ? // * 運算符獲得當(dāng)前的元素
? ? ? ? AEnemy* Enemy = *EnemyIterator;
? ? ? ? if (Enemy.Health == 0)
? ? ? ? {
? ? ? ? ? ? // RemoveCurrent 由 TSets 和 TMaps 支持
? ? ? ? ? ? EnemyIterator.RemoveCurrent();
? ? ? ? }
? ? }
}
// 將迭代器移回一個元素
--EnemyIterator;
// 以一定偏移前移或后移迭代器,此處的偏移為一個整數(shù)
EnemyIterator += Offset;
EnemyIterator -= Offset;
// 獲得當(dāng)前元素的索引
int32 Index = EnemyIterator.GetIndex();
// 將迭代器重設(shè)為第一個元素
EnemyIterator.Reset();
For-each 循環(huán)
迭代器很實用,但如果只希望在每個元素之間循環(huán)一次,則可能會有些累贅。每個容器類還支持 for each 風(fēng)格的語法在元素上進行循環(huán)。
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;
? ? // ...
}
著色器開發(fā)文檔:
https://docs.unrealengine.com/latest/CHN/Programming/Rendering/ShaderDevelopment/index.html
界面設(shè)計使用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
/*-----------------------------------------------調(diào)試時使用斷言------------------------------------------------------------*/
斷言:
check(expression);
check(Mesh != nullptr);
check(bWasInitialized && "Did you forget to call Init()?");
checkf(expression, ...);
checkf() 宏允許您將一個表達式斷言為 true,并在調(diào)試時打印有幫助的額外信息。在編譯行為方面,它和 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 被禁用后表達式仍然在執(zhí)行。
可使用它確認(rèn)變量的指定符合假設(shè)。
verifyf(expression, ...);
verify() 宏固定執(zhí)行表達式,verifyf() 也是如此。和 checkf(); 一樣,它通過額外的調(diào)試信息停止執(zhí)行
verifyf(Module_libeay32, TEXT("Failed to load DLL %s"), *DLLToLoad);
/*-----------------------------------------------動畫播放------------------------------------------------------------*/
//此處摘錄于:http://blog.csdn.net/JustinReynard/article/details/44153911
UE4的動畫通知和UE3的通知其實在本質(zhì)上是一樣的,但是在UE4 更多的時候使用BP進行了封裝,
不像UE3的時候直接在Pawn的代碼中直接調(diào)用。
UE4允許在每個動畫的時間幀上添加我們需要執(zhí)行動畫通知。
?
UE4的動畫通知主要分為兩類:
?
Notify和Notify State.
?
下面簡單的比較比較一下兩種通知不一樣的地方。
Notify,屬于單幀的概念。什么是單幀呢?就是角色動畫上的一幀,沒有時間段的概念。
比如說在這個動畫執(zhí)行到1/4的地方播放一個聲音,我們就可以Notify。
Notify State 它有三個通知的函數(shù):
?
Notify Start: 這個通知序列剛進入時調(diào)用
?
NotifyEnd: ?這個通知序列結(jié)束時調(diào)用
NotifyTick :在這個通知執(zhí)行過程中每Tick都會調(diào)用的函數(shù)。這個可以理解為不斷回調(diào)的函數(shù)或者更新函數(shù)。
BlendSpace和BlendSpaceID的卻別:
?
BlendSpaceID 只有一個軸的動畫混合空間,這而BlendSpace是一個包含兩個軸的動畫混合空間