發表文章

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的話,...

Projectile Movement Component的initial speed 初始速度設定

圖片
最近在使用projectile movement component (以下簡稱PMC)的時候遇到一個問題 如果一個Actor掛了一個PMC來做移動的運算,但是這個移動的運算可能是由事件觸發,而且移動的初速度可能也是一個變數,根據事件當時計算的結果會有不一樣的初速度。 然而經過測試發現有以下幾個問題: 1. 只有在Actor的construction script 或是PMC的default值設定initial speed才會生效,其他事後的設定都是無效的 。 在default值設定初始速度, 有效 。 在Construction Script設定初始速度, 有效 。 在BeginPlay或任何其他地方設定初始速度, 無效 ,會以construction script或是default值設定的值為準。 2. 對PMC disable component active之後再enable component active會影響到整個移動的運作。 以上方的圖舉例初速度是1500,第一次active會用1500的速度噴出去,可是如果disable active之後再enable,速度就會變成0。 有關第一點,追查原始碼之後才發現 初始速度只有在InitializeComponent的時候使用到 其餘程式碼都沒用到這個值,也間接證實了比BeginPlay早呼叫的Construction Script設值是有用的。因為呼叫時間的先後順序應該是Construction Script -> InitializeComponent -> BeginPlay。 但是有了這段code之後也代表initial speed其實可以自己處理,就如同程式碼說明的一樣。只是把目前的velocity乘上 speed而已。所以下圖的寫法等同於設定初速度~(為了偷懶safeNormal我就不在圖中作了) 第二點的話,推測是停掉之後velocity被設為0,所以再開啟的時候速度也被重設了。如果想要延續停掉前的速度,可能要自己記下來,然後在重新開啟的時候重新把之前的velocity設回去。

關閉IncrediBuild的方法

用incredibuild來build UnrealBuildTool.exe(UBT),UBT會再呼叫Incredibuild 形成遞迴呼叫incredibuild,導致在編譯的時候會收到錯誤: A Xoreax distributed job cannot be started from within another distributed job. 目前已知UBT跟Shader compile worker這兩個project好像都不能使用Incredibuild來作編譯。 如果想要關掉incredibuild 除了下面說的改xml的方法之外,另一個就是uninstall incredibuild了。不要想去incredibuild按stop service或是把incredibuild執行檔從工作管理員裡面停止,這兩招對unreal都沒用。 unreal都是直接去incredibuild的安裝資料夾叫起執行檔來執行的~ 為了解決這個問題,要在xml裡關掉incredibuild 來Build UBT 在檔案路徑 %appdata%\Unreal Engine\UnrealBuildTool\ 下的 BuildConfiguration.xml 或是 C:\Users\[使用者帳號]\AppData\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml 加上這行 <bAllowXGE>false</bAllowXGE> 範例如下: <?xml version="1.0" encoding="utf-8" ?> <Configuration xmlns="https://www.unrealengine.com/BuildConfiguration"> <BuildConfiguration> <bAllowXGE>false</bAllowXGE> </BuildConfiguration> </Configuration> 然後去Visu...