Unity——UI框架+远程加载+PC/WebGL

基本的逻辑如下:

1:我把各个面板的Prefab存到资源目录下,Resources、StreamAssets、Addressable

我是使用了Addressable,因为可能要涉及到WebGL,要节约我的打包空间,所以干脆把所有的面板都丢到了服务器上,然后我从服务器上远程加载

2:给本地的面板类型和路径创建一个Json文件,如下:

{
	"panelInfoList": [
		{
			"panelType": "PopUp",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/PopUpPanel.prefab"
		},
		{
			"panelType":"Enter",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/EnterTrainingPanel.prefab"
		},
		{
			"panelType": "Login",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/LoginPanel.prefab"
		},

		{
			"panelType": "Introduction",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/IntroductionPanel.prefab"
		},
		{
			"panelType": "Loading",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/LoadingPanel.prefab"
		},
		{
			"panelType": "PlanBG",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/PlanBGPanel.prefab"
		},
		{
			"panelType": "YieldPlan",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/YieldPlanPanel.prefab"
		},
		{
			"panelType": "MoneyPlan",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/MoneyPlanPanel.prefab"
		},
		{
			"panelType": "SelectPatten",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/SelectPattenPanel.prefab"
		},
		{
			"panelType": "TaskPlan",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/TaskPlanPanel.prefab"
		},
		{
			"panelType": "InsurePlan",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPanels/InsurePlanPanel.prefab"
		},
		{
			"panelType": "MainTask",
			"path": "Assets/Art/Prefabs(CiShenUI)/MainPagePanels/MainTaskPanel.prefab"
		},
		{
			"panelType":"Market",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/MarketPanel.prefab"
		},
		{
			"panelType":"ShoppingCartPanel",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/ShoppingCartPanel.prefab"
		},
		{
			"panelType":"Warehouse",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/WarehousePanel.prefab"
		},
		{
			"panelType":"YieldPlanCheck",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/YieldPlanCheckPanel.prefab"
		},
		{
			"panelType":"LiveState",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/LiveStatePanel.prefab"
		},
		{
			"panelType":"KnowLedge",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/KnowLedgePanel.prefab"
		},
		{
			"panelType":"Financial",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/FinancialPanel.prefab"
		},
		{
			"panelType":"Assemble",
			"path":"Assets/Art/Prefabs(CiShenUI)/MainPagePanels/AssemblePanel.prefab"
		}
	]
}

3:然后做一个数据类,专门存储字段和面板名称一样的常量,如下:

/// <summary>
/// 所有的面板名称
/// </summary>
public class UIPanelType
{
    public const string PopUp = "PopUp";
    public const string Enter = "Enter";
    public const string Login = "Login";
    public const string Introduction = "Introduction";
    public const string Loading = "Loading";
    public const string PlanBG = "PlanBG";
    public const string YieldPlan = "YieldPlan";
    public const string MoneyPlan = "MoneyPlan";
    public const string SelectPatten = "SelectPatten";
    public const string TaskPlan = "TaskPlan";
    public const string InsurePlan = "InsurePlan";
    public const string MainTask = "MainTask";
    public const string Market = "Market";
    public const string ShoppingCartPanel = "ShoppingCartPanel";
    public const string Warehouse = "Warehouse";
    public const string YieldPlanCheck = "YieldPlanCheck";
    public const string LiveState = "LiveState";
    public const string KnowLedge = "KnowLedge";
    public const string Financial = "Financial";
    public const string Assemble = "Assemble";
}

4:然后再来一个UIManager来解析和读取,我把注释都写得很清楚

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Cysharp.Threading.Tasks;
using UnityEngine.Networking;

/// <summary>
/// 该类用于控制面板的字典和UI面板的加载方式
/// </summary>
public class UIManagerCi
{
    private static UIManagerCi _instance;
    private Transform canvasTransform;
    private bool isInitialized = false;

    private Transform CanvasTransform
    {
        get
        {
            if (canvasTransform == null)
            {
                canvasTransform = GameObject.Find("MainCanvas").transform;
            }
            return canvasTransform;
        }
    }

    public static UIManagerCi Instance
    {
        get
        {
            if(_instance == null)
            {
                _instance = new UIManagerCi();
            }
            return _instance;
        }
    }

    /// <summary>
    /// 存储面板名称和路径的字典
    /// </summary>
    private Dictionary<string, string> panelPathDic;

    /// <summary>
    /// 存储面板名称和具体面板的字典
    /// </summary>
    public Dictionary<string, BaseUIPanel> panelDic;

    /// <summary>
    /// 用于控制界面切换的栈
    /// </summary>
    private Stack<BaseUIPanel> panelStack;

    string jsonFilePath = Application.streamingAssetsPath + "/UIPanelType.json";
    //string jsonFilePath = new System.Uri(Application.streamingAssetsPath + "/UIPanelType.json").AbsoluteUri;

   
    /// <summary>
    /// 界面入栈方法
    /// </summary>
    /// <param name="panelType">界面的名称</param>
    public async  UniTask<BaseUIPanel> PushPanel(string panelType)
    {
        if (!isInitialized)
        {
            await InitializeAsync();
        }
        if (panelStack == null)
        {
            panelStack = new Stack<BaseUIPanel>();
        }
        // if (panelStack.Count > 0)
        // {
        //     BaseUIPanel topPanel = panelStack.Peek();
        //     // topPanel.OnPause();
        // }
        BaseUIPanel panel = await GetPanel(panelType);
        panelStack.Push(panel);

        return panel;

        //然后执行当界面进入时的方法
        //panel.OnEnter();
    }

    /// <summary>
    /// 界面出栈方法
    /// </summary>
    public void PopPanel()
    {
        if(panelStack == null)
        {
            panelStack = new Stack<BaseUIPanel>();
        }

        if(panelStack.Count <= 0)
        {
            return;
        }
        BaseUIPanel topPanel = panelStack.Pop();
        
        topPanel.OnExit();
        
        // //如果栈中还有元素,就获取该元素,然后调用方法
        // if(panelStack.Count > 0)
        // {
        //     BaseUIPanel panel = panelStack.Peek();

        //     // panel.OnResume();
        // }
    }

    /// <summary>
    /// 对UI面板的Prefab进行实例化创建和管理
    /// </summary>
    /// <param name="panelType"></param>
    /// <returns></returns>
    private async UniTask<BaseUIPanel> GetPanel(string panelType)
    {
        if (!isInitialized)
        {
            await InitializeAsync();
        }
        if (panelDic == null)
        {
            panelDic = new Dictionary<string, BaseUIPanel>();
        }
        BaseUIPanel panel = panelDic.GetValue(panelType);

        //如果面板没有实例化的话,就从路径字典中进行实例化,然后存储到已经实例化好的字典中
        if (panel == null)
        {
            //从路径字典里面获取界面的存储路径并加载xin
            string panelPath = panelPathDic.GetValue(panelType);
            var loadOperation = Addressables.LoadAssetAsync<GameObject>(panelPath);

            await loadOperation.Task;

            // loadOperation.WaitForCompletion();
            if(loadOperation.Status == AsyncOperationStatus.Succeeded)
            {
                GameObject panelPrefab = loadOperation.Result;
                GameObject panelGo = GameObject.Instantiate(panelPrefab,CanvasTransform,false);
                panel = panelGo.GetComponent<BaseUIPanel>();
                panelDic.Add(panelType, panel);
            }
            else
            {
                Debug.LogError("Panel loading failed: " + loadOperation.OperationException);
            }
            // Addressables.Release(loadOperation);
            // GameObject panelGo = (GameObject)GameObject.Instantiate(Resources.Load(panelPath), CanvasTransform, false);
        }
        return panel;
    }
    public async UniTask InitializeAsync()
    {
        if (!isInitialized)
        {
            await ParseUIPanelTypeJson();
            isInitialized = true;
        }
    }
    /// <summary>
    /// 将Json文件读取到数据类
    /// 然后把名称和路径都存在字典里面
    /// </summary>
    private async UniTask ParseUIPanelTypeJson()
    {
        panelPathDic = new Dictionary<string, string>();

        //string jsonUIString = File.ReadAllText(jsonFilePath);

        UnityWebRequest request = UnityWebRequest.Get(jsonFilePath);
        await request.SendWebRequest();
        string str = request.downloadHandler.text;

        // 把和Json文件映射的类写入Json
        UIPanelInfoList panelInfoList = JsonUtility.FromJson<UIPanelInfoList>(str);

        foreach(UIPanelInfo uIPanelInfo in panelInfoList.panelInfoList)
        {
           panelPathDic.Add(uIPanelInfo.panelType, uIPanelInfo.path);
        //    Debug.Log(panelPathDic[uIPanelInfo.panelType]);
        }
    }

最主要得方法就是Pop和Push方法,用于把面板加载或卸载,在Push里面有一个GetPanel方法可以讲一下

 private async UniTask<BaseUIPanel> GetPanel(string panelType)
    {
        if (!isInitialized)
        {
            await InitializeAsync();
        }
        if (panelDic == null)
        {
            panelDic = new Dictionary<string, BaseUIPanel>();
        }
        BaseUIPanel panel = panelDic.GetValue(panelType);

        //如果面板没有实例化的话,就从路径字典中进行实例化,然后存储到已经实例化好的字典中
        if (panel == null)
        {
            //从路径字典里面获取界面的存储路径并加载xin
            string panelPath = panelPathDic.GetValue(panelType);
            var loadOperation = Addressables.LoadAssetAsync<GameObject>(panelPath);

            await loadOperation.Task;

            // loadOperation.WaitForCompletion();
            if(loadOperation.Status == AsyncOperationStatus.Succeeded)
            {
                GameObject panelPrefab = loadOperation.Result;
                GameObject panelGo = GameObject.Instantiate(panelPrefab,CanvasTransform,false);
                panel = panelGo.GetComponent<BaseUIPanel>();
                panelDic.Add(panelType, panel);
            }
            else
            {
                Debug.LogError("Panel loading failed: " + loadOperation.OperationException);
            }
            // Addressables.Release(loadOperation);
            // GameObject panelGo = (GameObject)GameObject.Instantiate(Resources.Load(panelPath), CanvasTransform, false);
        }
        return panel;
    }

在每次Push得时候都会先判断panelDic是否创建,如果没有创建,就重新创建,如果创建了就从该字典中获取到面板得名称

string panelPath = panelPathDic.GetValue(panelType);
var loadOperation = Addressables.LoadAssetAsync<GameObject>(panelPath);

await loadOperation.Task;

这就是使用Addressable来加载面板

if(loadOperation.Status == AsyncOperationStatus.Succeeded)
   {
    GameObject panelPrefab = loadOperation.Result;
     GameObject panelGo = GameObject.Instantiate(panelPrefab,CanvasTransform,false);
     panel = panelGo.GetComponent<BaseUIPanel>();
     panelDic.Add(panelType, panel);
    }

如果加载成功了,就实例化,然后把这个面板存储到字典里面,否则就打印加载失败

5:这些面板有基类,如下:

using UnityEngine;

public abstract class BaseUIPanel : MonoBehaviour
{
    /// <summary>
    /// 当面板进入时
    /// </summary>
    public abstract void OnEnter();
    /// <summary>
    /// 当个面板停止的时候调用
    /// </summary>
    public abstract void OnPause();
    /// <summary>
    /// 当面板恢复的时候
    /// </summary>
    public abstract void OnResume();

    /// <summary>
    /// 当面板退出的时候调用
    /// </summary>
    public abstract void OnExit();
}

都会在相应得时机执行相应得方法

然后让你的各个面板类去继承该基类

6:最后有一个启动节点,挂载到MainCanvas下面即可

using System;
using UnityEngine;
public class CanvasRoot : MonoBehaviour
{

    刺参计划购买,材料购买,饲料购买,药品购买名称
    //public string CiShenPlan, MaterialPlan, FoodPlan, DrugPlan;
    计划购买具体金额
    //public float CiShenPlanNum, MaterialPlanNum, FoodPlanNum, DrugPlanNum;
    计划密度,数量,体长
    //public string PlanDensity, PlanCount, PlanLength;
    计划具体数值
    //public float PlanDensityNum, PlanCountNum, PlanLengthNum;
    计划的单位
    //public string PlanDensityUnit, PlanCountUnit, PlanLengthUnit;
    private async void Awake()
    {
        UIManagerCi panelManager = UIManagerCi.Instance;
        BaseUIPanel PopUpPanel = await panelManager.PushPanel(UIPanelType.PopUp);
        BaseUIPanel EnterPanel = await panelManager.PushPanel(UIPanelType.Enter);
    }
}

创建面板就是下面两行代码就行,我因为是异步加载,所以使用了await

BaseUIPanel PopUpPanel = await panelManager.PushPanel(UIPanelType.PopUp);
BaseUIPanel EnterPanel = await panelManager.PushPanel(UIPanelType.Enter);

基本逻辑就是上面的,剩下的你如果想用本地加载就把面板Prefab放到Resources或者StreamingAssets下,如果远程下载,就把面板放到后台就行

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
UniWebView是用于移动Unity3D游戏的现代Web视图组件。将网页内容集成到游戏中从未如此简单。什么是UniWebView UniWebView是一个Unity 3D插件,用于将Web视图组件添加到Unity 3D手机游戏中。UniWebView在C#中包含一组抽象的高级API,它们包装了iOS和Android平台的本机API。借助UniWebView,您可以在不了解本机开发的情况下将某些行为(例如浏览器)插入游戏。当您需要显示公告或通知,为玩家排名添加排行榜或仅向用户显示任何网页时,此功能非常有用。 #支持的平台 UniWebView支持运行: iOS 9.0或以上 Android 5.0(API级别21)或更高版本 在iOS上,UniWebView WKWebView用作渲染组件。在Android WebView上使用。 UniWebView还包含macOS上的Unity Editor支持,用于调试目的。如果要在Mac上开发游戏,则可以直接在Unity Editor的播放模式下打开独立的Web视图。如果您在Windows PC上工作,则仍可以在移动设备上构建和使用UniWebView,但是无法在Windows Unity编辑器中直接查看结果。 该编辑器插件是功能齐全的各种移动版本。尽管UniWebView是为移动平台设计的,但如果需要,您也可以将其放入独立的macOS游戏中。 #版本3 UniWebView项目始于2013年。UniWebView的原始版本支持Unity4。在Unity 5中,Unity团队更改了本机插件工作方式的方法,并且无法在同一插件版本中同时支持Unity 4和5。因此,我们决定对版本2进行重大升级。经过几年的开发,UniWebView 2现在非常稳定。但是,遗留代码仅UIWebView在iOS上支持旧样式(并且已弃用),并且我们还必须考虑向后兼容性,并且也必须使用过时的API WebView。 我们对这种情况不满意。如果我们使用最新技术,则性能和代码质量可能会大大提高。添加功能和解决问题也将更加容易和快捷。这就是我们决定从头开始重写UniWebView的原因。在版本3中,我们再次从0开始,并重新设计了几乎所有API。凭借过去几年的发展经验,我们有机会使美好的事物变得更好,而糟糕的设计也就消失了。 已经在使用UniWebView 2?请查看第3版的重点内容,以了解它是如何从以前的版本演变而来的。请注意,版本3与版本2不兼容。如果要从UniWebView 2升级,则不妨对迁移指南进行简要介绍。大多数概念是相似的,但可能仍需要一段时间才能升级。我们还建议您阅读我们的文档,以将UniWebView的潜在功能带到您的项目中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laker404

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值