發表文章

了解UE4同步傳輸的開銷(Bunch Overhead)

圖片
這篇文章其實算是Network Profiler (一) (二) 的後續 主要是利用Profiler分析的過程中發現replicate property已經減少很多 可是total send Bytes沒有如預期的下降到目標 經過追查研究後 發現問題在Bunch Overhead後 才有了這一篇文章的內容 Bunch Overhead 如果降replicate傳輸到一定程度之後,會發現其實Bunch Overhead蠻大的。 從Profiler裡面可以看到Bunch Overhead分為 Bunch Headers ContentBlock Headers Content Footers Handles Export GUIDS MustBeMapped GUIDS 這幾個項目 如圖1.所示 圖1. BunchOverhead的細項可在Network Profiler的Summary內找到 其中我只稍微追查Bunch Headers, Handles, Export GUIDS這幾項而已,其他項目因為傳輸不多所以我沒有深入追。 Bunch Headers Bunch Header到底傳了那些,可以在 Engine/Source/Runtime/Engine/Private/NetConnection.cpp 的UNetConnection::SendRawBunch() 裡面追查到 大致上就是這個Bunch 是open/close,是不是reliable, channel index是多少等等的資訊 Bunch headers的資料量從我們開發端是很難省掉的,不過引擎端因為Fornite持續在開發的關係,應該會不斷地改進。 例如以前有Bunch.bIsDormant現在直接被合併進 enum EChannelCloseReason Bunch.CloseReason。 Export GUIDS 這個項目主要發生在Server 要同步一個新的Actor給client的時候,需要利用GUID跟client建立對應關係 如果是動態生成的物件,會直接使用物件的路徑+名稱,以字串的方式作為GUID傳送 舉例來說server生成一個新的需要同步的Actor 路徑在Content/...

Blueprints In-depth - Part 2

Unreal 官方公佈了兩個有關blueprint的深度介紹的影片 Blueprints In-depth - Part 1 | Unreal Fest Europe 2019 | Unreal Engine https://www.youtube.com/watch?v=j6mskTgL7kU Part 1 https://yekdniwunrealengine.blogspot.com/2019/06/blueprints-in-depth-part-1.html Blueprints In-depth - Part 2 | Unreal Fest Europe 2019 | Unreal Engine https://www.youtube.com/watch?v=0YMS2wnykbc 投影片 https://epicgames.ent.box.com/s/hdv4bye3dezabp4duq8pttsha8kjjlde 這篇文章是摘錄Part 2的一些重點出來~ Compilation BP的編譯時間是不會影響程式實際執行時間的。 但是對於開發者來說,如果BP編譯太久會嚴重影響到開發過程 也有可能在使用編輯器時發生記憶體吃太兇的問題 BP編譯時間通常跟以下幾點有相關 1. BP graph內的節點數目 2. 與其他BP有reference,或是有cast其他BP。 3. BP有Circular reference。 BP大小是有上限的,不過無論如何一般的使用情境都應該遠低於上限才對。 如果你不小心撞到BP的上限,代表你對BP理解是有問題的。 BP Macro如同C++的Macro概念一樣,會在呼叫Macro的地方直接展開Macro的內容 也就是說呼叫Macro就跟複製貼上BP節點差不多,使用過多複雜的Macro是會增加BP編譯時間的 BP Function的行為與Macro有很大的不同,不會複製貼上,所以如果把Macro轉為Function的話, 可以有效的降低BP編譯時間。 將複雜的BP分為多個actor,或是多個component,或是child actor,或是以C++改寫,都能有效降低編譯時間。 不過這部份就牽扯到系統設計,要選擇哪一種方法完全就是要看情況而決定,沒有完美的答案...

UE4 Network Profiler介紹 (二)

圖片
調整觀看折線圖的橫軸縱軸 只看某個時間區段的數據(橫軸) 這個功能比較直覺,就是滑鼠左鍵按著選擇到想看的範圍放開滑鼠左鍵就是了 如圖1,選擇範圍之後,就會只顯示這個時間範圍內的數據,如圖2。 圖1. 選擇時間區段 圖2. Actors內只會顯示這個時間範圍的數據 只看折線圖縱軸的某個區間 這個功能沒有文件也沒有UI提示,我也是偶然測到發現的,不過有的時候的確會用到這個功能。 通常是某單一影格傳輸的尖峰值太高,但是當下只想看平均傳輸的時候會需要 支援選擇縱軸區段的作法就是在折線圖上面按一下滑鼠右鍵... 就會從"選擇橫軸區段"切換到"選擇縱軸區段" 然後一樣滑鼠左鍵按著,選擇想看的範圍再放開滑鼠左鍵,如圖3 圖3. 選擇縱軸區段 不過這個模式只會影響到折線圖內,畢竟縱軸是傳輸的資料量或是數目,這些值是不會受到顯示範圍而改變的。 例如圖4與圖2Actors內的數據因為時間範圍沒改變,所以一樣。 圖4. 選擇縱軸不影響Actors內顯示的數值 折線圖無法顯示的項目 我現在的版本是UE4.22 我有發現如果property傳輸低於1個byte的話,折線圖是不會顯示的, 即使你把縱軸放大到可以看到0~1的區間也是不會顯示。 在分析的時候要稍微注意一下這個小問題。 圖5. 示範在BP內定期改變enum與integer的範例。 圖5是一個blueprint範例,每0.5秒改變一次enum的內容(這個enum傳輸會低於一個byte) 每1秒改變一次inispeed的內容,因為是integer,所以改變一次是4Bytes的傳輸。 我們用Profiler看的結果會發現,smallEnum因為傳一次低於1 Byte (3/9),就直接不顯示在折線圖上面了,如圖6。 圖6. 從Actors頁面可以看到smallEnum是有傳的,但是在折線圖看不到。 Network Profiler Source Code Network Profiler分引擎輸出資料端跟Network Profiler顯示端兩大部分 引擎輸出.nprof的程式碼放在 Engine/Source/Runtime/Engine/Public/...

Blueprints In-depth - Part 1

Unreal 官方公佈了兩個有關blueprint的深度介紹的影片 Blueprints In-depth - Part 1 | Unreal Fest Europe 2019 | Unreal Engine https://www.youtube.com/watch?v=j6mskTgL7kU Blueprints In-depth - Part 2 | Unreal Fest Europe 2019 | Unreal Engine https://www.youtube.com/watch?v=0YMS2wnykbc 投影片 https://epicgames.ent.box.com/s/hdv4bye3dezabp4duq8pttsha8kjjlde 這篇文章算是摘錄Part 1的一些重點出來~ Author 作者說他自己是artist designer,不是程式出身,所以內容可能有一些是身為程式本來就知道的事情 https://youtu.be/j6mskTgL7kU?t=88 Introduction Blueprint(BP)是Unreal Engine很重要核心的功能 學習BP是很容易,就像畫流程圖一樣。 BP的UI介面其實跟程式的.h以及.cpp是很類似的,所以也容易理解。 使用BP很簡單,但是重點在於如何"正確"使用 Feature https://youtu.be/j6mskTgL7kU?t=409 Feature就是介紹BP跟各種功能/資料類型/類別的關係與說明 The Big picture 基本上寫程式想法差不多 如何讓BP盡可能的簡潔 如果有人要接手我的工作,怎麼樣才好理解我寫的BP 在作BP的時候有沒有一併考慮記憶體以及效能相關的問題 有沒有考慮到這個BP未來如果會擴張的情況 https://youtu.be/j6mskTgL7kU?t=752 以一個門作為範例 首先一開始一定都是很簡單一個靠近就會開門的BP 之後隨著需求增加了好幾個門的BP,每個功能都有些微的不同。 然後把有相同的部分往上抽了底層,base BP class BP_EnvironmentObject。 隨著複雜度提升,還繼續往C++層抽,把複雜的功能放進C++。...

UE4 Network Profiler介紹 (一)

圖片
Network profiler是UE4的一個外部工具 用來分析UE4原生的網路傳輸量,包含RPC, Replicated property等等。 如何使用 建立資料檔 首先在你要分析的對象(一般是Server) 執行console command netprofile enable開始紀錄 然後一段時間後再執行netprofile disable結束錄製 結束後在[project path]/Saved/Profiling 資料夾中會看到.nprof檔 就是network profiler錄下來的資料 執行Network profiler network Profiler的執行檔直到4.22都沒有辦法在Editor內叫起來 必須自己到[Engine path]/Binaries/DotNET/NetworkProfiler.exe 執行 打開後點open 選擇剛剛錄好的檔案就可開始分析 Network profiler介面介紹 折線圖與Summary 預設打開會列出好幾個數據的折線圖 可以先了解一下平均傳輸的級距大概在哪裡,以及是否有特別不平均的現象要注意(有很多突峰)。 左下方Summary頁面列一些影格與秒數資訊,以及總傳輸與每秒傳輸的各細項數據,一開始建議看總傳輸量與每秒傳輸量就好。 Actors頁面 Actors頁面預設會列出整段資料所有replicate actor的資訊。單點某一段時間的話就是改為列出這段時間replicate actor的資訊。 MS欄位代表Server花了多少時間在計算處理這個actor的replication KB/s以及Bytes就是這個actor property的總/每秒傳輸量 Count是傳輸次數(接近Property count的總和) UpdateHz是ServerCPU計算處理這個actor要replicate的頻率 RepHz則是實際上有replicate東西出去的頻率 Waste=(UpdateHz-RepHz)/UpdateHz 官方的影片有提到Waste高代表Server的CPU有浪費的情況,等於server一直在計算這個actor,但是這個actor都沒有變動需要replicate。這個時候會建議降低這個actor的update...

揭密SpawnActor的BP節點

圖片
在BP的SpawnActor節點有個厲害的功能 就是你給不同的class type的話,這個節點會根據class type產生不同的樣貌,主要有兩個 1. return的actor type會是你傳入的class type,而不是基礎type actor,還要自己cast 2. 如果傳入的class有expose on spawn的變數,也會再這裡列舉出來讓你可以傳入 在說明細節之前,我們先看一下C++處理 expose on spawn的變數值是如何設定的。 AMyActor* pActor = SpawnActorDeferred; // Fill your variable here... FinishSpawningActor(pActor); 所以可以知道其實spawn一個擁有expose on spawn的actor是要作上述三個步驟的。 Spawn -> SetProperties -> FinishSpawn 如果因為某些因素沒呼叫到最後的FinishSpawn,程式的運作就會有問題。 而BP的SpawnActorFromClass只用了一個節點就作到上述三件事情,為了理解其中的奧妙,我花了一些時間追查,在這邊分享一下。 程式碼在 Engine\Source\Editor\BlueprintGraph\Classes\K2Node_SpawnActorFromClass.h 在function ExpandNode裡面,就是處理一個節點其實會分成三大節點的主函式。 static const FName BeginSpawningBlueprintFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, BeginDeferredActorSpawnFromClass); static const FName FinishSpawningFuncName = GET_FUNCTION_NAME_CHECKED(UGameplayStatics, FinishSpawningActor); 上面兩行可以看到會從UGameplayStatics之中取出BeginDeferredActorSpawnFromClass以及FinishSpawnin...

GameplayAbilities System介紹 (二)

圖片
本篇要說明個人最近研究有關Gameplay abilities system的各個系統介紹以及負責的項目。 AbilitySystemComponent AbilitySystemComponent(ASC),處理一個角色整個GAS的相關事務。每一個可以發動ability或是受到ability效果的單位都必須掛上ASC。ASC身為中心負責了ability的發動與接收,角色屬性值的變更與網路傳輸。由於ASC通常是程式在C++端就掛上去,所以這個系統原則上跟企劃比較沒有關係。 AttributeSets 一個角色的屬性值,通常技能最後的結果就是影響角色的值。例如血量,能量,氣條,攻擊力。 AtrributeSets內儲存的值都是浮點數,要使用其他類型可能就不適合(或是根本沒辦法?)。通常這部份的值都是企劃決定。UE4在這部份也提供了curve table讓值可以從表格決定,並且可以定義根據不同等級該有的值。 例如玩家角色的防禦值可能會被定義為 PlayerDefense 1,2,5,10 代表等級1的時候防禦是1,到了等級4的時候防禦值是10。 GameplayAbility 一個Ability可以視為一個技能,技能可以決定從client先發動,或是從server發動,以及技能要不要同步。 Tag組合 技能上面可以定義許多不同的tag組合,用來處理各種可能的情況: 1. 技能在角色擁有哪些tag才可以發動 2. 角色有哪些tag的話不能發動此技能 3. 這個技能啟動後會取消有哪些tag的其他技能 4. 這個技能發動期間哪些tag的其他技能不能被發動成功 以下是範例: 1. 要有已知用火的tag,火技能才能發動 2. 角色被上了凍結的tag,技能不能發動 3. 施放大絕會取消所有普通技能 4. 施放技能中所有戰鬥技能都不能被發動。 Costs and Cooldowns 技能也支援costs以及cooldowns的概念,costs處理發動一個技能要有的消耗,例如發動技能要耗10點魔力,如果角色魔力不足就會發動失敗。cooldowns處理發動一個技能後的冷卻時間,要冷卻時間結束之後才能夠再次發動。 Triggers 技能的發動除了可以手動呼叫之外,也可以利用技能的Trigger機制,設定角色...