發表文章

UE4 開發常用外部工具介紹

圖片
 在開發遊戲的過程中,還是會需要用到不少外部的工具來輔助開發。 本篇就要來介紹用了好幾年覺得好用的工具。 因為個人是程式,所以其他職能不一定適合,就當參考參考。 有些是免費,有些是付費。 另外我的環境是windows,所以其他desktop平台也不一定適用。 本篇我發誓百分之百不是業配,我沒有拿任何一毛錢,真的就是經驗分享。 版本控制系統(必備) ★★★★★ 例如git、svn、perforce等等。 基本上版本控制系統百分之百是必須的,就選擇一套用吧。 文字編輯器 ★★★★☆ Visual Studio Code & Notepad++ 這兩個我都有裝。也是建議至少擇一。 比起visual studio開啟比較笨重,這兩套開啟快速是大優點。 看各種檔案或是作文字替換、Unicode 轉換也都很方便。 Visual Assist ★★★☆☆ 俗稱的番茄,小番茄。 是屬於Visual Studio的外部工具,基本上可以用最快的時間找到你要的變數,函式,檔案。 對我個人來說幾乎是必裝,因為個人不太能等待Visual Studio幫我找檔案的時間。 會是只有三顆星是因為代理商的價格實在是太不推薦了,而且個人版的授權寫得不清不楚的,一邊寫可以公司用,一邊寫不能公司用。 桌面錄影軟體 ★★★☆☆ 目前是用OBS ,不過已經很久沒更新了。 不確定現在有沒有更好的。 桌面錄影軟體我都拿來除錯,先找到問題重現的方法後,錄製遊戲過程,然後逐格播放影片,再來分析問題在哪。 硬碟空間管理與分析 WinDirStat 檔案內容分析 ★★★★☆ 在使用UE4的過程中,硬碟永遠不夠用,尤其是常常出不同平台的版本,或是出各種版本測試,都需要用掉大量的硬碟空間。 這時候我都會定期使用WinDirStat對專案目錄作分析,找出特別大的資料夾,如果不是必需的就會砍掉。 另外一個使用時機則是分析打包後資料的時候,有的時候最後打包的檔案過大。 我會利用這個軟體看一下Cooked目錄,分析一下是不是有哪些Asset檔不符合應該有的大小,然後再回去做調整。 mklink 目錄連結 ★★★★★ windows內建的外部工具,但是因為太好用了所以不能不特別介紹 大部份開發UE4使用SSD應該已經是標配,不過並不是所有的專案都能整個專案放SSD。 但是如果全部放硬碟,想必開啟或使用的速度上是受到嚴重限制的。

批次執行Console commands

 有的時候我們會想要執行一連串的console command,才能得到結果,可是又不想要為這一串console command專門寫一個console command把他們集合起來。怎麼辦? 作法(只需要做一次) 把功能加在CheatManager 在你繼承的CheatManager.h加上函式 UFUNCTION(exec) void ExecComboCommand(const FString& ComboCommandName); 在你繼承的CheatManager.cpp實作函式 void UMyCheatManager::ExecComboCommand(const FString& ComboCommandName) { FConfigSection* CommandsToRun = GConfig->GetSectionPrivate(*ComboCommandName, false, true, GGameIni); if (!CommandsToRun) { return; } if (!IsValid(GetOuterAPlayerController())) { return; } for (FConfigSectionMap::TIterator It(*CommandsToRun); It; ++It) { GetOuterAPlayerController()->ConsoleCommand(*It.Value().GetValue()); } } 使用組合指令 在ini裡面製作要批次執行的指令 例如在 [Project]\Saved\Config\Windows\Game.ini 新增 [Debug.ComboCommand1] +Cmds=stat fps +Cmds=stat unit (新增的時候請先關閉Editor,以免修改被Editor蓋掉) 如果要上平台也能測試,可能就要新增在 [Project]\Config\DefaultGame.ini 內不過記得最後要拔掉。 然後打開你的Editor或是執行目標平台的遊戲,先輸入 EnableCheats 再輸入 Ex

客製化DisplayAll輸出Struct的內容

  在使用DisplayAll來顯示物件資訊的時候,有些struct結構比較龐大或是複雜(例如帶有指標指向其他物件)的時候,會顯示過多的資訊,讓整個螢幕變得很亂,反而不利於除錯。這時候我們會想要控制struct輸出的結果,去除不想看到的欄位。 為了達到這件事,我們尋找了一下怎麼控制輸出的結果,後來找到這篇的方法,可以透過UE4對struct做的Type Traits來幫助我們做到這件事。 Type Traits如果不知道是什麼的話沒有關係,下面的範例直接抄就好了。 不過打在這邊就單純是讓想多了解一點的人,有關鍵字可以做更進一步的了解背後運作的原理。 修改輸出結果的具體範例以及程式碼可以在Class.cpp以及Class.h裡面看到。 檔案路徑在 Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp Class.cpp裡面有個FTestStruct struct ENGINE_API FTestStruct 這次的需求,需要關注的項目是 WithExportTextItem 以及Struct對應的函式ExportTextItem 你必須先定義TStructOpsTypeTraits<FTestStruct>,並把將WithExportTextItem設為true template<> struct TStructOpsTypeTraits<FTestStruct> : public TStructOpsTypeTraitsBase2<FTestStruct> { enum { WithExportTextItem = true, }; }; 然後在FTestStruct裡面實作ExportTextItem。 bool ExportTextItem(FString& ValueStr, FTestStruct const& DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope) const { ValueStr += TEXT("("); for (TMap<int32, double>::TCons

UE4 Navigation Mesh 心得

圖片
UE4的Navigation Mesh 如果照著網路上的教學做,大概都可以建的出來。 A.I.角色也都能夠在上面正常行走。 不過應用稍微有點變化的時候就會碰上一些問題,在這邊先介紹過去遇過的項目 名詞與縮寫說明 NavMesh: Navigation Mesh NBV: Navigation Bounds Volume,用來定義navigation mesh的範圍。 P-Level: Persistent Level。 主地圖。 Sublevel: 放置於主地圖下的子地圖。 如何調整NavMesh的大小 雖然一般都會調整NBV的scale,不過並不建議這麼做。 Volume類型的個人都建議調整Brush內的大小,不要改Actor的scale。 NavMesh到底存在哪邊? NavMesh實際上存在於有NBV的場景的umap內。 不是場景的BuiltData,也不一定是主地圖。 舉例來說 主地圖    (1個NBV)     sublevel1 (0個NBV) sublevel2 (0個NBV) sublevel3 (2個NBV) 當Build完NavMesh之後,主地圖與sublevel3都需要存檔。 我可以在Build的時候排除sublevel嗎? 可以,在Build之前把sublevel設隱藏的話,就可以排除掉,如下圖所示 sublevel隱藏的時候Build Path,就不會排除方塊(圖1.)。 sublevel顯示的時候Build Path,會排除方塊(圖2.)。 圖1. 隱藏Sublevel build path 圖2. Sublevel1內的方塊被考慮進去並視為不可行走。  有Nav Mesh刪不掉 有的時候會看到場景裡面有不該存在的Nav Mesh,而且不管怎麼重Build都刪不掉。 我找到了重現步驟如下: 1. 開啟一個新的Level File->NewLevel->Default 2. 放置Nav Mesh Bounds Volume (NBV) 於場景內,並與地板有交疊。 3. Build->Build Paths (或是引擎自己會auto build navigation) 4. 確認Nav Mesh有出現 5. 直接刪除步驟2的NBV 6. Build->Build Paths (或是引擎自己會auto b

Editor內Blueprint中斷點沒有觸發

最近在做功能的時候遇到了有趣的問題。 其實以前就偶爾有遇到但是沒有認真找原因,因為發生的機會其實很低。 這次很幸運的找到問題的原因,所以分享一下 問題發生的現象 在解決問題之前,先描述問題的定義 在BP下中斷點 無論如何都不會停下來 但是在中斷點前或後面的節點下PrintString確定會印,功能也都正常 就只是斷點不會停 如果這個BP是從C++呼叫的話 C++的斷點是會停的。 問題的原因 追查發現ScriptCore.cpp 在執行BP的breakpoint 之前 會檢查現在是不是在GameThread 如果有在Game Thread才會觸發中斷點 剛好我這次的功能是從muti-threading的animation事件過來的 CallStack直接看到有Update_AnyThread的字眼 所以下次如果再遇到類似的現象 可能要想一下是不是因為multi threading造成的~ 相關程式碼 ScriptCore.cpp FBlueprintCoreDelegates::ThrowScriptException裡面的 if (IsInGameThread()) {     OnScriptException.Broadcast(ActiveObject, StackFrame, Info); }

根據不同平台調整Static mesh的LOD

圖片
通常開發跨平台遊戲的時候,會想要針對Static Mesh做LOD區隔。 而UE4提供好用的Minimal LOD功能,讓開發者不用特別寫程式碼,就可以根據不同平台調整LOD參數。Minimal LOD的參數是可以每個static mesh設定的,設定的地方可以在Static Mesh的編輯器內找到。如圖所示 例如說Windows的Minimal LOD設為0,Android跟iOS設為1。 這樣的話在實際執行的時候,Android跟iOS平台只會看到1以後的LOD mesh,可以有效的控制場景總面數。 還有另一個參數r.StaticMeshLODDistanceScale可以控制LOD切換的距離。 數字越大代表會越早切換到低階層的LOD。 這個參數也可以針對平台做設定,不過是影響全域的變數,所以要在Device Profile的頁面設定。記得要Save as Default才會存檔。 舉例來說 r.StaticMeshLODDistanceScale=2.0 然後LOD1的screen size設為0.3的話 代表在這個平台0.3*2的距離就會切換成LOD1了。 不過使用LODDistanceScale有個小缺點,就是在編輯的時候預設都是使用r.StaticMeshLODDistanceScale=1.0。要把場景調整到1.0跟2.0外觀看起來不錯的狀態,是需要很多人工檢查的。 上面提到的兩個參數可以控制Minimal LOD,不過這兩個參數都是執行的時候,告訴系統該顯示哪一層LOD。 在打包的過程還是都會把全部的LOD都包進去,影響最後打包的容量。 如果想要避免比Minimal LOD更精細的LOD也被打包進平台內。我們需要在打包的平台把Device Profile參數 r.StaticMesh.StripMinLodDataDuringCooking設為1。 或是使用文字編輯器打開 [Project Path]/Config/DefaultDeviceProfiles.ini 把以下區段 [Windows DeviceProfile] DeviceType=Windows BaseProfileName= 改為 [Windows DeviceProfile] DeviceType=Windows BaseProfileName= +CVars=r.Static

UE4 除錯技巧分享 (二)

圖片
上一篇介紹了兩個除錯小技巧 這一篇會比較著重在中斷點的部份。 技巧分享 這篇的複雜度稍高,而且技巧互相有關連,建議按照順序看。 環境 先稍微介紹一下本篇的環境。 開發平台的部分是Windows + Visual Studio 2017; 引擎是UE4.23。 照理說引擎版本沒什麼差,不過為了保險還是提一下。 從BP中斷點找出完整的Call Stack 在使用編輯器的時候,我們常常會使用BP中斷點來追查執行順序,如同C++的中斷點一樣。 但是如果這個事件是從C++來的話,在BlueprintDebugger是無法得知的,如下圖所示。 其實我們是有辦法知道的,在BP中斷點停住的狀態下,回去Visual Studio,假設UE4 process已經是attach的狀態,按Debug->BreakAll (如圖),這時候就可以看到Call Stack了。 通常CallStack分頁會看到一大串,好像很嚇人,這時候不要慌不要著急,看到Slate那種的都略過一直往下捲。慢慢的看你應該會找到認識的函式,如下圖所示。 以這張圖為例子,就可以知道BP的Tick是從C++的Actor::Tick內呼叫ReceiveTick來的。 有時候你會看到CallStack極短,長的像這樣: 這是因為斷點剛好停在別的Thread,這時候只要去Visual Studio的Debug->Windows->Threads將Thread分頁叫出,然後跳到MainThread就可以了。 從C++中斷點找出BP呼叫的來源 前一個技巧是BP斷點想知道從哪個C++呼叫進來的。這個技巧是要說明如何從C++斷點找出是哪個BP呼叫來的。這個技巧特別重要,因為就算是Packaged Game也可以抓出BP來源。 假設我現在中斷點停在C++的程式碼,有兩種方法可以試 方法1.  到Visual Studio的Watch視窗內輸入 {,,UE4Editor-Core}::PrintScriptCallstack() 或是 ::PrintScriptCallstack() Debug Editor的話則是輸入 {,,UE4Editor-Core-Win64-Debug}::PrintScriptCallstack()  然後去Visual Studio的Output視窗就會看到印出來的BP Call Stac