Unity UI框架

这篇具有很好参考价值的文章主要介绍了Unity UI框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

最近在各大网站看了一下 Unity3d 的 UI 框架,各种 UI 框架已经有很多的版本了,各有千秋,有的功能虽然写的完善,但用起来太复杂,有的框架功能不完善,搞个课程就上架了,还有什么 MVC 框架,绕来绕去的看的头都大了,这些根本不想用。

于是我自己就写了一个 UI 框架,只有两个脚本,不用向 UI 预制体上挂载脚本,所有的组件访问都可以通过 UIManager 来控制,常用的几个方法:显示界面,关闭界面,查找子物体,就这么多。

二、UI 框架

下面的两个脚本是 UI 框架的核心部分,具体的用法在下面的章节有介绍

UIBase

using UnityEngine;

public class UIBase
{
    #region 字段
    
    /// <summary>
    /// Prefabs路径
    /// </summary>
    public string PrefabsPath { get; set; }
    /// <summary>
    /// UI面板的名字
    /// </summary>
    public string UIName { get; set; }
    /// <summary>
    /// 当前UI所在的场景名
    /// </summary>
    public string SceneName { get; set; }
    /// <summary>
    /// Type 的全名
    /// </summary>
    public string FullName { get; set; }
    /// <summary>
    /// 当前UI的游戏物体
    /// </summary>
    public GameObject UIGameObject { get; set; }


    #endregion

    /// <summary>
    /// 面板实例化时执行一次
    /// </summary>
    public virtual void Start() { }

    /// <summary>
    /// 每帧执行
    /// </summary>
    public virtual void Update() { }

    /// <summary>
    /// 当前UI面板销毁之前执行一次
    /// </summary>
    public virtual void Destroy() { }


    /// <summary>
    /// 根据名称查找一个子对象
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public GameObject GetObject(string name)
    {
        Transform[] trans = UIGameObject.GetComponentsInChildren<Transform>();
        foreach (var item in trans)
        {
            if (item.name == name)
                return item.gameObject;
        }

        Debug.LogError(string.Format("找不到名为 {0} 的子对象", name));
        return null;
    }

    /// <summary>
    /// 根据名称获取一个子对象的组件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    public T GetOrAddCommonent<T>(string name) where T : Component
    {
        GameObject child = GetObject(name);
        if (child)
        {
            if (child.GetComponent<T>() == null)
                child.AddComponent<T>();
            return child.GetComponent<T>();
        }
        return null;
    }


    protected UIBase() { }
}

UIManager

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

public class UIManager : MonoBehaviour
{
    public static UIManager Instance;

    //存储场景中的UI信息
    private Dictionary<string, UIBase> UIDic = new Dictionary<string, UIBase>();

    //当前场景的 Canvas 游戏物体
    private Transform CanvasTransform = null;

    //当前字典中UI的个数
    public int UICount
    {
        get { return UIDic.Count; }
    }

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {

    }

    private void Update()
    {
        if (UIDic.Count > 0)
        {
            foreach (var key in UIDic.Keys)
            {
                if (UIDic[key] != null)
                    UIDic[key].Update();
            }
        }
    }

    /// <summary>
    /// 显示面板
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public UIBase ShowUI<T>() where T : UIBase
    {
        Type t = typeof(T);
        string fullName = t.FullName;

        if (UIDic.ContainsKey(fullName))
        {
            Debug.Log("当前面板已经显示了,名字:" + fullName);
            return UIDic[fullName];
        }

        GameObject canvasObj = GameObject.Find("Canvas");
        if (canvasObj == null)
        {
            Debug.LogError("场景中没有Canvas组件,无法显示UI物体");
            return null;
        }
        CanvasTransform = canvasObj.transform;

        UIBase uiBase = Activator.CreateInstance(t) as UIBase;
        if (string.IsNullOrEmpty(uiBase.PrefabsPath))
        {
            Debug.LogError("Prefabs 路径不能为空");
            return null;
        }

        GameObject prefabs = Resources.Load<GameObject>(uiBase.PrefabsPath);
        GameObject uiGameOjbect = GameObject.Instantiate(prefabs, CanvasTransform);
        uiGameOjbect.name = uiBase.PrefabsPath.Substring(uiBase.PrefabsPath.LastIndexOf('/') + 1);

        uiBase.UIName = uiGameOjbect.name;
        uiBase.SceneName = SceneManager.GetActiveScene().name;
        uiBase.UIGameObject = uiGameOjbect;
        uiBase.FullName = fullName;
        uiBase.Start();

        UIDic.Add(fullName, uiBase);
        return uiBase;
    }

    /// <summary>
    /// 移除面板
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public void RemoveUI<T>()
    {
        Type t = typeof(T);
        string fullName = t.FullName;

        if (UIDic.ContainsKey(fullName))
        {
            UIBase uIBase = UIDic[fullName];
            uIBase.Destroy();

            GameObject.Destroy(uIBase.UIGameObject);
            UIDic.Remove(fullName);
            return;
        }
        Debug.Log(string.Format("当前的UI物体未实例化,名字:{0}", fullName));
    }

    /// <summary>
    /// 清除所有的UI物体
    /// </summary>
    public void ClearAllPanel()
    {
        foreach (var key in UIDic.Keys)
        {
            UIBase uIBase = UIDic[key];
            if (uIBase != null)
            {
                uIBase.Destroy();
                GameObject.Destroy(uIBase.UIGameObject);
            }
        }

        UIDic.Clear();
    }

    /// <summary>
    /// 找到指定的UI面板
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="name"></param>
    /// <returns></returns>
    public GameObject GetGameObject<T>(string name)
    {
        Type t = typeof(T);
        string fullName = t.FullName;

        UIBase uIBase = null;
        if (!UIDic.TryGetValue(fullName, out uIBase))
        {
            Debug.Log("没有找到对应的UI面板,名字:" + fullName);
            return null;
        }

        return uIBase.GetObject(name);
    }

    private UIManager() { }
}

三、UI 框架的用法

我用了两个 场景来测试框架,start 和 main 场景

start 场景如下:

unity ui框架,Unity,unity   

在 Start 场景 GameRoot 上挂上 StartSceneRoot 脚本

unity ui框架,Unity,unity

这个脚本就调用框架在场景中显示一个UI

using UnityEngine;

public class StartSceneRoot : MonoBehaviour {	
	void Start () {
		UIManager.Instance.ShowUI<Panel_MainUI>();
    }
}

在 GameManager 游戏物体上有两个脚本,这个是要跟随着场景一起跳转的。

unity ui框架,Unity,unity

UIManager 的代码在上一节,下面是 GameManager 代码 

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour {

    public static GameManager Instance;
    private static bool origional = true;

    private void Awake()
    {
        if (origional)
        {
            Instance = this as GameManager;
            origional = false;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }
    }

    void Start () {
        SceneManager.sceneUnloaded += SceneManager_sceneUnloaded;
        SceneManager.sceneLoaded += SceneManager_sceneLoaded;
    }

    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        //Debug.Log("场景加载了,场景名:" + arg0.name);
    }

    private void SceneManager_sceneUnloaded(Scene arg0)
    {
        //Debug.Log("场景卸载了,场景名:" + arg0.name);

        //注意:切换场景要清除掉 UIManager 中保存的 UI 数据
        UIManager.Instance.ClearAllPanel();
    }

    public void LoadScene(string sceneName)
    {
        if (SceneManager.GetActiveScene().name != sceneName)
        {
            SceneManager.LoadScene(sceneName);
        }
    }

    private GameManager() { }
}

在 start 场景中挂载到游戏物体上的脚本就这三个:StartSceneRoot,GameManager,UIManager

下面就准备要显示的 UI 了,在这里,我做了三个 UI 界面,并做成预制体

unity ui框架,Unity,unity

界面 Panel_MainUI

unity ui框架,Unity,unity

界面 Panel_Setting

unity ui框架,Unity,unity

界面 Panel_Affiche

unity ui框架,Unity,unity

这三个预制体对应的也是三个脚本,但不用挂在游戏物体上,作用是UI的逻辑部分。

Panel_MainUI

using UnityEngine;
using UnityEngine.UI;

public class Panel_MainUI : UIBase
{
    public Panel_MainUI()
    {
        PrefabsPath = "Prefabs/UI/Panel_MainUI";
    }

    public override void Start()
    {
        GetOrAddCommonent<Button>("Button_Setting").onClick.AddListener(() =>
        {
            //显示设置面板
            UIManager.Instance.ShowUI<Panel_Setting>();
        });

        GetOrAddCommonent<Button>("Button_Task").onClick.AddListener(() =>
        {
            //清除所有的面板
            //UIManager.Instance.ClearAllPanel();  

            //跳转到 main 场景
            GameManager.Instance.LoadScene("main");
        });

        GetOrAddCommonent<Button>("Button_Equipage").onClick.AddListener(() =>
        {
            Debug.Log("UIManager 中 UI 面板的个数:" + UIManager.Instance.UICount);
        });
    }

    public override void Update()
    {
        //Debug.Log("我是 Panel_MainUI Update 方法");
    }

    public override void Destroy()
    {
        //Debug.Log("我是 Panel_MainUI Destroy 方法");
    }
}

Panel_Setting

using UnityEngine;
using UnityEngine.UI;

public class Panel_Setting : UIBase
{
    public Panel_Setting()
    {
        PrefabsPath = "Prefabs/UI/Panel_Setting";
    }

    public override void Start()
    {
        //Debug.Log("我是 Panel_Setting Start 方法");

        GetOrAddCommonent<Button>("Button_Close").onClick.AddListener(() =>
        {
            //移除自己
            UIManager.Instance.RemoveUI<Panel_Setting>();
        });

        GetOrAddCommonent<Button>("Button_Test").onClick.AddListener(() =>
        {
            //访问其他的面板的游戏物体 
            GameObject obj = UIManager.Instance.GetGameObject<Panel_MainUI>("Button_Map");
            if (obj != null)
                obj.transform.Find("Text").GetComponent<Text>().text = "Map";
        });

        GetOrAddCommonent<Button>("Button_Test1").onClick.AddListener(() =>
        {
            Debug.Log("UIManager 中 UI 面板的个数:" + UIManager.Instance.UICount);
        });
    }

    public override void Update()
    {
        //Debug.Log("我是 Panel_Setting Update 方法");
    }

    public override void Destroy()
    {
        //Debug.Log("我是 Panel_Setting Destroy 方法");
    }
}

Panel_Affiche

using UnityEngine;
using UnityEngine.UI;

public class Panel_Affiche : UIBase
{
    public Panel_Affiche()
    {
        PrefabsPath = "Prefabs/UI/Panel_Affiche";
    }

    public override void Start()
    {
        GetOrAddCommonent<Button>("Button_Close").onClick.AddListener(() =>
        {
            GameManager.Instance.LoadScene("start");
        });
    }

    public override void Update()
    {
        //Debug.Log("我是 Panel_Affiche Update 方法");
    }

    public override void Destroy()
    {
        //Debug.Log("我是 Panel_Affiche Destroy 方法");
    }
}

main 场景只挂了一个脚本

unity ui框架,Unity,unity

unity ui框架,Unity,unity

MainSceneRoot 脚本同样也是只是用来显示UI用的

using UnityEngine;

public class MainSceneRoot : MonoBehaviour {
	void Start () {
		UIManager.Instance.ShowUI<Panel_Affiche>();
	}
}

运行后就能看到,显示了 Panel_MainUI 的UI界面,点击设置,就会打开设置的界面,点击任务按钮,就会跳转到 main 场景(这里只是测试)

跳转到 main 场景后,点击关闭按钮,又会返回到 start 场景。

演示就这些了,写这个框架我也就用了几个小时而已,当然还有待继续完善和改进的,另外,我用的 Unity版本是 Unity 5.6.7f1 ,C# 的一些高级语法用不了,不然可以写的更优雅一些。

源码:点击跳转

结束

如果这个帖子对你有所帮助,欢迎 关注 + 点赞 + 留言

end文章来源地址https://www.toymoban.com/news/detail-814965.html

到了这里,关于Unity UI框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity 前端场景搭建UI框架的设计

    基础组件库:设计一套基础组件库,包括常用的 UI 控件,如文本、按钮、图像等,组件库的设计应该尽量简单易用,方便开发者快速搭建 UI 界面。 布局管理器:为了方便 UI 界面的排版,需要设计一套布局管理器,如水平布局、垂直布局、网格布局等,布局管理器应该支持自

    2024年02月16日
    浏览(46)
  • Unity–UI框架-Canvas-EventSystem-Panel

    画布canvas是控制一组UI元素如何呈现的组件, 所有UI元素必须是画布的子项 ,场景中可以有多个画布,但是UI元素至少需要一个可用的画布canvas, 每个画布都有不同的渲染模式,渲染模式可以使用Render Mode进行设置, 1.Screen Space-Overlay 其中,第一种是最常见的渲染模式,也是

    2024年02月03日
    浏览(53)
  • Unity Xlua热更新框架(五):Lua和UI管理

    :::info Lua存在两种加载器,一种默认加载器(env.DoString(\\\"require(‘test’)\\\"直接用了默认加载其),直接调用StreamingAssets中的脚本);一种是自定义加载器(env.AddLoader(Envpath)),优先于默认加载器(下文DoString就是从自定义加载器的路径读取的),并且当Lua代码执行require函数时,

    2024年02月06日
    浏览(55)
  • 【Unity小技巧】手戳一个简单易用的游戏UI框架(附源码)

    参考原视频链接: 【视频】:https://www.bilibili.com/video/BV1zT411b7L3/ 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入 开发一款游戏美术成本是极其高昂的,以我们常见的宣传片CG为例,动辄就要成百上千万的价格,因此这种美术物料一般只

    2024年02月11日
    浏览(52)
  • Unity用鼠标拖拽UI,UI跟随鼠标移动

    先上效果 继承几个拖拽的接口 IBeginDragHandler, IDragHandler,IEndDragHandler 计算下偏移量,转换下坐标系 限制下可拖拽的范围,我设置的是canvas的大小 欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。 如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~ 声明

    2024年02月06日
    浏览(82)
  • Unity UI 优化技巧

    问题:当 UI Canvas 的任何元素发生变化时,都会影响整个 Canvas。 Canvas 是 Unity UI 的重要组成部分。它创建一个网格来表示放置在其顶部的 UI 元素,在 UI 元素更改时重建网格,并调用 GPU 来渲染实际的用户界面。 创建这些网络可能非常昂贵。UI 元素应该写在组件中,以便可以

    2024年04月14日
    浏览(36)
  • unity 拖拽UI

    我们经常会使用拖拽UI的效果,untiy 为拖拽事件也提供了现成的API,我们只要简单的实现几个接口即可 我们用两种方式来实现拖拽代码,一种是使用MonoBehaviour里的方法,一种是实现UI事件接口,但不论是那种方法,拖拽的逻辑都是没有区别的。以下为拖拽核心代码 实现一:使

    2024年02月11日
    浏览(44)
  • Unity UI规范

    参考自:Unity 程序员UI编码规范 - 知乎 (zhihu.com) 大部分情况下,我们一套UI,能基本全部适配好,Unity UI让建立一个可以适应不同分辨率和宽高比屏幕调整位置和缩放UI很简单。然而,一种设计不总适合所有平台,所以创建多种版本的UI(或者说部分UI)来让每个设备上都有最佳

    2024年03月17日
    浏览(47)
  • Unity UI——UGUI

    包名: com.unity.ugui Canvas :   容纳所有UI元素的区域。   一种带有画布组件的游戏对象。   使用EventSystem对象来协助消息系统。 绘制顺序: 按照在 Hierarchy 中显示的顺序绘制,由上到下。 如果两个 UI 元素重叠,则后一个元素将显示在前一个元素之上 渲染模式:(Render Mode)

    2024年04月28日
    浏览(40)
  • Unity学习记录——UI设计

    ​ 本文是中山大学软件工程学院2020级3d游戏编程与设计的作业8 1.相关资源 ​ 本次项目之中的人物模型来自Starter Assets - Third Person Character Controller | 必备工具 | Unity Asset Store ​ 此处使用了以下路径的 PlayerArmature 预制,这个预制人物模型可以进行行走奔跑跳跃等动作,很适合

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包