框架與資源打包

一、對象池

一種通用型的技術(shù),在其他語言中也會用到

1. 池

線程池、網(wǎng)絡(luò)連接池,池是一個思想,將不用的東西暫時用池存起來,等到再次使用的時候再調(diào)出來用,節(jié)省CPU的調(diào)度

2. 對象

C#的任何一個類都可以實例化一個對象Object
Unity中的游戲?qū)ο驡ameObject

3. 思路

最開始的時候,池中沒有對象,需要生成。用完之后放到池中。再次使用的時候再從池中獲取

3.1 回收對象

把對象放到池中

3.2 獲取對象

從池中獲取對象

3.3 代碼實現(xiàn)

using System.Collections.Generic;
using UnityEngine;

public class ObjectPool
{
    #region 單例

    // 聲明單例
    private static ObjectPool Instance;

    /// <summary>
    /// 獲取單例
    /// </summary>
    /// <returns>The instance.</returns>
    /// <param name="resPath">Res path.</param>
    public static ObjectPool GetInstance(string resPath = "")
    {
        if (Instance == null)
        {
            if (resPath != "")
                Instance = new ObjectPool(resPath);
            else
                Instance = new ObjectPool();
        }
        Instance.UpdateResourcePath(resPath);
        return Instance;
    }
    // 構(gòu)造函數(shù)
    private ObjectPool()
    {
        prefabs = new Dictionary<string, GameObject>();
        pools = new Dictionary<string, List<GameObject>>();
    }
    private ObjectPool(string resPath)
    {
        prefabs = new Dictionary<string, GameObject>();
        pools = new Dictionary<string, List<GameObject>>();
        resourcePath = resPath;
    }

    #endregion

    #region 對象預(yù)設(shè)體資源管理

    // 資源加載路徑
    private string resourcePath;
    // 用字典存儲所有的預(yù)設(shè)體
    private Dictionary<string, GameObject> prefabs;
    // 更新預(yù)設(shè)體加載路徑
    private void UpdateResourcePath(string resPath)
    {
        resourcePath = resPath;
    }

    // 獲取預(yù)設(shè)體
    private GameObject GetPrefab(string prefabName)
    {
        // 如果包含預(yù)設(shè)體,直接返回
        if (prefabs.ContainsKey(prefabName))
            return prefabs[prefabName];
        // 如果不包含預(yù)設(shè)體,添加新的預(yù)設(shè)體,并返回
        return LoadPrefab(prefabName);
    }
    // 加載預(yù)設(shè)體
    private GameObject LoadPrefab(string prefabName)
    {
        // 拼接路徑
        string path = "";
        if (resourcePath != "")
        {
            path += resourcePath;
        }
        // 加載預(yù)設(shè)體
        GameObject obj = Resources.Load<GameObject>(path + prefabName);
        // 存入字典
        if (obj != null)
            prefabs.Add(prefabName, obj);
        // 返回
        return obj;
    }

    #endregion

    #region 對象池

    // 對象池
    private Dictionary<string, List<GameObject>> pools;

    /// <summary>
    /// 回收對象
    /// </summary>
    /// <param name="obj">Object.</param>
    public void RecycleObject(GameObject obj)
    {
        // 非激活
        obj.SetActive(false);
        // 獲取對象名稱
        string objName = obj.name.Replace("(Clone)", "");
        // 判斷有無該類對象池
        // 如果沒有,實例化一個子池
        if (!pools.ContainsKey(objName))
            pools.Add(objName, new List<GameObject>());
        // 存入
        pools[objName].Add(obj);
    }

    /// <summary>
    /// 獲取對象
    /// </summary>
    /// <returns>The object.</returns>
    /// <param name="objName">Object name.</param>
    /// <param name="poolEvent">Pool event.</param>
    public GameObject SpawnObject(string objName, System.Action<GameObject> poolEvent = null)
    {
        // 聲明一個輸出結(jié)果
        GameObject result = null;
        // 如果有池,并且池中有對象
        if (pools.ContainsKey(objName) && pools[objName].Count > 0)
        {
            result = pools[objName][0];
            pools[objName].Remove(result);
        }
        // 如果沒有池,或者池中沒有對象,需要生成
        else
        {
            // 拿到預(yù)設(shè)體
            GameObject prefab = GetPrefab(objName);
            if (prefab != null)
                result = GameObject.Instantiate(prefab);
        }
        // 激活
        result.SetActive(true);

        // 執(zhí)行事件
        if (result && poolEvent != null)
            poolEvent(result);

        // 返回結(jié)果
        return result;
    }

    #endregion
}

二、AssetBundle

  • 游戲中少部分必要的資源會隨游戲打包,其余的貼圖等資源在安裝好游戲后再獲得。AssetBundle就是資源的壓縮包,放在服務(wù)器。

1. 資源管理流程

  • 資源版本號:
    • 客戶端
      游戲開啟后,進行資源版本號校驗,如果發(fā)現(xiàn)版本號不同,就會從服務(wù)器下載
    • 服務(wù)器
      接收版本號之后,進行校驗,發(fā)現(xiàn)不同時,發(fā)送資源下載地址
  • 下載資源
    拿到下載地址,使用WWW進行下載,下載后得到AssetBundle,然后解壓加載資源
  • 資源校驗
    • 遇到新文件,則保存
    • 發(fā)現(xiàn)有文件重復(fù),則使用MD5校驗,一樣則沒有改變,不一樣就將客戶端的資源更新為從服務(wù)器上下載下來的資源
  • 資源的熱更新
    不需要重新下載安裝包,在游戲中將更新應(yīng)用

2. 資源管理操作

  • AssetBundle的打包(服務(wù)器操作)
    • Unity不支持一種AssetBundle多平臺用,只能一個平臺一個AssetBundle
    • 給需要打包的資源命名(名字AssetBundle名都是小寫)
    • 使用插件,Editor文件夾中
    • 菜單中打包
    • 資源依賴關(guān)系 Dependencies
      代碼實現(xiàn)
      BuildAssetBundle.cs
using UnityEngine;
using UnityEditor; // 用于寫插件的命名空間
using System.IO;

// 在菜單中創(chuàng)建一個選項
public class BuildAssetBundle : Editor
{
    [MenuItem("AssetBundle/Build/OSX")]
    public static void BuildOSX()
    {
        // AssetBundle的存儲路徑
        string path = Application.dataPath + "/AssetBundles/OSX";

        // 判斷路徑是否存在
        if (!File.Exists(path))
        {
            // 如果路徑不存在,創(chuàng)建路徑
            Directory.CreateDirectory(path);
        }

        // 打包
        BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSXIntel64);

        Debug.Log("打包成功!");
    }
}
  • AssetBundle的加載(客戶端操作)

    • 不帶有依賴的加載
    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class LoadTexture : MonoBehaviour
    {
        // 路徑
        private string path;
        // AssetBundle名字
        public string bundleName;
        // 資源名字
        public string assetName;
    
        private void Awake()
        {
            path = "file://" + Application.dataPath + "/AssetBundles/OSX/";
        }
    
        // 只加載一張圖,沒有依賴
        private IEnumerator Start()
        {
            WWW www = new WWW(path + bundleName);
            // 下載
            yield return www;
            // 獲取AssetBundle
            AssetBundle assetBundle = www.assetBundle;
            // 加載資源
            Texture texture = assetBundle.LoadAsset<Texture>(assetName);
            // 使用資源
            GetComponent<RawImage>().texture = texture;
            // 釋放資源
            assetBundle.Unload(false);
        }
    }
    
    • 帶有依賴的加載
    using System.Collections;
    using UnityEngine;
    
    public class LoadCube : MonoBehaviour
    {
        private string path;
        public string bundleName;
        public string assetName;
        public int version = 0;
    
        private void Awake()
        {
            path = "file://" + Application.dataPath + "/AssetBundles/OSX/";
        }
    
        // Cube有依賴,需要先查一下都依賴了什么
        private IEnumerator Start()
        {
            // 下載整個資源管理系統(tǒng)的說明文件(.manifast)先檢查緩存,存在則加載,不存在則下載
            WWW www = WWW.LoadFromCacheOrDownload(path + "OSX", version);
            // 下載
            yield return www;
            // 獲取到說明文件的bundle
            AssetBundle mani = www.assetBundle;
            // 加載mani文件
            AssetBundleManifest assetBundleManifest =   mani.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            // 查當(dāng)前要加載的資源的所有依賴
            string[] dependencies = assetBundleManifest.GetAllDependencies(bundleName);
            // 釋放AssetBundle
            mani.Unload(false);
            // 聲明依賴的Bundle數(shù)組
            AssetBundle[] depBundles = new AssetBundle[dependencies.Length];
            // 依次下載依賴
            for (int i = 0; i < dependencies.Length; i++)
            {
                // 下載依賴
                www = WWW.LoadFromCacheOrDownload(path + dependencies[i], version);
                // 等待下載
                yield return www;
                // 獲取,內(nèi)存中有就可以,不需要加載出來
                depBundles[i] = www.assetBundle;
            }
            // 下載最終的資源Bundle
            www = WWW.LoadFromCacheOrDownload(path + bundleName, version);
            // 等待下載
            yield return www;
            // 獲取Bundle
            AssetBundle assetBundle = www.assetBundle;
            // 獲取資源
            GameObject cubePre = assetBundle.LoadAsset<GameObject>(assetName);
            // 生成對象
            Instantiate(cubePre);
            // 釋放Bundle
            assetBundle.Unload(false);
            for (int i = 0; i < dependencies.Length; i++)
            {
                depBundles[i].Unload(false);
            }
        }
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容