Unity3d進階學習(8)-- 自定義資源配置檔案、序列化
一、資源配置檔案、序列化的介紹
資源配置檔案:在遊戲開發中,經常會用到一些配置檔案儲存一些資料,然後專案執行中讀取這些配置檔案中的資料在遊戲中使用。比如 XML、JSON、Protobuf、Excel、TXT等等。
序列化:就是將資料的狀態資訊轉換為可以儲存或傳輸的形式的過程。比如將遊戲裡面的資料寫進檔案裡, 包括角色的生命, 攻擊, 防禦等等. 這樣當遊戲需要調整時 (比如平衡性問題), 就只需要對檔案進行改寫, 而不需要將遊戲進行重新編譯. 玩家在更新的時候也只需要下載幾個被改寫的檔案即可.
1.變數 –> 2.序列化格式資料 –> 3.儲存為檔案到硬碟 –> 4.載入檔案 –> 5.讀取序列化格式資料 –> 6.變數
1到2就是序列化,5到6就是反序列化
二、unity的自定義配置檔案
接下來說下使用可序列化類儲存配置,介紹一個Unity的配置檔案(.asset)。
優點:當我們需要將遊戲資源裡的貼圖(Texture)、遊戲物件(Gameobject)等預設體儲存到配置檔案時,這時我們就可以使用該配置檔案,但是當關聯的預設體丟失時,需要重新將預設體關聯起來。
三、通過案例深入理解
下面做一個小案例
1. 玩家通過滑鼠點選螢幕創建出不同的物件(玩家通過配置檔案自定義),創建出來的物件通過資源池進行管理
2. 每個類都有詳細介紹,可以根據需求直接使用
建立序列化類資源池類【GameObjectPool】– 儲存遊戲資源
1. 該類宣告為 [Serializable]
2. 需要序列化的變數將其設定為public或者設定其屬性為[SerializeField]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class GameObjectPool {
[SerializeField]
private string m_name;
[SerializeField]
private GameObject m_perfab;
[SerializeField]
private int m_maxAmount;
public string name
{
get
{
return m_name;
}
}
public GameObject gameobject
{
get
{
return m_perfab;
}
}
public int maxAmount
{
get
{
return m_maxAmount;
}
}
//
[NonSerialized]
private List<GameObject> m_gameObjList = new List<GameObject>();
public List<GameObject> gameObjList
{
get
{
if(m_gameObjList == null)
{
m_gameObjList = new List<GameObject>();
}
return m_gameObjList;
}
}
//如果要優化,可以在建立一個list用來存放Active為false的物體,需要的時候直接獲取就不用遍歷了
public GameObject GetObject()
{
foreach(GameObject obj in m_gameObjList)
{
if (!obj.activeInHierarchy)
{
obj.SetActive(true);
return obj;
}
}
if(m_gameObjList.Count >= m_maxAmount)
{
GameObject.Destroy(m_gameObjList[0]);
m_gameObjList.RemoveAt(0);
}
GameObject prefab = GameObject.Instantiate(m_perfab, new Vector3(0, 3, 0), Quaternion.identity);
m_gameObjList.Add(prefab);
return prefab;
}
}
儲存所有資源池的類【GameObjectPoolList】 – 建立該類為配置檔案
1. 類必須繼承 ScriptableObject
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 儲存所有的資源池 繼承ScriptableObject變成可自定義的資源配置檔案
/// </summary>
public class GameObjectPoolList: ScriptableObject
{
[SerializeField]
private List<GameObjectPool> m_poolList = new List<GameObjectPool>();
public List<GameObjectPool> poolList
{
get
{
if(m_poolList == null)
{
m_poolList = new List<GameObjectPool>();
}
return m_poolList;
}
}
}
管理資源池的類【PoolManager】 – 外界通過訪問這個類來訪問資源池
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager {
private static PoolManager m_instance = null;
public static PoolManager Instance
{
get
{
if(m_instance == null)
{
m_instance = new PoolManager();
}
return m_instance;
}
}
//檔案路徑
private const string m_pathPrefix = "Assets/FrameWork/Resources/";
private const string m_fileName = "Gameobjectpool";
private const string m_pathPostfix = ".asset";
public static string PoolConfigPath
{
get
{
return m_pathPrefix + m_fileName + m_pathPostfix;
}
}
//字典 根據name查詢對應的pool
private Dictionary<string, GameObjectPool> m_poolDic;
//建構函式
PoolManager()
{
GameObjectPoolList poolList = Resources.Load<GameObjectPoolList>(m_fileName);//獲取檔案類
m_poolDic = new Dictionary<string, GameObjectPool>();
foreach(GameObjectPool pool in poolList.poolList)
{
m_poolDic.Add(pool.name, pool);
}
}
public void Init()
{
//do nothing
}
public GameObject GetObjectFromPool(string poolName)
{
GameObjectPool pool;
if(m_poolDic.TryGetValue(poolName, out pool))
{
return pool.GetObject();
}
else
{
Debug.LogWarning("poolName: " + poolName + " is not exit");
return null;
}
}
}
建立配置檔案的類 【PoolManagerEditor】– 利用編譯器方法建立 GameObjectPoolList 為配置檔案
1. 工程下新建一個資料夾 Editor,在該資料夾下建立下面的類
2. 選單欄中找 Manager –> Create GameObjectPoolConfig 點選執行就可以 PoolManager.PoolConfigPath 的路徑下看到生成的配置檔案
public class PoolManagerEditor
{
//將這個方法做成一個選單
[MenuItem("Manager/Create GameObjectPoolConfig")]
static void CreatePoolList()
{
//將物件例項化
GameObjectPoolList poolList = ScriptableObject.CreateInstance<GameObjectPoolList>();
//建立類為可編輯的配置檔案
AssetDatabase.CreateAsset(poolList, PoolManager.PoolConfigPath);
AssetDatabase.SaveAssets();
}
}
四、測試
1. 通過配置檔案,自行配置資源
2. 程式碼測試
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
GameObject obj = PoolManager.Instance.GetObjectFromPool("Sphere");
}
}