發表文章

目前顯示的是 2018的文章

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機制,設定角色

GameplayAbilities System介紹 (一)

圖片
Gameplay Abilities System(GAS)是UE4內建但是預設沒開啟的一個plugin,並且有在Epic Games自己出的Paragon以及Fornite兩款遊戲使用。因為兩款遊戲都是網路對戰類型的遊戲,所以GAS的設計是有考慮低網路傳輸以及網路預測的。GAS也開出了許多blueprint(bp)編輯的介面,讓設計可以在bp層完成所有的技能開發。因為系統設計非常活的關係,使用GAS幾乎可以達到各種設計的需求,並且許多常用的功能都已經內建在GAS裡面。 使用已完成的GAS系統其實不難,技能定義好,技能的效果定義好,很快就可以完成一個技能。在大量製作上會非常快速。 但是理解GAS以及要擴充GAS功能的難度就很高了,由於GAS可塑性非常好,要完成一件事可以用很多種方法達成,但是只有少部分方法是效率最好,網路傳輸最少的,要找到這一條方法就需要大量的時間研究才辦的到。 如果想更深入了解Gameplay Abilities System,在官方4.20發表的時候也一併公布了ActionRPG的專案範例,可以去Unreal Launcher下載來研究。 為什麼要用GAS系統,以下有幾點原因可供參考: 1. Unreal原生支援並有兩款已上市遊戲使用 2. 記憶體、效率、網路傳輸都是官方有調整過 3. 支援Client預測與後續相關要處理的事情 4. 可塑性高,大部分的設計都可以用內建的功能做到 很不錯的英文介紹投影片:[ 連結 ] 技術需求 在目前的UE4版本,GAS是沒辦法運作在純bp專案的,所以在繼續往下看之前,要先具備C++的基本知識,電腦環境也要安裝Visual Studio才能正確啟用GAS。或是直接從ActionRPG開始,用基本已建立好的角色型態做實驗。 GameplayAbilitySystem設定 在Unreal的plugin上啟用 Edit->Plugins->Built-In->Gameplay 勾選Enabled。重開Unreal。 打開Visual studio專案,打開[專案名稱].Build.cs, 新增以下程式碼: PublicDependencyModuleNames.AddRange(new string[] {

UE4驗證網路版本的程式碼

在開發多人遊戲的時候總是會遇到client沒辦法連上server的情況。例如有人沒有更新,或是開錯目錄的執行檔等等。這篇文章稍微提一下UE4如何驗證不同版本的機制以及程式碼在哪邊處理這些事情,以及如何從log判斷是不是版本有問題。 EngineBaseTypes.h 有個ENetworkFailure::NetChecksumMismatch的enum 定義。 而PackageMapClient.cpp 有一些程式碼會檢查讀取物件的NetworkChecksum,如果判斷不對就會送出NetChecksumMismatch事件。 client會因為上面原因,造成spawn actor失敗,接著就會送NMT_ActorChannelFailure給server,此時server就會關掉對這個玩家的連線。送NMT_ActorChannelFailure的程式碼在 DataChannel.cpp 從client會看到的log: LogNetPackageMap: Warning: GetObjectFromNetGUID: Network checksum mismatch. FullNetGUIDPath: [57]/Game/xxxxx.[55]xxxxx.[53]PersistentLevel.[131]xxxxx, 2365598466, 229775609 LogNet: Warning: UActorChannel::ProcessBunch: SerializeNewActor failed to find/spawn actor. Actor: None, Channel: 30 (LogNet可能預設不會輸出訊息,可能要透過修改參數或是用console command 輸入Log LogNet All來看) server會看到的log: Server connection received: ActorChannelFailure 所以server 或是client看到上述的訊息的話,就可以知道可能兩邊版本有問題,總之還是記得client跟server都要用相同的build比較不容易出這個狀況。

Unreal Avoidance系統(下)

圖片
在上篇 我們提到使用Unreal內建的Detour迴避有一些限制 這些限制主要是純BP專案無法透過C++修改行為造成的。 所以本篇是以C++專案為基礎,說明如果要使用Detour的功能,可能要做哪些修改才能達到。 需要注意的是這篇文章為了重現當初改寫時遇到的過程,會有大量的文字描述,沒興趣的話應該會啃不下去。 但是裡面有一些遇到問題的解法,對解題過程有興趣的人可以看看,或是有更好的建議也歡迎~ 本篇會介紹下面幾個項目,可以先看看有沒有你要的內容再繼續~ 1. 為什麼要複寫CrowdManager 2. 繼承並複寫CrowdManager 3. 在執行時期更改AvoidanceGroup 為什麼要複寫CrowdManager 這是個很冗長的流程,當初我發現RVO可以動態透過API修改Avoidance Group, 但是用CrowdPathFollowingComponent(以下簡稱CPFC)卻不行時,我也是嚇了一跳。 於是我跑去追CPFC的程式碼,發現要修改Detour迴避行為的函式全部都被定義為private(圖1), 然後標頭檔的最後標示了CPFC的friend class是 CrowdManager。 顯示即使繼承CPFC也沒辦法改寫迴避的行為,設定全部都必須要透過CrowdManager處理。 圖1. 設定Detour的函式都是private。 然後跑去CrowdManager挖程式碼,卻發現CPFC那些設定相關的函式都沒被用到... 代表要繼承CrowdManager才能達到我希望能修改迴避參數的目標。 繼承並複寫CrowdManager 首先當然就是先繼承CrowdManager: 在Unreal Editor->New C++ Class->Show all classes 輸入CrowdManager,並選擇CrowdManager,輸入名字與路徑就可以完成繼承。 在Edit->Project Settings->Engine->NavigationSystem內有CrowdManagerClass 將此欄位指向剛剛創好的MyCrowdManager。可參考圖2 圖2. 在Engine設定CrowdManagerClass為自己複寫的cl

Unreal Avoidance系統(上)

圖片
AI角色在移動時,為了能夠閃開場景的物件,大致上可分為靜態物件與動態物件兩種。 靜態場景的物件能夠透過Collision+CanAffectNavigation設定或是在場景內種Navi Modifier Volume將Navigation Mesh挖空,讓AI沒辦法走在這些物件上;而動態物件的閃避(閃避其他角色)則利用Avoidance閃避系統來處理。 Unreal Engine裡面有兩種avoidance系統可以選擇性地使用,其中一個是RVO,另一種則是Detour crowd simulation。然而根據 https://wiki.unrealengine.com/Unreal_Engine_AI_Tutorial_-_2_-_Avoidance 所提到的,Unreal提供的RVO不保證在推擠或閃避的過程中角色依然能維持在Navigation mesh上,這代表有可能你的角色會發生卡在場景內走不出來的現象...(我也不知道為什麼這樣子的東西能放在上面給人使用)。 因為這樣的原因,在蒐集一些資料後我直接選擇Detour使用,RVO就直接被我跳過不用了。所以本篇會著重在Detour crowd simulation系統上作說明。除此之外,一般網路搜尋到的文章也會建議RVO與Detour不要同時打開,以免產生衝突的行為。 RVO與Detour的差異 開始詳細介紹Detour之前,先比較一下RVO跟Detour兩個系統的差別。 Table 1 . 比較RVO與Detour系統的差異。 RVO Detour 使用難易度 簡單 普通 可調整參數 少 超多 可改寫的行為 不確定 很多但麻煩(只能C++) 缺點 不保證在NavMesh上 複雜的計算與設定 使用的難易度:RVO 比 Detour容易。 RVO開啟非常簡單,更改設定也很簡單。也允許blueprint(BP)端執行期間更改迴避的設定;Detour就相對麻煩了,如果只是要開啟一些很簡單的效果,使用難度跟RVO差不多,但是只支援BP事先定義好的迴避參數,想要在實際執行過程中改變迴避設定的話有很多事情要處理,而且都是要在C++端實作才行。 可調整參數:RVO能調整的似乎就是迴避半徑,迴避比

在Pawn發送RPC給server失敗的解決方法

圖片
先前有遇到在某個class發送RPC (Remote procedure calls)都正常,但是在某一個特定的class發送就發生server收不到的狀況。 經過一番追查後發現原因在於Pawn的GetNetConnection()跟Actor的GetNetConnection()行為是有所不同的。 一般的Actor如果沒有特別override的話,就是以Actor的Owner遞迴去尋找,直到找到PlayerController。 但是Pawn如果有controller posses的話,會以Controller的NetConnection()作為依據。如果這時候Controller沒有設定Owner(或是其NetConnection沒有連通)的話,這時候RPC就會失敗。 實驗環境 以下紀錄整個乾淨的實驗環境 (UE4.18) 1. 首先創造一個Class,TestPawn。TestPawn的ClassDefault的ControllerClass指向AIController。 2. TestPawn實作一個Client通知server的RPC,然後再實作一個server廣播給其他人的RPC。如下圖所示: 3. 到PlayerController或是PlayerPawn的Class實作Client請求Server在Sever端生成TestPawn的程式,如下圖所示: 4. 記得執行的時候要開啟dedicated server模式,或是叫兩個client起來,然後非server的玩家按F的時候,TestPawn會被spawn,會印字串Client notify to server,但是不會看到server receive from client後續的字串,顯示RPC是失敗的。 5. 此時如果追TestPawn的GetNetConnection()會發現回傳的是Null,原因是因為Controller不是Null但是Controller的GetNetConnection()是Null。 Engine\Source\Runtime\Engine\Private\Pawn.cpp line524 6. 而Controller的NetConnection有問題的原因源自於如果APawn如果有給ControllerClass的話,