Unity组件开发--UI管理器

news2024/11/18 17:36:57

1.Canvas组件:

注意属性:

(1)渲染模式是:屏幕空间相机

(2)创建一个UICamera节点,管理相机

(3)屏幕画布缩放模式

(4)画布下挂载两个脚本:UIRoot和UIManager

(5)事件系统管理节点必须有:

2.画布下其他节点类型:用于不同界面类型的管理归类window类型

3.先看UIRoot脚本:

using UnityEngine;

/// <summary>
/// 这个脚本用来定位UIROOT,因为GameObject.Find在浏览器上会踩坑
/// </summary>
public class UIRoot : MonoBehaviour {

    private void Awake() {
        DontDestroyOnLoad(gameObject);
    }

    void Start () {
    }

}

4.所有的UI界面预设体都用一个json文本管理起来:UIPanelType

{
"infoList":
[

{"panelTypeString":"HOME_PANEL",
"path":"HomePanel"},

{"panelTypeString":"WELCOME_PANEL",
"path":"WelcomePanel"},

{"panelTypeString":"MAIN_PANEL",
"path":"MainPanel"}

]
}

5.上面这个json文件中的path,对应的就是UI预设体的名字:由于我们的UI预制体都是用AB包的方式加载的,就都放在BundleAsset文件夹中

6.C#代码中也有有一个对应UI预设体名字的枚举类:

public enum UIPanelType {
    ALERT_PANEL,
    CONNECT_PANEL,
    HOME_PANEL,
    WELCOME_PANEL,
    MAIN_PANEL,
}

7.然后所有UI类脚本必须继承的基类:BasePanel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

[RequireComponent(typeof(CanvasGroup))]
public class BasePanel : MonoBehaviour {

    public enum PanelLayer {
        Normal,
        Hud,
        Addition,
        Windows,
        Wanring,
        ModelView,
    }

    [HideInInspector]
    public UIPanelType panelTpe;

    public PanelLayer Layer;


    protected CanvasGroup canvasGroup;
    protected virtual void Awake() {

        子类会继承这个函数,所以这里不应该写任何代码
        //name = GetType() + ">>";
        //canvasGroup = gameObject.GetComponent<CanvasGroup>();
    }

    protected new string name;



    /// <summary>
    /// 开启交互,页面显示
    /// </summary>
    public virtual void OnEnter() {
        //Debug.Log(name + "Enter");
        
        SetPanelActive(true);
        SetPanelInteractable(true);

    }

    /// <summary>
    /// 界面暂停,关闭交互
    /// </summary>
    public virtual void OnPause() {
        SetPanelInteractable(false);
    }

    /// <summary>
    /// 界面继续,恢复交互
    /// </summary>
    public virtual void OnResume() {
        SetPanelInteractable(true);
    }

    /// <summary>
    /// 界面不显示,退出这个界面,界面被关闭
    /// </summary>
    public virtual void OnExit() {
        SetPanelActive(false);
        SetPanelInteractable(false);
    }


    /// <summary>
    /// 关闭自身
    /// </summary>
    public void CloseSelf() {
        SetPanelActive(false);
        UIManager.Instance.CloseWindowMask();
        UIManager.Instance.ClosePannel(panelTpe);
    }

    private void SetPanelActive(bool isActive) {
        //isActive ^= this.gameObject.activeSelf;
        bool compare = isActive ^ gameObject.activeSelf;
        if (compare) {
            gameObject.SetActive(isActive);
        }
    }

    private void SetPanelInteractable(bool isInteractable) {
        //canvasGroup = canvasGroup == null ? gameObject.GetComponent<CanvasGroup>() : canvasGroup;
        //bool compare = isInteractable ^ canvasGroup;
        //if (compare) 
        //{
        //    canvasGroup.interactable = isInteractable; 
        //}
        //canvasGroup = canvasGroup == null ? gameObject.GetComponent<CanvasGroup>() : canvasGroup;
        //if (isInteractable ^ canvasGroup.interactable) canvasGroup.interactable = isInteractable;
    }

}

8.UI管理器脚本:UIManager

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using static BasePanel;

public class UIManager : MonoBehaviour {

    private static UIManager sInstanceUiManager;
    private Dictionary<UIPanelType, string> mPanelPathDictionary;//存储所有面板Prefab的路径
    private Dictionary<UIPanelType, BasePanel> mPanelPool;//保存所有实例化面板的游戏物体身上的BasePanel组件
    private Stack<BasePanel> mPanelStack; //TODO:需要拆分成多个堆栈,否则会有各种奇怪的问题


    private Transform mUIRootTransform;
    private GameObject windowsMask;
    
    
    
    
    

    public static UIManager Instance
    {
        get { return sInstanceUiManager; }
    }


    [Serializable]
    public class UIPanelTypeJson {
        public List<UIPanelInformation> infoList;
    }
    /// <summary>
    /// 实例化UIManager
    /// </summary>
    /// <returns></returns>



    void Awake() {
        sInstanceUiManager = this;
        DontDestroyOnLoad(gameObject);

        ParseUIPanelTypeJson();
        mUIRootTransform = GameObject.FindAnyObjectByType<UIRoot>().transform;
        windowsMask = mUIRootTransform.Find("Windows/Mask").gameObject;
        windowsMask.GetComponent<Button>().onClick.AddListener(ClickMask);
    }

    /// <summary>
    /// 从json配置文件解析为相对应的object类
    /// </summary>
    private void ParseUIPanelTypeJson() {
        mPanelPathDictionary = new Dictionary<UIPanelType, string>();
        TextAsset textAsset = Resources.Load<TextAsset>("GameRes/UIPrefabs/UIPanelType");
        //将json对象转化为UIPanelTypeJson类
        UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(textAsset.text);
        foreach (UIPanelInformation info in jsonObject.infoList) {
            mPanelPathDictionary.Add(info.panelType, info.path);
        }
    }

    public bool TopPanelIs(UIPanelType panelType) {

        BasePanel panel;
        mPanelPool.TryGetValue(panelType, out panel);
        if (!mPanelStack.Contains(panel))
        {
            return false;
        }
        else {
            int indexPanel = UtilsFunc.GetStackIndex(mPanelStack, panel);
            if (indexPanel!=null) return true;
            return false;
        }
    }



    public void CloseLastModelViewTypePanel() {

        //从栈顶开始查找指定面板
        BasePanel panelToRemove = null;
        for (int i = mPanelStack.Count - 1; i >= 0; i--)
        {
            BasePanel panel = mPanelStack.ElementAt(i);
            if (panel.Layer == PanelLayer.ModelView)
            {
                //找到则关闭页面
                panelToRemove = panel;
                panel.OnExit();
                break;
            }
        }
        if (panelToRemove != null)
        {
            //移除要关闭的面板
            mPanelStack.Pop();

            //重新压入除要移除的面板外的所有面板
            Stack<BasePanel> tempStack = new Stack<BasePanel>();
            while (mPanelStack.Count > 0)
            {
                BasePanel panel = mPanelStack.Pop();
                if (panel != panelToRemove)
                {
                    tempStack.Push(panel);
                }
            }
            while (tempStack.Count > 0)
            {
                BasePanel panel = tempStack.Pop();
                mPanelStack.Push(panel);
            }
        }
    }

    public bool IsOpenModelView() {
        for (int i = mPanelStack.Count - 1; i >= 0; i--)
        {
            BasePanel panel = mPanelStack.ElementAt(i);
            if (panel.Layer == PanelLayer.ModelView)
            {

                return true;

            }
        }
        return false;
    }

    /// <summary>
    /// 获得一个指定页面
    /// </summary>
    /// <param name="panelType">指定页面类型</param>
    /// <returns>返回该页面的BasePanel</returns>
    private void GetPanel(UIPanelType panelType) {
        if (mPanelPool == null) {
            mPanelPool = new Dictionary<UIPanelType, BasePanel>();
        }
        BasePanel panel;
        //从页面池中尝试找到指定页面的示例
        mPanelPool.TryGetValue(panelType, out panel);

        

        if (panel == null) {

            if (mPanelPool.ContainsKey(panelType)) {//意味着正在加载,不需要重复调用
                return;
            }
            string path;
            mPanelPathDictionary.TryGetValue(panelType, out path);

#if !UNITY_EDITOR
            AppConst.UseAssetBundle = true;
#endif
            mPanelPool.Add(panelType, null);
            if (AppConst.UseAssetBundle) {
                var addressPath = "Prefab/UIPrefabs/" + path;
                AssetBundleManager.Instance.LoadPrefab(addressPath, (instancePanel) => {

                    if (instancePanel != null) {
                        var targetPanel = instancePanel.GetComponent<BasePanel>();
                        SetPanel(targetPanel, panelType);
                    }
                    else {
                        Debug.LogError($"error {addressPath}");
                    }

                });
            }
            else {

                StartCoroutine(coEnsureWaitTime(panelType,path));
            }

        }
        else {
            if (panel.Layer != BasePanel.PanelLayer.Wanring) {
                panel.transform.SetAsLastSibling();
                if (mPanelStack.Contains(panel) == false) { //不存在才加入
                    mPanelStack.Push(panel);
                }
                else { //存在的话将其移动到栈顶
                    ToStackTop(panel);
                }
            }
            
            panel.OnEnter(); //OnEnter在 SetAsLastSibling 之后的目的是要置顶其他页面的时候可以生效
        }
    }



    void SetPanel(BasePanel targetPanel, UIPanelType panelType) {
        targetPanel.panelTpe = panelType;
        AddLayer(targetPanel);
        mPanelPool[panelType] = targetPanel;
        targetPanel.transform.SetAsLastSibling();

        if (targetPanel.Layer != BasePanel.PanelLayer.Wanring) {
            mPanelStack.Push(targetPanel);
        }

        targetPanel.OnEnter();
    }

    private void ToStackTop(BasePanel panel) {
        var tempStack = new Stack<BasePanel>();
        var tempPanel = mPanelStack.Pop();
        while (tempPanel != panel && mPanelStack.Count > 0) {
            tempStack.Push(tempPanel);
            tempPanel = mPanelStack.Pop();
        }
        if (tempPanel == panel) {
            mPanelStack.Push(tempPanel);
        }
        while (tempStack.Count > 0) {
            mPanelStack.Push(tempStack.Pop());
        }
    }

    IEnumerator coEnsureWaitTime(UIPanelType panelType, string path) {

        yield return new WaitForSeconds(0.1f);
#if UNITY_EDITOR
        var editorPath = "Assets/BundleAsset/Prefab/UIPrefabs/" + path + ".prefab";
        Debug.Log("load ui :"+editorPath);
        var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(editorPath);

        GameObject instancePanel = Instantiate(prefab) as GameObject;
        if (instancePanel != null) {
            var targetPanel = instancePanel.GetComponent<BasePanel>();
            SetPanel(targetPanel, panelType);
        }
#endif
    }

    private void ClickMask() {
        windowsMask.gameObject.SetActive(false);
        var topPanel = mPanelStack.Peek();
        topPanel.CloseSelf();
    }

    public void PreLoadUI(UIPanelType panelType) {
        if (mPanelPool == null)
        {
            mPanelPool = new Dictionary<UIPanelType, BasePanel>();
        }
        BasePanel panel;
        //从页面池中尝试找到指定页面的示例
        mPanelPool.TryGetValue(panelType, out panel);
        if (panel == null)
        {
            string path;
            mPanelPathDictionary.TryGetValue(panelType, out path);

#if !UNITY_EDITOR
            AppConst.UseAssetBundle = true;
#endif
            if (AppConst.UseAssetBundle)
            {
                var addressPath = "Prefab/UIPrefabs/" + path;
                AssetBundleManager.Instance.PreLoadBundle(addressPath);
            }
        }
    }

    public void OpenWindowMask() {
        EventManager.Instance.TriggerEvent(EventName.UIInteraction);
        windowsMask.SetActive(true);
        windowsMask.transform.SetAsLastSibling();
        if (mPanelStack != null) {
            var topPanel = mPanelStack.Peek();
            topPanel.transform.SetAsLastSibling();
        }
        
    }

    public void CloseWindowMask() {
        EventManager.Instance.TriggerEvent(EventName.ExitUIInteraction);
        windowsMask.SetActive(false);
    }

    /// <summary>
    /// 显示指定的面板
    /// </summary>
    /// <param name="panelType"></param>
    public void PushPanel(UIPanelType panelType) {

        if (mPanelStack == null)
            mPanelStack = new Stack<BasePanel>();
        //判断一下栈里面是否有页面
        if (mPanelStack.Count > 0) {
            var topPanel = mPanelStack.Peek();
            topPanel.OnPause();
        }
        this.CloseLastModelViewTypePanel();
        GetPanel(panelType);

    }

    public void CloseAllPannel() {

        for (int i = mPanelStack.Count - 1; i >= 0; i--)
        {
            BasePanel panel = mPanelStack.ElementAt(i);
            panel.OnExit();
            mPanelStack.Pop();
        }

    }

    /// <summary>
    /// 从栈里面找到指定面板将其关闭
    /// </summary>
    /// <param name="panelType"></param>
    public void ClosePannel(UIPanelType panelType) {

        if (mPanelPool.ContainsKey(panelType) == false) {
            Debug.LogError($"ClosePannel {panelType} null");
            return;
        }



        if (mPanelStack == null)
            return;
        //从栈顶开始查找指定面板
        BasePanel panelToRemove = null;
        for (int i = mPanelStack.Count - 1; i >= 0; i--) {
            BasePanel panel = mPanelStack.ElementAt(i);
            if (mPanelPool[panelType] == panel) {
                //找到则关闭页面
                panelToRemove = panel;
                panel.OnExit();
                break;
            }
        }
        if (panelToRemove != null) {

            //重新压入除要移除的面板外的所有面板
            Stack<BasePanel> tempStack = new Stack<BasePanel>();
            while (mPanelStack.Count > 0) {
                BasePanel panel = mPanelStack.Pop();
                if (panel != panelToRemove) {
                    tempStack.Push(panel);
                }
            }
            while (tempStack.Count > 0) {
                BasePanel panel = tempStack.Pop();
                mPanelStack.Push(panel);
            }
        }
    }

    /// <summary>
    /// 关闭页面并显示新的页面
    /// </summary>
    /// <param name="panelType"></param>
    /// <param name="isPopCurrentPanel">true时, 关闭当前页面; false时, 关闭所有页面</param>
    public void PushPanel(UIPanelType panelType, bool isPopCurrentPanel) {
        if (isPopCurrentPanel) {
            PopCurrentPanel();
        }
        else {
            PopAllPanel();
        }
        PushPanel(panelType);
    }
    /// <summary>
    /// 返回上一个页面
    /// </summary>
    /// <returns></returns>
    public bool BackToLastPanel() {
        //判断当前栈是否为空??表示是否可以返回
        if (mPanelStack == null)
            mPanelStack = new Stack<BasePanel>();
        if (mPanelStack.Count <= 1) return false;
        //关闭栈顶页面的显示
        var topPanel1 = mPanelStack.Pop();
        topPanel1.OnExit();
        //恢复此时栈顶页面的交互
        BasePanel topPanel2 = mPanelStack.Peek();
        topPanel2.OnResume();
        return true;
    }

    void AddLayer(BasePanel panel) {
        Transform dstParent = null;
        switch (panel.Layer) {
            case BasePanel.PanelLayer.Normal:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Normal));
                break;
            case BasePanel.PanelLayer.Hud:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Hud));
                break;
            case BasePanel.PanelLayer.Addition:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Addition));
                break;
            case BasePanel.PanelLayer.Windows:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Windows));
                break;
            case BasePanel.PanelLayer.Wanring:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.Wanring));
                break;
            case BasePanel.PanelLayer.ModelView:
                dstParent = mUIRootTransform.Find(nameof(BasePanel.PanelLayer.ModelView));
                break;
            default:
                break;
        }

        panel.transform.SetParent(dstParent,false);
    }

    /// <summary>
    /// 隐藏当前面板
    /// </summary>
    private void PopCurrentPanel() {
        if (mPanelStack == null)
            mPanelStack = new Stack<BasePanel>();
        if (mPanelStack.Count <= 0) return;
        //关闭栈顶页面的显示
        BasePanel topPanel = mPanelStack.Pop();
        topPanel.OnExit();
    }

    /// <summary>
    /// 隐藏所有面板
    /// </summary>
    public void PopAllPanel() {
        if (mPanelStack == null)
            mPanelStack = new Stack<BasePanel>();
        if (mPanelStack.Count <= 0) return;
        //关闭栈里面所有页面的显示
        while (mPanelStack.Count > 0) {
            BasePanel topPanel = mPanelStack.Pop();
            topPanel.OnExit();
            
        }
    }
    /// <summary>
    /// 切换场景前,调用该方法来清空当前场景的数据
    /// </summary>
    public void RefreshDataOnSwitchScene() {
        mPanelPathDictionary.Clear();
        mPanelStack.Clear();
    }
}

9.AB包加载管理器:AssetBundleManager

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

public class AssetBundleManager : MonoBehaviour {
    private static AssetBundleManager instance;

    

    private Dictionary<string, List<Action<GameObject>>> m_loadingActions = new Dictionary<string, List<Action<GameObject>>>(); 

    public static AssetBundleManager Instance {
        get {
            if (instance == null) {
                instance = new GameObject("AssetBundleManager").AddComponent<AssetBundleManager>();
            }
            return instance;
        }
    }

    private Dictionary<string, AssetBundle> loadedAssetBundles = new Dictionary<string, AssetBundle>();

    //public AssetBundle LoadAssetBundle(string bundleName, string sceneName = "") {
    //    if (loadedAssetBundles.ContainsKey(bundleName)) {
    //        return null;
    //    }

    //    string path = Application.streamingAssetsPath + "/" + bundleName;
    //    AssetBundle bundle = AssetBundle.LoadFromFile(path);
    //    if (bundle == null) {
    //        Debug.LogError($"Failed to load asset bundle: {bundleName}");
    //        return null;
    //    }

    //    loadedAssetBundles.Add(bundleName, bundle);

    //    if (!string.IsNullOrEmpty(sceneName)) {
    //        SceneManager.LoadScene(sceneName, LoadSceneMode.Additive);
    //    }

    //    return bundle;
    //}

    public void UnloadAssetBundle(string bundleName, string sceneName = "") {
        if (!loadedAssetBundles.ContainsKey(bundleName)) {
            return;
        }

        AssetBundle bundle = loadedAssetBundles[bundleName];
        bundle.Unload(true);
        loadedAssetBundles.Remove(bundleName);

        if (!string.IsNullOrEmpty(sceneName)) {
            SceneManager.UnloadSceneAsync(sceneName);
        }
    }

    public bool IsAssetBundleLoaded(string bundleName) {
        return loadedAssetBundles.ContainsKey(bundleName);
    }

    /// <summary>
    /// 示例 Prefab/Com/NpcHello
    /// </summary>
    /// <param name="prefabPath"></param>
    /// <param name="callback"></param>
    public void LoadPrefab(string prefabPath,System.Action<GameObject> callback) {

        if (m_loadingActions.TryGetValue(prefabPath,out var list)) {
            list.Add(callback);
            return; //这里返回不需要再开启协程
        }
        else {
            m_loadingActions.Add(prefabPath, new List<Action<GameObject>>());
            m_loadingActions[prefabPath].Add(callback);
        }

        StartCoroutine(LoadPrefabCoroutine(prefabPath));
    }

    enum Platefrom
    {
        PC,
        Mobile
    }


    string GetPrefabName(string prefabPath, Platefrom platefrom)
    {
        string desPlatform = "";
        if (platefrom == Platefrom.Mobile)
        {

            desPlatform = prefabPath + "_Mobile";

        }
        else
        {
            desPlatform = prefabPath;

        }
        var prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
        return prefabName;
    }

    
    private IEnumerator LoadPrefabCoroutine(string prefabPath) {
        
        var desPlatform = "";
        Debug.Log("UI路径LoadPrefabCoroutine......" + prefabPath);
        if (!PlayerData.Instance.isRunningPC)
        {

            desPlatform = prefabPath + "_Mobile";
            
        }
        else
        {
            desPlatform = prefabPath;

        }

        desPlatform = $"{Host.AssetBundleIP}/{desPlatform.ToLower()}.bundle";
        string prefabName = "";
        string bundlePath = $"{prefabPath.ToLower()}.bundle";
        string fullBundlepath = $"{Host.AssetBundleIP}/{bundlePath.ToLower()}";
        AssetBundle bundle = null;
        if (loadedAssetBundles.ContainsKey(prefabPath)) {
            yield return new WaitForEndOfFrame();
            bundle = loadedAssetBundles[prefabPath];
            if (bundle.Contains(GetPrefabName(prefabPath,Platefrom.Mobile)))
            {
                prefabName = GetPrefabName(prefabPath, Platefrom.Mobile);
            }
            else
            {
                prefabName = GetPrefabName(prefabPath, Platefrom.PC);
            }
        }
        else {
#if UNITY_EDITOR
            if (AppConst.useShowBundlePath) { //打需要演示的包时候需要先读取本地的streamAsset,如果存在侧不执行
                    var showBundlePath = Application.streamingAssetsPath + $"/webgl/{bundlePath.ToLower()}";
                    Debug.Log("showBundlePath:"+ showBundlePath);
                    UnityWebRequest showRequest = UnityWebRequestAssetBundle.GetAssetBundle(showBundlePath);
                    yield return showRequest.SendWebRequest();

                    if (showRequest.result == UnityWebRequest.Result.Success) {
                        Debug.Log($"load bundle ok: {showBundlePath}");
                        bundle = DownloadHandlerAssetBundle.GetContent(showRequest);
                    }
                    else {
                        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                        yield return request.SendWebRequest();
                        if (request.result != UnityWebRequest.Result.Success) {
                            Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                            yield break;
                        }
                        Debug.Log($"load bundle ok: {fullBundlepath}");
                        bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }
                }else {
                    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
                    yield return request.SendWebRequest();
                    if (request.result != UnityWebRequest.Result.Success) {
                        Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
                        request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                        yield return request.SendWebRequest();
                        if (request.result != UnityWebRequest.Result.Success) {
                            Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                            yield break;
                        }
                        Debug.Log($"load bundle ok: {fullBundlepath}");
                        prefabName = GetPrefabName(prefabPath,Platefrom.PC);
                        bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }else{
                    
                         Debug.Log($"load bundle ok: {desPlatform}");
                         prefabName =  GetPrefabName(prefabPath, PlayerData.Instance.isRunningPC ? Platefrom.PC : Platefrom.Mobile);
                         bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }
                   

                }
#else


            UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
            yield return request.SendWebRequest();
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");

                request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                yield return request.SendWebRequest();
                if (request.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                    yield break;
                }

                Debug.Log($"load bundle ok: {fullBundlepath}");
                bundle = DownloadHandlerAssetBundle.GetContent(request);
                prefabName = GetPrefabName(prefabPath,Platefrom.PC);

            }
            else {
                Debug.Log($"load bundle ok: {desPlatform}");
                prefabName = GetPrefabName(prefabPath, PlayerData.Instance.isRunningPC ? Platefrom.PC : Platefrom.Mobile);
                bundle = DownloadHandlerAssetBundle.GetContent(request);
            }
            
           
#endif
            loadedAssetBundles.Add(prefabPath, bundle);
        }

        
     
        if (bundle == null) {
            Debug.LogError($"Failed to get asset bundle content at path: {fullBundlepath}");
            doCallBack(prefabPath);
             yield break;
        }
        else {
            ResetBundleMaterials(bundle);
        }

        Debug.Log($"load bundle ok: {fullBundlepath}");
        AssetBundleRequest prefabRequest = bundle.LoadAssetAsync<GameObject>(prefabName);
        yield return prefabRequest;

        if (prefabRequest.asset == null) {
            Debug.LogError($"Failed to load prefab {prefabName} from asset bundle at path: {desPlatform}");
            doCallBack(prefabPath);
            yield break;
        }

        doCallBack(prefabPath, prefabRequest.asset);
        //bundle.UnloadAsync(true);
    }

    public void PreLoadBundle(string prefabPath) {
        StartCoroutine(PreLoadBundleCoroutine(prefabPath));
    }

    private IEnumerator PreLoadBundleCoroutine(string prefabPath) {


        var desPlatform = "";
        Debug.Log("UI路径PreLoadBundleCoroutine......" + prefabPath);
        if (!PlayerData.Instance.isRunningPC)
        {

            desPlatform = prefabPath + "_Mobile";
        }
        else
        {
            desPlatform = prefabPath;

        }

        desPlatform = $"{Host.AssetBundleIP}/{desPlatform.ToLower()}.bundle";

        string bundlePath = $"{prefabPath.ToLower()}.bundle";
        string prefabName = "";

        string fullBundlepath = $"{Host.AssetBundleIP}/{bundlePath.ToLower()}";

        AssetBundle bundle = null;
        if (loadedAssetBundles.ContainsKey(prefabPath)) {
            yield return null;
            bundle = loadedAssetBundles[prefabPath];
        }
        else {
#if !UNITY_EDITOR
            if (AppConst.useShowBundlePath) { //打需要演示的包时候需要先读取本地的streamAsset,如果存在侧不执行
                    var showBundlePath = Application.streamingAssetsPath + $"/webgl/{bundlePath.ToLower()}";
                    Debug.Log("showBundlePath:"+ showBundlePath);
                    UnityWebRequest showRequest = UnityWebRequestAssetBundle.GetAssetBundle(showBundlePath);
                    yield return showRequest.SendWebRequest();

                    if (showRequest.result == UnityWebRequest.Result.Success) {
                        Debug.Log($"load bundle ok: {showBundlePath}");
                        bundle = DownloadHandlerAssetBundle.GetContent(showRequest);
                    }
                    else {
                        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                        yield return request.SendWebRequest();
                        if (request.result != UnityWebRequest.Result.Success) {
                            Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                            yield break;
                        }
                        Debug.Log($"load bundle ok: {fullBundlepath}");
                        bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }
                }else {
                    UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
                    yield return request.SendWebRequest();
                    if (request.result != UnityWebRequest.Result.Success) {
                        Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
                        request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                        yield return request.SendWebRequest();
                        if (request.result != UnityWebRequest.Result.Success) {
                            Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                            yield break;
                        }
                        Debug.Log($"load bundle ok: {fullBundlepath}");
                        prefabName = UtilsFunc.GetFileNameWithoutExtension(fullBundlepath) + ".prefab";
                        bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }else{
                        Debug.Log($"load bundle ok: {desPlatform}");
                         prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
                        bundle = DownloadHandlerAssetBundle.GetContent(request);
                    }

                }
#else
            UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(desPlatform);
                yield return request.SendWebRequest();
            if (request.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"Failed to load asset bundle at path: {desPlatform}");
                request = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
                yield return request.SendWebRequest();
                if (request.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"Failed to load asset bundle at path: {fullBundlepath}");
                    yield break;
                }
                Debug.Log($"load bundle ok: {fullBundlepath}");
                prefabName = UtilsFunc.GetFileNameWithoutExtension(fullBundlepath) + ".prefab";
                bundle = DownloadHandlerAssetBundle.GetContent(request);
            }
            else {

                Debug.Log($"load bundle ok: {desPlatform}");
                prefabName = UtilsFunc.GetFileNameWithoutExtension(desPlatform) + ".prefab";
                bundle = DownloadHandlerAssetBundle.GetContent(request);
            }
                
#endif
        }

        if (bundle == null) {
            Debug.LogError($"Failed to get asset bundle content at path: {fullBundlepath}");
            yield break;
        }


        loadedAssetBundles.Add(prefabPath, bundle);
    }


    void doCallBack(string prefabPath, UnityEngine.Object asset = null) {

        if (asset == null) {
            m_loadingActions.Remove(prefabPath);
            return;
        }

        m_loadingActions.TryGetValue(prefabPath, out var list);
        if (list != null) {
            foreach (var action in list) {
                GameObject prefab = Instantiate(asset) as GameObject;
                action(prefab);
            }
            m_loadingActions.Remove(prefabPath);
        }
        else {
            Debug.LogError($"doCallBack {prefabPath}");
        }

    }

    public async Task<UnityWebRequest> LoadSceneSync(string sceneName) {

        string fullBundlepath = $"{Host.AssetBundleIP}/scenes/{sceneName.ToLower()}.bundle";

        UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(fullBundlepath);
        var asyncOp = await www.SendWebRequest();

        if (asyncOp.result != UnityWebRequest.Result.Success) {

            Debug.LogError(www.error);
        }
        else {
            Debug.Log("LoadSceneSync");
            DownloadHandlerAssetBundle.GetContent(www);
            await SceneManager.LoadSceneAsync(sceneName);

            ResetSceneAllMaterials();
        }

        return asyncOp;

    }

    private void ResetSceneAllMaterials() {
#if UNITY_EDITOR
        var scene = SceneManager.GetActiveScene();
        GameObject[] roots = scene.GetRootGameObjects();
        foreach (GameObject root in roots) {
            var renderers = root.GetComponentsInChildren<Renderer>();
            foreach (var render in renderers) {
                ResetMaterials(render.materials);
            }
        }
        if (RenderSettings.skybox != null)
            RenderSettings.skybox.shader = Shader.Find(RenderSettings.skybox.shader.name);
#endif
    }
    private void ResetMaterials(Material[] materials) {
        foreach (Material m in materials) {
            var shaderName = m.shader.name;
            if (shaderName == "Hidden/InternalErrorShader")
                continue;
            var newShader = Shader.Find(shaderName);
            if (newShader != null) {
                m.shader = newShader;
            }
            else {
                Debug.LogWarning("unable to refresh shader: " + shaderName + " in material " + m.name);
            }
        }
    }

    private  void ResetBundleMaterials(AssetBundle bundle) {

#if UNITY_EDITOR
        var materials = bundle.LoadAllAssets<Material>();
        ResetMaterials(materials);
#endif
    }



    void OnDestroy() {
        foreach (var bundle in loadedAssetBundles.Values) {
            bundle.Unload(true);
        }
        loadedAssetBundles.Clear();
    }
}
public static class Host
{
    /// <summary>
    /// 如果StreamAsset CONFIG 里面有配置AssetBundleIP,则使用那边的
    /// </summary>
    public static string AssetBundleIP = Application.dataPath.Replace("Assets", "") + "ABundles/webgl";
    public static string gameServer = "";
    public static string ApiHost = "";
    public static string remote = "";
}

10.新建一个UI预设体:

这个界面的业务脚本:WarningPanel

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class WarningPanel : BasePanel
{
    static string showText;
    public Text text;
    
    public GameObject confirmBtn;
    public GameObject closeBtn;

    private static Action confirmCallBack;
    private static Action closeCallBack;

    public static void Show(string showText,Action confirmBack,Action closeBack)
    {
        WarningPanel.showText = showText;

        WarningPanel.confirmCallBack = confirmBack;
        WarningPanel.closeCallBack = closeBack;
        UIManager.Instance.PushPanel(UIPanelType.WARNING_PANEL);
    }

    public override void OnEnter()
    {
        base.OnEnter();
        text.text = WarningPanel.showText;
        confirmBtn.GetComponent<Button>().onClick.AddListener(onClickConfirm);
        if(closeBtn!=null) closeBtn.GetComponent<Button>().onClick.AddListener(onClickClose);
    }

    private void onClickClose()
    {
        if (WarningPanel.closeCallBack != null) {

            WarningPanel.closeCallBack();
            
        }
    }

    IEnumerator WaitHide()
    {
        yield return new WaitForSeconds(2f);
        gameObject.SetActive(false);
    }

    private void onClickConfirm()
    {
        if (WarningPanel.confirmCallBack != null)
        {

            WarningPanel.confirmCallBack();
            //StopAllCoroutines();
            //StartCoroutine(WaitHide());
            
        }
        gameObject.SetActive(false);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1371587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见Mysql数据库操作语句

-- DDL创建数据库结构 -- 查询所有数据库 show databases ; -- 修改数据库字符集 alter database db02 charset utf8mb4; -- 创建字符编码为utf——8的数据库 create database db05 DEFAULT CHARACTER SET utf8;-- 创建表格 create table tb_user(id int auto_increment primar…

Kubernetes 核心实战之三(精华篇 3/3)

文章目录 6、Ingress ★6.1 安装 Ingress6.2 访问6.3 安装不成功的bug解决6.4 测试使用6.4.1 搭建测试环境6.4.2 配置 Ingress的规则6.4.3 测试I6.4.4 测试II6.4.5 路径重写6.4.6 限流 7. Kubernetes 存储抽象7.1 NFS 搭建7.2 原生方式 数据挂载7.3 PV 和 PVC ★7.3.1 创建 PV …

2023年度总结:但行前路,不负韶华

​ &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x…

【三】把Python Tk GUI打包exe可执行程序,移植到其他机器可用

背景 这是一个系列文章。上一篇【【二】为Python Tk GUI窗口添加一些组件和绑定一些组件事件-CSDN博客】 使用python脚本写一个小工具。因为命令行运行的使用会有dos窗口&#xff0c;交互也不是很方便&#xff0c;开发环境运行也不方便分享给别人用&#xff0c;所以想到…

生物信息学中的可重复性研究

科学就其本质而言&#xff0c;是累积渐进的。无论你是使用基于网络的还是基于命令行的工具&#xff0c;在进行研究时都应保证该研究可被其他研究人员重复。这有利于你的工作的累积与进展。在生物信息学领域&#xff0c;这意味着如下内容。 工作流应该有据可查。这可能包括在电脑…

java递归生成树型结构

java递归生成树 1.获取数据 public List<TreeClassifyRespVO> getTreeClassifyList(ClassifyPageReqVO reqVO) {List<ClassifyDO> classifyList classifyMapper.selectList(reqVO);List<TreeClassifyRespVO> childClassifyResp ClassifyConvert.INSTANCE…

2019年认证杯SPSSPRO杯数学建模B题(第一阶段)外星语词典全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 基于方差分布的方法对未知语言文本中重复片段的自动搜索问题的研究 B题 外星语词典 原题再现&#xff1a; 我们发现了一种未知的语言&#xff0c;现只知道其文字是以 20 个字母构成的。我们已经获取了许多段由该语言写成的文本&#xff0c;但…

哈希表-散列表数据结构

1、什么是哈希表&#xff1f; 哈希表也叫散列表&#xff0c;哈希表是根据关键码值(key value)来直接访问的一种数据结构&#xff0c;也就是将关键码值(key value)通过一种映射关系映射到表中的一个位置来加快查找的速度&#xff0c;这种映射关系称之为哈希函数或者散列函数&…

性能分析与调优: Linux 磁盘I/O 观测工具

目录 一、实验 1.环境 2.iostat 3.sar 4.pidstat 5.perf 6. biolatency 7. biosnoop 8.iotop、biotop 9.blktrace 10.bpftrace 11.smartctl 二、问题 1.如何查看PSI数据 2.iotop如何安装 3.smartctl如何使用 一、实验 1.环境 &#xff08;1&#xff09;主机 …

HarmonyOS4.0系统性深入开发15Want概述

Want概述 Want的定义与用途 Want是对象间信息传递的载体&#xff0c;可以用于应用组件间的信息传递。其使用场景之一是作为startAbility()的参数&#xff0c;包含了指定的启动目标以及启动时需携带的相关数据&#xff0c;如bundleName和abilityName字段分别指明目标Ability所…

Vue-10、Vue键盘事件

1、vue中常见的按键别名 回车 ---------enter <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>键盘事件</title><!--引入vue--><script type"text/javascript" src"h…

游戏版 ChatGPT,要用 AI 角色完善生成工具实现 NPC 自由

微软与 AI 初创公司 Inworld 合作&#xff0c;推出基于 AI 的角色引擎和 Copilot 助理&#xff0c;旨在提升游戏中 NPC 的交互力和生命力&#xff0c;提升游戏体验。Inworld 致力于打造拥有灵魂的 NPC&#xff0c;通过生成式 AI 驱动 NPC 行为&#xff0c;使其动态响应玩家操作…

问题记录:关于vivado报错解决

start_gui open_project E:/githome/xxxx.xpr ERROR: [Project 1-510] Parsing generated run data failed 在某些时候打开工程出现如下错误&#xff0c;运行源文件损坏。 解决办法&#xff1a; 重新打开工程。

scrollTop与offsetTop解决小分辨率区域块向上滚动效果效果,结合animation与@keyframes实现标题左右闪动更换颜色效果。

scrollTop 是一个属性&#xff0c;它表示元素的滚动内容垂直滚动条的位置。对于可滚动元素&#xff0c;scrollTop 属性返回垂直滚动条滚动的像素数&#xff0c;即元素顶部被隐藏的像素数。 offsetTop 是一个属性&#xff0c;用于获取一个元素相对于其父元素的垂直偏移量&…

揭秘智慧礼品背后的故事:AI怎么挑选礼物?

如若不是从事技术行业&#xff0c;在罗列礼品清单时&#xff0c;可能不会想到 “数据”&#xff0c;但幸运的是&#xff0c;我们想到了。如何将AI技术应用到当季一些最受青睐的产品中去&#xff0c;训练数据是这一智能技术的背后动力。很多电子设备或名称中带有“智能”一词的设…

中年危机与自我成长职业女性的心理转型之路

中年危机与自我成长&#xff1a;职业女性的心理转型之路 案例&#xff1a;李女士&#xff0c;45岁&#xff0c;职业女性 李女士是一位职业女性&#xff0c;人到中年&#xff0c;她突然感到自己的生活仿佛失去了方向。她来找我咨询&#xff0c;希望能够找到一条心理转型的道路&a…

数据结构入门到入土——链表(完)LinkedList

目录 一&#xff0c;双向链表 1.单向链表的缺点 2.什么是双向链表&#xff1f; 3.自主实现双向链表 接口实现&#xff1a; 二&#xff0c;LinkedList 1.LinkedList的使用 1.1 什么是LinkedList&#xff1f; 1.2 LinkedList的使用 1.LinkedList的构造 2.LinkedList的…

Ubuntu下多设备映射名称设置

目录 序言解决方法详细步骤编写映射规则文件针对 外设硬件信息 进行区分针对 机器人系统接口信息 进行区分 生效映射规则 摄像头外设特殊说明参考文献 序言 在机器人开发过程中&#xff0c;开发者会使用到多个外设&#xff0c;在传感器外设中&#xff0c;会用到激光雷达、摄像头…

关于git使用的tips

前言 这里是一些git指令使用的tips&#xff0c;如果你作为初学者的话&#xff0c;我认为它将对你有所帮助。 常见指令 常见问题处理 1、使用git clone下载【huggingface.co】资源超时或无法请求问题 绝大多数情况是网络问题&#xff0c;首先如果是比较大的资源&#xff0c;你需…

Centos7升级openssl到openssl1.1.1

Centos7升级openssl到openssl1.1.1 1、先查看openssl版本&#xff1a;openssl version 2、Centos7升级openssl到openssl1.1.1 升级步骤 #1、更新所有现有的软件包列表并安装最新的软件包&#xff1a; $sudo yum update #2、接下来&#xff0c;我们需要从源代码编译和构建OpenS…