2016年7月19日 星期二

2016.07.12 Random Exp for Unity

在上一篇「2016.06.22 Random Exp for Unity」初次展示 Random Exp for Unity 這個小工具之後,經過一些朋友所表達的意見以及準備用於實作專案中所產生的一些想法,再次做了一些修改,所以,再次來展示一下。



影片網址:https://youtu.be/4pzykoTXEJ0

這次的修改內容,影片裡只展示了關於 Scene Manage 和 Batch Command、Components 功能按鈕的擴充方面,但實際上還花了不少的時間來整理程式碼,在本篇文章後段將會大致說明一下。

Scene Manage

這次的修改與「2016.06.22 Random Exp for Unity」的差別,主要在於 Normal Scene 功能之後的 Add Loader 功能,這些功能主要是要提供給除了負責「初始化」與「載入中」場景以外的場景所使用的,Normal Scene 會在場景中建立基本一般場景中需要的基礎架構,包含負責初始化的遊戲物件、淡入淡出效果的 UI 以及應對各種畫面比例的自動調整… 等。

在執行 Normal Scene 功能之後,會同時依照 Initial、Loading 與 Target 選單欄位所選擇的項目,建立負責初始化的遊戲物件 Initialization 以及場景加載執行器 Scene Load Executor 與第一個 Loader 遊戲物件,當 Loader 的 StartLoad 被執行時,Loader 會要求 Scene Load Executor 遊戲物件去載入 Loader 所指定的場景。

所以,在「2016.06.22 Random Exp for Unity」的影片中可以發現到,不斷的在使 Button 的 On Click 事件指定 Loader 的 StartLoad。

而影片中為了讓 Game 視窗畫面容易理解在做什麼以及方便操作,所以,統一使用 UGUI 的 Button 來觸發要轉換場景的行為,但這樣也讓人產生疑問,Button 重複做著那幾個設置操作,為何不加上一個 Component 或是做成 Prefab 來更方便和簡化 Button 要求載入場景的操作。

在這裡,我們可能要先理解到一件事情,就是任何情況下,都可能會有需求去轉換場景,而要求轉換場景的契機不一定是點擊 UI 上的按鈕時,例如故事情節事件、任務事件、地圖傳點、戰鬥狀態、角色死亡... 等等的時機,依照設計上的不同,Loader 的 StartLoad 就可能被不同的事件執行,所以,並不能局限於給 Button 的 On Click 執行(事實上,這裡只是示範上的需求才使用 Button 的 On Click 來執行 Loader 的 StartLoad)。

不過,也因為這些疑問,突顯了設置事件去執行 Loader 的 StartLoad 時,操作上有多繁瑣以及不方便,所以,就產生了一些想法來嘗試改進。

Loader 遊戲物件主要所扮演的角色,其實就是「執行事件」與 Scene Load Executor 之間的溝通橋樑,事實上,我們不太需要去理會 Loader 遊戲物件,而應該把焦點放在哪個遊戲物件的事件欄位應該要執行哪一個 Loader 的 StartLoad 功能。

因此,決定在 Add Loader 功能按鈕被點擊之後,除了依照 Common Scene 區域所指定的選項來建立 Loader 遊戲物件之外,同時,也針對目前被選取的遊戲物件所配置的 Component 列出全部事件欄位清單,並可直接點擊清單上的 Attach 按鈕,快速地讓 Loader 與所指定的事件欄位連結起來。

而針對同一個目標場景,並不需要第二個相同 Loader 遊戲物件,所以,除了目標場景為 None 之外(因為不曉得目標為何),當場景中已經有一個相同的目標場景 Loader 遊戲物件存在時,Add Loader 按鍵功能,並不會再次產生相同內容的 Loader 遊戲物件,而直接列出事件欄位清單,當然,也為了讓 Hierachy 視窗可以方便辨識不同的 Loader 遊戲物件,也改為以目標場景名稱來命名 Loader 遊戲物件。

在「Unity:使用 UnityEngine.Events 讓程式更靈活、穩定」曾經提到過「如果 Class 裡所宣告的欄位並沒有要提供給外部存取的話,使用 public 修飾字就有些不恰當」,同樣的,針對事件欄位也是一樣,Add Loader 列出事件欄位清單的功能,也會因此遭遇到 Inspector 視窗明明有顯示出來的事件欄位,實際上卻不是具備 public 修飾字的欄位,因此,這個改進的功能,將不管該事件欄位是不是 public,只要它是能夠顯示於 Inspector 視窗的 Serialize 欄位,就都可以被列出來並透過 Attach 按鈕去設置。

經過這些修改,對照影片裡所展示的操作步驟,可以發現到設置要求載入場景的事件時,明顯快了很多,幾乎只要不斷的在 Shortcut 工具視窗上面點擊按鈕,就可以完成所有關於要求載入場景的事件,而省去了許多拖拉的操作。



Extend

就像上一篇裡的 Extend Components 一樣,直接在 Class 名稱上方加入 ComponentCategory 的 Attribute,就可以讓 Shortcut 工具視窗的 Components 區增加功能按鈕,而且,除了使用既有的分類之外,也可以使用自訂的名稱建立新的分類。

本次的修改,為了使程式功能更獨立以及未來功能的擴充,將 Batch Command 區的 SceneManage 內的功能分為兩個區塊,且也仿造 Components 那邊一樣,只要在 Class 名稱上方加入 SceneCommand 或 NormalSceneCommand 的 Attribute 就可以個別擴充該區塊的功能按鈕。

預設上,這些功能按鈕會依照 Class 名稱的字母順序排列,並且如 Inspector 視窗所顯示的欄位名稱一樣,將 Class 名稱依照字母大小寫來插入空格,使這些名稱更易於閱讀,但考慮到有時候會希望顯示於按鈕上的文字,可以使用比 Class 名稱更詳細、更易於表達功能的名稱,所以,另外加入了具名參數 nicifyName,來直接指定顯示於功能按鈕上的文字。

會有自訂顯示文字的需求,也可能會有指定排列順序的需求,所以,這些 Attribute 還有另一個具名參數 order,可以在該區塊中指定所要插入的排列順序。

Refactor

這部分並沒有在影片中展示,只在此處說明,Random Exp for Unity 工具程式同時包含了各式各樣的 Component,所涵蓋的功能,主要是各個不同專案中常用的共用功能,經過彙整之後,可以避免以後每個專案還要再寫相同的程式碼,以提昇工作效率。

而在每個專案實作的過程中,必定會有該專案專屬客製化的功能,所以,也會跟 Random Exp for Unity 一樣,會有許多新增的 Component 需要提供給不同場景的許多不同遊戲物件使用,以及會有簡化或者自動化配置的批次指令需求,所以,針對不同的專案,也會需要有個別客製化功能的 Shortcut 工具視窗。

所以,為了讓製作這個 Random Exp for Unity 的程式碼,可以延伸擴充開發個別專案的工具,也將程式碼重整並且抽離出來做為 Utilities API,包含製作 Editor 介面擴充與動態、組織命令功能按鈕、語言管理、PlayerSettings 控制、序列化屬性、Unity 事件欄位、驗證等。

如此,未來只要仿照相同的架構,就能對不同專案客製化建立類似 Random Exp for Unity 的工具,而不再需要重複編寫以及測試 Random Exp for Unity 已經完成的東西。

以上,雖然未能提供程式碼與範例專案下載,但主要還是希望能分享製作上的一些想法與思考方式,未來還會有其他的展示與說明來分享開發上的想法與經驗,還請大家多多關注粉絲專頁與 YouTube 頻道。

Unity 5.3.5f1。