2015年6月11日 星期四

Unity:使用 CreateAssetMenuAttribute 建立 Data Assets 來儲存設定資料

通常開發軟體都會有基本預設的設定值,特別是開發遊戲,總是會有很多遊戲系統、內容設定資料,每個人使用來儲存及設定這些資料的方法都不一樣,例如 XML 文檔、使用符號分隔的純文字檔、JSON 格式的純文字檔、Binary資料檔、Excel 檔.. 等等,不管使用哪一種,都需要有一套編輯這些資料以及寫入、讀出資料的規則及工具,這無非是一種額外的工作流程,但在 Unity 極富彈性的視覺化工作環境裡,我們可以透過建立資料資源檔來使工作變得更加便利以及更加有效率。

在以前發佈過的文章「腳本化物件 ScriptableObject 設置資料成為 AssetBundle」中,前半段即是在說明如何實作腳本化物件 ScriptableObject 來建立 Data Asset。

但是,時過境遷,經過幾年下來,前不久 Unity 5.1 也已發佈了,終於在這部分有了更方便的做法,就是使用 CreateAssetMenuAttribute 來使繼承 ScriptableObject 的 class 直接出現在 Unity 的 Assets > Create 選單的項目中,之後只要從選單直接選擇就能建立自己定義的資料資源檔。

實作方法非常簡單,首先,如往常一樣在 Project view 建立 Script,開啟之後將預設 class 繼承的 MonoBehaviour 改為 ScriptableObject,並在 class 上一行加入 [CreateAssetMenu],寫好要用來儲存設定資料的 public 欄位之後,回來 Unity 等待程式編譯完成,就可以發現 Assets > Create 多出與 class 名稱相同的選項。

using UnityEngine;

[CreateAssetMenu]
public class GameSettings : ScriptableObject {

    public string[] strings;
    public int[] integers;
    public float[] floats;
    public bool[] booleans;
    public byte[] bytes;
}

主選單的 Assets > Create 多出 Game Settings 資源選項
Project view 的 Create 選單多出 Game Settings 資源選項
在 Project view 按滑鼠右鍵的選單多出 Game Settings 資源選項



選擇該選項試試,會發現在 Project view 裡很輕易的就建立好用來存放資料的資源檔,選擇這個檔案之後,可以在 Inspector view 看到在 class 中宣告的欄位,如此就可以直接在 Unity 中輸入設定資料。
建立新的資源檔名會預設以 class 名稱前面加上 New 來命名
在 Inspector view 看到宣告的 public 欄位
有關 CreateAssetMenuAttribute 細節可以查看官方文件 的說明,從文件中可以知道我們還可以另行自訂預設檔名、選單路徑以及排列順序,所以,可以再修改程式碼如下:

using UnityEngine;

[CreateAssetMenu(fileName = "MySettings" , menuName = "My Asset/Data Setting" , order = 1)]
public class GameSettings : ScriptableObject {

    public string[] strings;
    public int[] integers;
    public float[] floats;
    public bool[] booleans;
    public byte[] bytes;
}

主選單 Assets > Create 原本的 Game Settings 資源選項變成 My Asset > Data Setting
Project view 的 Create 選單原本是 Game Settings 資源選項,變成 My Asset > Data Setting
在 Project view 滑鼠右鍵選單原本的 Game Settings 資源選項,變成 My Asset > Data Setting
新的資源檔名會以自行宣告的名稱來命名

至於要怎麼取用這些資料呢?只要在寫給 GameObject 做為 Component 使用的 Script(繼承 MonoBehaviour 的 class)宣告 public 欄位,然後直接在 Inspector view 將資料資源檔拉給該欄位即可取得檔案內的資料。

using UnityEngine;

public class GameManager : MonoBehaviour {

    public GameSettings settings;
}

在 Inspector view 的 Settings 欄位型別與資源檔相同
直接將資源檔設置到 Settings 欄位
以上面的兩段程式碼為例,我們之後的程式內容,只需要在 GameManager class 裡面寫 settings.booleans 就能取得 GameSettings 資源檔裡面的 booleans 欄位所設定的內容,相當直接,不用再另外製作工具或者設計寫入、讀出資料的規則,而且工作流程會相當統一,減少不必要的溝通,當然,如果有時間再另外編寫自定義編輯器的話,也可以為這個資料資源檔另外設計 UI,使得在 Inspector view 的操作上及資料識別更加方便及更容易閱讀。

這樣的做法除了很方便直接之外,還有另外的好處是,我們可以製作好幾份不同的 GameSettings 資源檔,然後分別拉給不同場景的 GameManager 使用,或者分類成不同版本的 GameSettings 來使用,那麼整個遊戲資料設定上將會變得非常有彈性和自由,而且開發快速。

另外,如果有在 Unity 中使用 UnityEditor API 去開發其他遊戲編輯、開發工具,使用這種資料資源檔也將會帶來很大的便利性。

最後,要提醒大家的是,當 Play mode 時,對資料資源檔所做的變更也會直接被儲存下來,而不會像其他遊戲物件一樣,關閉 Play mode 就恢復回 Play 之前的狀態,這一點要特別注意。

P.S. 目前使用 Unity 版本為 5.1.0f3。