UE4 除錯技巧分享 (一)
俗話說的好
給他魚吃不如教他釣魚
今天要分享幾個我平常在用的技巧
那我會建議你要先幫自己做好心裡建設。
你在用的是開發原始碼的引擎,
遇到問題時應該儘量往引擎內部追,
不要馬上就找繞過(workaround)的方法或求救。
那樣作你很快就會想放棄,因為無法進步,遇到問題無法自救。
雖說是技巧心得,理論上要跟硬體無關,但是這個真的要講一下。
給他魚吃不如教他釣魚
今天要分享幾個我平常在用的技巧
心理建設
如果你是有程式背景,但是正在用blueprint(BP)開發。那我會建議你要先幫自己做好心裡建設。
你在用的是開發原始碼的引擎,
遇到問題時應該儘量往引擎內部追,
不要馬上就找繞過(workaround)的方法或求救。
那樣作你很快就會想放棄,因為無法進步,遇到問題無法自救。
硬體設備
雖說是技巧心得,理論上要跟硬體無關,但是這個真的要講一下。
想追code一定要準備好2個螢幕以上,至少一個螢幕是UE4 Editor,另一個是Visual Studio。
單螢幕的話光是切換視窗就亂掉了。
技巧分享
這裡面的技巧應該比較零散,所以可以跳著看。
不寫Code就直接顯示變數值在螢幕上
如果問我只能寫一條的話,我一定選這一條。
這個是我第一常用的技巧了,大部分我們想到要得知某一個值,就是跑去Actor或是Component的Tick裡面下PrintString,這樣資訊就會顯示在畫面上。如下圖。
可是有的時候bug是機率出現的,好不容易bug發生了,想看某個值是否異常,但是當下卻沒有埋PrintString,難道只能放棄了嗎?
其實沒有,引擎提供了強大的console command "DisplayAll",讓我們可以直接拿到變數值並顯示於螢幕。如圖。
DisplayAll的使用方法是:
DisplayAll [ClassName] [PropertyName]
大小寫無分別,所以可以不管大小寫。
ClassName的部份,可分為C++與BP class兩種。
如果你要追查的class是C++ class,那麼直接輸入C++的名稱就好,
但是要去除第一個字。例如
AActor應該輸入Actor
想知道movement移動速度的最大值可下
displayall charactermovementcomponent maxwalkspeed
如果你要追查的class是BP,那麼你要輸入[BP的名稱_C],
舉例來說
有一個BP名稱為BP_CodeTraceActor 裡面有一個變數是value
那麼要輸入的是
DisplayAll BP_CodeTraceActor_c value
PropertyName的部份,只要這個變數有被定義為UPROPERTY,就可以拿到值。BP所有的變數應該都有UPROPERTY,所以沒問題。
資料顯示出來後,我通常會搭配桌面錄影軟體搭配測試,一有問題就可以把影片檔抓出來單格播放,抓出異常的時間點,然後再回去想想問題可能出在哪裡。
故障排除
如果輸入之後畫面沒任何東西,建議先輸入一些一定會出現的指令確認環境
例如
diaplayall playercontroller spawnLocation
如果這樣看的到,那可能是你的class name打錯,系統找不到。
如果這樣還看不到,檢查一下自己的環境是不是Debug / Development,還是有什麼東西關掉。
如果輸入之後畫面有字,但是沒有值(有綠色的字沒有紅色的字),那可能是PropertyName打錯,建議檢查一下。
我宣布放棄DisplayAll列出來的資訊
只要執行Console Command
DisplayClear
就可以了
DisplayAll使用條件限制與缺點
DisplayAll只會在Debug以及Development顯示,所以如果在Test跟Shipping是看不到的。
Dedicated Server因為沒有螢幕,所以也看不到。
但是如果Dedicated Server + SingleProcess模式的話,畫面上會同時列出Server跟Client的值,很好用。
相反的Editor/ Packaged Development Game都看的到,建議可以多加利用。
使用DisplayAll最大的缺點就是只能根據class列出,沒有辦法針對某個class的某個實體(Instance)輸出。所以class沒有選擇好的話就會列出過多資訊,無法好好地做判斷。
另一個就是如果值在一個frame裡面會變動多次,想要從DisplayAll抓出問題也沒辦法,畢竟這個功能一個frame只會更新一次。
避免程式碼被Optimize造成中斷點失效
一般我們都是使用Development Editor在開發,但是因為編譯器會做Code Optimization的關係,有的時候中斷點會無效或異常。
經驗上有以下幾種現象會因為Code Optimize產生:
1. 斷點失效,雖然Visual Studio顯示該行有下斷點,但是有執行卻不停。
2. 斷點下不到準確的行數,例如下在53行卻顯示斷點在55行。
3. 執行順序怪異,跳下後又跳上,或是直接跳過整段,或是走到一半就離開函式。
4. 看不到變數值
下圖就是想看變數MutableThis內容看不到的範例。
這個時候,如果真的非得知道這個值,
常見的解法就是加Log強制印出,或是編譯DebugGame Editor,或是Debug Editor等等。
但是我個人最常用的方式是直接使用Macro Define把想看的函式夾起來,不用改DebugGame Editor或是Debug Editor。
範例如下
PRAGMA_DISABLE_OPTIMIZATION
//Your codes here
PRAGMA_ENABLE_OPTIMIZATION
下圖就是使用PRAGMA後可以成功拿到值的範例
這個方法有幾個好處:
1. 編譯速度快,因為相當於改cpp code而已,不像切換成DebugGame Editor,如果先前沒有build過要等很久。
2. 省硬碟空間,切換成DebugGame Editor,就會多出Debug版本的dll,吃掉硬碟空間。
3. 效能沒有受到犧牲,如果用DebugEditor的話,整個編輯器會變得很慢,這個方法不會。
這個方法的缺點:
目前我使用到最大的缺點就是,這段PRAGMA要記得除錯完就刪掉,不然這段程式碼都不會做Optimization,執行效能是會受到影響的。
然後有很少數的情況夾了還是有部分看不到,這時候我就會直接夾整個cpp檔,通常就沒問題了。
其實還有一個缺點,就是這兩行我永遠背不起來,每次都要去筆記本裡面複製貼上。
對我來說,這個方法沒什麼負擔跟缺點,很推薦大家學起來,推推!
下回預告
預計下個禮拜會分享第二集,是有關如何在UE4中使用中斷點的部份
留言
張貼留言