iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

探索Unity中的視覺化製作工具系列 第 3

撰寫客製化的AssetGraph節點

一開始嘗試AssetGraph(AG)的情境是相當簡單的,但實際專案開發時的需求不太可能只是單純的將資料複製到另一個目錄。

隨著遊戲專案的進程,一定是愈來愈多元的資料會被加入,美術人員放入的圖檔後所延申的需求也好,企劃人員放入的數值資料所延申的需求也好,亦或是程式人員自身都有需要對於某些物件(Game Object)加入某特定元件(Component)的處理。雖然在AG還沒有被開發出來前,多數都是可藉由AssetPostprocessor趨動或Editor Menu趨動的機制實現,但這樣的製程下,相當仰賴程式人員的協助。

而視覺化的工具,旨在降低進入的門檻,串連節點和節點之間進而完成、實現某些功能。在這樣的認知下審視著AG,只能說目前提供的節點種類太少,想要利用它完成稍微複雜的處理是不可行的。

所幸它提供了一定程度的擴充,讓開發者可以自行依照需求撰寫各製化的節點。而它所提供的擴充目前從文件裡可以找到的是透過如下的Interface

  • IFilter
  • IPrefabBuilder
  • IAssetGenerator

進行客製化節點的實現。

這些Interface雖於文件中有額外更詳細的API文件,其連接的URL確是無效的連結,因此,沒有更多的內容可以參考,唯一的途徑只剩下從現有的節點去研究和在網路上找是否有同好撰寫的文章可供參考。

撇開要如何客製化節點的問題,先進行情境上的設定,易於展開後續的探索和實作。既然是希望能貼近實際的開發需求,那情境上的設定就需要複雜一些。一樣是圍繞在角色扮演(RPG)類型的遊戲製作上而展開需求。

這次會希望依據不同的的資料來源地產生相關聯的資料後,再擺放到另一目錄。延伸前述的資料分工,企劃人員將已將每一隻怪物的資料設定好後,以一隻怪物一份Json檔的方式放入到企劃人員開設的目錄下。而美術人員則是將怪物圖片以多張的方式存放在子目錄下,如Monster001、Monster002等,這些子目錄是放置在美術人員所開設的目錄下。

而程式人員則是因應後續在遊戲中可引用的原則下,將企劃人員給予的Json檔轉成ScriptableObject(SO),並將美術人員提供的圖片轉化成Prefab,放上相對應的Sprite Renderer元件。最後再輪出到另一目錄,按照怪物名稱產生子目錄後將關聯的SO和Prefab放入。

撰寫程式碼

為了確保這樣的情境不是天方夜譚無法實現的,先利用Editor Script進行。

Json轉成SO這部份,雖然Unity自身有提供JsonUtility可供使用,但結構中的序列化(Serialization)和反序列化(Deserialization)要自行撰寫,有些繁複。故利用quicktype網路服務,直接餵Json資料後取得Json.NET可直接使用的程式碼。

餵入了假想的怪物資料後,得到的程式碼可讀取此份Json檔。而讀取後再轉換成SO。但SO的部份就只能純手工撰寫,或許日後會用文字代換或Roslyn進行程式碼生成,但現階段來說太龐大且離題了。

產生SO的代碼片段如下

var assetOutPath =
    Path.Combine("Assets", "_", "Exported", "Monsters", $"{asset.id}", $"{asset.id}.asset");
AssetDatabase.CreateAsset(asset, assetOutPath);
AssetDatabase.SaveAssets();

至於產生Prefab這裡,憑藉著Unity提供的PrefabUtility即可完成,相關代碼片段如下

var monsterGO = new GameObject($"monster-{smdn}");
var spriteRenderer = monsterGO.AddComponent<SpriteRenderer>();
spriteRenderer.sprite = monsterTexture;

var monsterPrefabPath = Path.Combine("Assets", "_", "Exported", "Monsters", $"monster-{smdn}", $"monster-{smdn}.prefab");

monsterPrefabPath = AssetDatabase.GenerateUniqueAssetPath(monsterPrefabPath);

PrefabUtility.SaveAsPrefabAssetAndConnect(monsterGO, monsterPrefabPath, InteractionMode.UserAction);
GameObject.DestroyImmediate(monsterGO);

換換成客製化節點

客製化節點說穿了仍是撰寫程式碼,但切分的方式很講究的-至少要符合AG的預期才能夠順利的被其框架使用。

現有的情境中,要產生SO和Prefab,這很自然的就是要實現IAssetGeneratorIPrefabBuilder。試著將之前的程式碼抽出一部份,修改一部份,進而完成了二個客製化的節點。

分開的SO和Prefab都可產生唯中間的子目錄還未找到適合的地方生成,或許二個客製化的節點都需要分別加上產生目錄的功能,才不會有前後相依性的問題。但這對於任一個節點來說似乎是產生了過多的物件,故這點還尚未定案。

預設情境的需求在加入客製化的節點後,仍未能達成。中間的子目錄和prefab的名稱並不如預期。看樣子沒有文件的情況下,一時三刻是無法解決的。

今日測試用的專案放罝在Git Repo中的custom-asset-graph目錄裡,雖然離成功還有些距離,希望仍有些參考的價值,有興趣的開發者可以自行下載了解。

客製化節點感想

花了不少時間在嘗試上,若是文件中有詳細的解說和範例,相信入手的困難度會大幅度降低,而文件URL丟失這件事希望下一版的使用文件中能夠補上,這樣或許可以幫助到不少用AG的開發者,而我也可以將未完成的部份補上。


上一篇
半自動化工具AssetGraph
下一篇
串連執行多個AssetGraph
系列文
探索Unity中的視覺化製作工具30

尚未有邦友留言

立即登入留言