Calmer的文章

  • 首页
  • 文章归档
  • 关于页面

  • 搜索
体验游戏 笔记 推荐 工具链 工具使用 小游戏 插件 UI 软件 教程

FairyGUI包管理扩展(支持Addressables)

发表于 2020-07-04 | 分类于 游戏开发 | 0 | 阅读次数 1099

UILoadMgr的管理思路
一般采用单例设计模式

字段:
预加载包字典
对象池字典

方法:
加载package
加载packages

获得Object

处理包之间依赖的关系

加载组件

加载纹理
释放纹理

移除包
释放Object


代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI;
using UnityEngine.ResourceManagement.AsyncOperations;
using System;
public class UILoadMgr
{
    private static UILoadMgr instance = null;
    public static UILoadMgr Instance
    {
        get
        {
            if (instance == null)
                return new UILoadMgr();
            return instance;
        }
    }

    private const string address = "Assets/ZBuild/Build/UI/{0}/{1}";

    private UILoadMgr()
    {
        //UIConfig.defaultFont=""
    }

    private struct HandleStruct
    {
        public Action callback;
        public bool isThemePark;
    }


    private Dictionary<string, Queue<AsyncOperationHandle>> dicHandle = new Dictionary<string, Queue<AsyncOperationHandle>>();
    private Dictionary<string, Queue<HandleStruct>> dicPkgCallback = new Dictionary<string, Queue<HandleStruct>>();
    private Dictionary<string, Queue<ModelViewStruct>> dicCallback = new Dictionary<string, Queue<ModelViewStruct>>();
    private static List<string> comPkgList = new List<string> { "Icon" };
    private static Dictionary<string, int> pkgRefCountDic = new Dictionary<string, int>();

    private static Dictionary<string, GObjectPool> dicGObjectPool = new Dictionary<string, GObjectPool>();

    public void LoadPackage(string modelName,Action callback=null)
    {
        Queue<AsyncOperationHandle> handles;
        if(dicHandle.TryGetValue(modelName,out handles))
        {
            callback?.Invoke();
            return;
        }
        Queue<HandleStruct> actions;
        if(dicPkgCallback.TryGetValue(modelName,out actions))
        {
            actions.Enqueue(new HandleStruct() { callback = callback, isThemePark = false });
            return;
        }
        else
        {
            dicPkgCallback[modelName] = new Queue<HandleStruct>();
            dicPkgCallback[modelName].Enqueue(new HandleStruct() { callback = callback, isThemePark = false });
        }

        AsyncOperationHandle handleBin = default(AsyncOperationHandle);
        handleBin = AddressableTools.LoadBinary(string.Format(address,modelName,modelName)+ "_fui.bytes", bytes =>
        {
            AddHandle(modelName, handleBin);
            UIPackage.AddPackage(bytes, modelName, (string name,string extension,System.Type type,PackageItem item)=> {
                AddressableTools.Load(string.Format(address, modelName, name + extension), data => {
                    item.owner.SetItemAsset(item, data, DestroyMethod.Unload);
                });
            });
            while(dicPkgCallback[modelName].Count>0)
            {
                var v = dicPkgCallback[modelName].Dequeue();
                v.callback?.Invoke();
            }
            dicPkgCallback[modelName].Clear();
            dicPkgCallback.Remove(modelName);
        });
    }

    public void PreLoadPackages(Action callback=null)
    {
        LoadPackages(comPkgList, callback);
    }

    public void LoadPackages(List<string> list,Action callback=null)
    {
        if(list==null || list.Count==0)
        {
            callback?.Invoke();
            return;
        }
        int count = 0;
        for (int i = 0; i < list.Count; i++)
        {
            Load(list[i], null, com => {
                count++;
                if (count >= list.Count)
                    callback?.Invoke();
            },false);
        }
    }

    private Transform uiPoolTransformRoot;

    public GObject GetPoolObject(string modelName,string viewName)
    {
        GObject obj;
        GObjectPool pool;
        string resourceURL = UIPackage.NormalizeURL(UIPackage.URL_PREFIX + modelName + "/" + viewName);
        if(resourceURL==null)
        {
            Debug.LogError(modelName + "/" + viewName + "没有设置导出!!!");
            return null;
        }
        if(!dicGObjectPool.TryGetValue(resourceURL,out pool))
        {
            pool = new GObjectPool(uiPoolTransformRoot);
            dicGObjectPool[resourceURL] = pool;
        }
        bool isCreate = pool.count == 0;
        obj = pool.GetObject(resourceURL);
        if(isCreate)
        {
            string pkgId = obj.packageItem.owner.id;
            int count;
            if(!pkgRefCountDic.TryGetValue(pkgId,out count))
            {
                pkgRefCountDic[pkgId] = 1;
            }
            else
            {
                pkgRefCountDic[pkgId] = ++count;
            }
        }
        return obj;
    }

    public void RecyclePoolObject(GObject obj)
    {
        if (obj == null) return;
        string resouceURL = obj.resourceURL;
        GObjectPool pool;
        if(dicGObjectPool.TryGetValue(resouceURL,out pool))
        {
            pool.ReturnObject(obj);
        }
        else
        {
            Debug.LogError(string.Format("回收对象{0},没有在对象内", obj.name));
        }

    }

    public void ClearPoolObject(string resourceURL)
    {
        GObjectPool pool;
        if(dicGObjectPool.TryGetValue(resourceURL,out pool))
        {
            pool.Clear();
        }
    }

    private struct ModelViewStruct
    {
        public string modelName;
        public string viewName;
        public bool isCreate;
        public Action<GObject> callback;
    }

    private List<string> GetNoLoadedDependenciesPackages(string[] dependenciesPackages)
    {
        List<string> list = new List<string>();
        Array.ForEach<string>(dependenciesPackages, v => {
            if(!comPkgList.Contains(v)&& !list.Contains(v)&&UIPackage.GetByName(v)==null)
            {
                list.Add(v);
            }
        });
        return list;
    }

    public void Load(string modelName,string viewName=null,Action<GObject> callback=null,bool isCreate=false,string[] dependenciesPackages=null)
    {
        List<string> pkgNames;
        if(dependenciesPackages!=null&& dependenciesPackages.Length>0&&(pkgNames=GetNoLoadedDependenciesPackages(dependenciesPackages)).Count>0)
        {
            LoadPackages(pkgNames, () => {
                LoadMain(modelName, viewName, callback, isCreate);    
            });
        }
        else
        {
            LoadMain(modelName, viewName, callback, isCreate);
        }
    }

    private void LoadMain(string modelName, string viewName = null, Action<GObject> callback = null,bool isCreate=false)
    {
        Queue<ModelViewStruct> actions;
        if(dicCallback.TryGetValue(modelName,out actions)&& actions!=null)
        {
            actions.Enqueue(new ModelViewStruct() { modelName = modelName, viewName = viewName, callback = callback, isCreate = isCreate });
            return;
        }
        else
        {
            dicCallback[modelName] = new Queue<ModelViewStruct>();
            dicCallback[modelName].Enqueue(new ModelViewStruct() { modelName = modelName, viewName = viewName, callback = callback, isCreate = isCreate });
        }
        LoadPackage(modelName, () => {
            while(dicCallback[modelName].Count>0)
            {
                var v = dicCallback[modelName].Dequeue();
                if(!v.isCreate)
                {
                    v.callback?.Invoke(null);
                    continue;
                }
                if(v.callback!=null)
                {
                    var com = GetPoolObject(v.modelName, v.viewName).asCom;
                    v.callback(com);
                }
            }
            dicCallback.Remove(modelName);
        });
    }

    public void LoadTexture(int address,Action<Texture> callback=null)
    {
        AsyncOperationHandle handle = AddressableTools.Load(address.ToString(), tex =>
        {
            callback(tex as Texture);
        });
    }

    public void DisposeTexture(int address)
    {
        AddressableTools.Release(address.ToString());
    }

    private void AddHandle(string modelName,AsyncOperationHandle handleBin)
    {
        Queue<AsyncOperationHandle> handles;
        if(!dicHandle.TryGetValue(modelName,out handles))
        {
            dicHandle[modelName] = new Queue<AsyncOperationHandle>();
            dicHandle[modelName].Enqueue(handleBin);
        }
    }

    private void RemovePackage(string modelName)
    {
        Queue<AsyncOperationHandle> handles;
        if(dicHandle.TryGetValue(modelName,out handles))
        {
            while(handles.Count>0)
            {
                var v = handles.Dequeue();
                AddressableTools.Release(v);
            }
            handles.Clear();
            dicHandle.Remove(modelName);
            UIPackage.RemovePackage(modelName);
        }
    }

    public void DisposeObject(GObject obj)
    {
        if (obj == null) return;
        int count;
        string pkgId = obj.packageItem.owner.id;
        if(pkgRefCountDic.TryGetValue(pkgId,out count))
        {
            pkgRefCountDic[pkgId] = --count;
            if(count<=0)
            {
                var pkg = UIPackage.GetById(pkgId);
                RemovePackage(pkg.name);
                pkgRefCountDic.Remove(pkgId);
            }
        }
        obj.Dispose();
    }

}

  • 本文作者: Calmer
  • 本文链接: https://mytechplayer.com/archives/fairygui包管理扩展支持addressables
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
# 工具链
协程管理
自动化生成代码工具
  • 文章目录
  • 站点概览
Calmer

Calmer

88 日志
7 分类
10 标签
RSS
Creative Commons
0%
© 2020 — 2025 Calmer
由 Halo 强力驱动
蜀ICP备20010026号-1川公网安备51019002006543
Copyright © 2020-2025 Calmer的文章