[程式] 在UE4 Editor繪製除錯用的元件

看板GameDesign (遊戲設計)作者 (yekdniw)時間4年前 (2020/06/25 00:00), 4年前編輯推噓5(500)
留言5則, 5人參與, 4年前最新討論串1/1
網頁版 https://yekdniwue.blogspot.com/2020/06/ue4-editor.html 簡介 在遊戲中,我們都知道可以使用Blueprint的DrawDebug系列的功能, 用來繪製圓球,膠囊體等物件提供除錯。 但是如果想在編輯器的View視窗用DrawDebug是做不到的(註1), 至少UE4引擎內部並不是這樣用。 註1.我有試過在ConstructorScript呼叫DrawDebugSphere,結果是會畫出來, 但是永遠不會消失了。 不過引擎是有提供編輯器除錯用的顯示功能的,我們可以在幾個地方看到: 1. Visual Logger 2. EQS Testing Pawn 3. NavigationTestingActor 使用Visual Logger可以在編輯器看到AI角色的位置資訊被記錄下來, 也可以自己透過API紀錄想要的資訊,如圖所示。 [圖1.] EQS Testing Pawn則是可以隨著編輯過程的狀況不同,顯示/更新Query的結果, 如圖所示。 [圖2.] NavigationTestingActor是比較罕見的功能,可以在編輯器就預覽路徑搜尋的結果。 有個時候專案也會需要這方面的功能,如果沒有心理準備, 就直接看上面三個系統的實作,通常會被複雜的程式碼勸退。 這次我硬著頭皮研究並試著實作了一輪,簡單的做個筆記與分享。 最主要是去除複雜的程式碼,只列出最基本要實作的項目。有需要改進的部分再從上面提 到的系統抽取出來即可。 本篇文章的內容以NavigationTestingActor為出發點作分析,雖然比較少見,但似乎是這 幾個系統裡面相對簡單的部份。 架構組成 1. AActor 2. URenderComponent 3. FSceneProxy 要完成這個功能,首先要有三個class,一個就是顯示項目要依附在的Actor。 然後要為這個Actor新增自定義的RenderComponent,作為顯示用。 在RenderComponent內會創出自定義的SceneProxy, 你要繪製的項目要實作在SceneProxy的函式內。 以下實際用TestActor, TestRenderComponent, TestSceneProxy分別做為案例。 TestActor要實作的項目 在TestActor的member加上 UPROPERTY() class UTestRenderComponent* TestRenderComp; 如果只想讓這個功能在Editor中出現,可以使用macro #if WITH_EDITORONLY_DATA #endif 將所有使用到TestRenderComponent的地方夾起來。 TestActor的Constructor加上 TestRenderComp = CreateDefaultSubobject<UTestRenderComponent>(TEXT("TestRenderComp")); TestRenderComp->PostPhysicsComponentTick.bCanEverTick = false; 根據需求,Override PreEditChange或PostEditChangeProperty或PostEditMove。 在有資料變動的時候呼叫MarkRenderStateDirty。 TestRenderComp->MarkRenderStateDirty(); PostEditChangeProperty內可以實作property內容變動後該做的事; PostEditMove則是Actor在編輯器內被拖拉移動的時會進入的事件; TestRenderComponent要實作的項目 首先TestRenderComponent要繼承UPrimitiveComponent,然後實作下面兩個函式。 virtual FPrimitiveSceneProxy* CreateSceneProxy() override; virtual FBoxSphereBounds CalcBounds(const FTransform &LocalToWorld) const override; CreateSceneProxy就是new出SceneProxy,並且把component自己傳入SceneProxy的 constructor,說這麼多其實直接看程式碼比較快。 FPrimitiveSceneProxy* UTestRenderComponent::CreateSceneProxy() { FTestSceneProxy* newSceneProxy = new FTestSceneProxy(this); return newSceneProxy; } CalcBounds比較簡單,就是決定這個component的bounding box範圍,用來決定這個 component會不會進rendering。 可以從GetOwner拿到TestActor,然後直接回傳Actor的BoundingBox即可。 FBoxSphereBounds UTestRenderComponent::CalcBounds( const FTransform &LocalToWorld) const { FBox BoundingBox(ForceInit); AActor* TestActor = GetOwner(); if (TestActor) { BoundingBox = TestActor->GetComponentsBoundingBox(true); } return FBoxSphereBounds(BoundingBox); } TestSceneProxy要實作的項目 TestSceneProxy反而是最複雜的項目,要實作的函式比較多,實際上要繪製的程式碼也寫 在這。 GetTypeHash() Constructor(const UTestRenderingComponent* inComponent); Destructor GetDynamicMeshElements() GetViewRelevance() GetAllocatedSize() 其中GetTypeHash,Constructor, Destructor, GetViewRelevance, GetAllocatedSize建議直接參考 Engine/Source/Runtime/NavigationSystem/Private/NavMesh/ 內的NavTestRenderingComponent.cpp就好, GetTypeHash, Destructor, GetViewRelevance我是直接照抄。 Constructor目的是要透過TestRenderingComponent拿到TestActor的資料, 存入自定義的資料結構。 在GetDynamicMeshElements會使用這些資料結構做繪製。 GetAllocatedSize要回傳TestSceneProxy額外使用到的記憶體大小, 請參考NavTestRenderingComponent。 GetDynamicMeshElements是主要繪製的程式碼入口,請參考以下的範例程式碼: for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { if (!(VisibilityMap & (1 << ViewIndex))) { continue; } // Write your codes here!! } 在Engine/Source/Runtime/Engine/Public/SceneManagement.h內 提供了許多繪製形狀的函式, 所以從Constructor拿到的資料在這裡傳入繪圖函式就可以了。 繪製的函式基本上又可以分為兩大類,一類是以Get為開頭的函式; 另一類則是Draw開頭的函式。 Get系列要傳入Material,所以需要產生FMaterialRenderProxy後傳入。 Draw系列需要FPrimitiveDrawInterface (引擎縮寫PDI), 可以呼叫Collector.GetPDI(ViewIndex)取得。 以上兩個系列的程式碼在FNavTestSceneProxy::GetDynamicMeshElements內挖的到, 請直接參考就好。 下圖 為分別使用DrawWireSphereAutoSides與GetSphereMesh的範例結果。 [圖3.] [圖4.] 結論 這次的範例是精簡過後的程式碼結果,如果想要往後鑽研的話,參考 GameplayDebuggerCategory裡面的使用方法是最好的。 在實作這些功能之前,最好是先在遊戲中輸入'開啟debug模式預覽結果。 在融會貫通之後,就可以針對專案開發出獨特的工具。 例如在Unreal Fest Europe 2019的演講中提到, 該Studio會在編輯器內顯示被選擇的Actor, 以連線的方式顯示參照的對象與被參照的對象。如圖 所示。 用來輕易地理解場景物件彼此的相關性, 如果場景物件關係複雜的話,這個功能會特別 有用。 [圖5.] 參考資料 https://docs.unrealengine.com/en-US/Gameplay/Tools/VisualLogger/index.html Visual Logger https://docs.unrealengine.com/en-US/Engine/AI/EnvironmentQuerySystem/EQSPawn/index.html EQS Testing Pawn https://www.unrealengine.com/zh-CN/events/unreal-fest-europe-2019/blueprints-blending-system-architecture-and-creativity Blueprints: Blending System Architecture and Creativity Deep Silver Dambuster Studios -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.162.114.82 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/GameDesign/M.1593014413.A.86A.html

06/25 00:03, 4年前 , 1F
推推推
06/25 00:03, 1F

06/25 01:13, 4年前 , 2F
推 太神啦 最近正在學習 感謝分享
06/25 01:13, 2F

06/25 03:20, 4年前 , 3F
good
06/25 03:20, 3F

06/25 10:43, 4年前 , 4F
06/25 10:43, 4F

06/25 15:50, 4年前 , 5F
06/25 15:50, 5F
※ 編輯: yekdniw (59.120.146.90 臺灣), 07/15/2020 11:03:58
文章代碼(AID): #1UytYDXg (GameDesign)
文章代碼(AID): #1UytYDXg (GameDesign)