文章目录
- 前言
- 整套框架分为三大部分
- 素材
- 效果
- 框架代码
- 调用
- 源码
- 参考
- 完结
前言
开发一款游戏美术成本是极其高昂的,以我们常见的宣传片CG为例,动辄就要成百上千万的价格,因此这种美术物料一般只会放在核心剧情节点,引爆舆论,做高潮展示!
而另外一种表意方武:则是通过玩法设计,层层引导玩家深入探索游戏世界,这里则需要策划的精心设计和程序的秃头爆肝,因此对于绝大多数游戏而言,选择UI来进行剧情展示、玩法交互和核心表达才是最物美价廉的选择。
unity在4.6版本之后,引入了自己的界面显示系统,全称unity graphic user interface,即我们所熟知的ugui。
毕竟是unity的亲儿子,这个系统一经推出,就与其灵活快速可视化,迅速抢占用户市场,逐渐成为unity ui的主流系统,但是它也并不是完美的,对于开发人员来说,使用这套系统往往需要面对如下困境,比如缺乏跨场景的u管理器,界面的上下层关系紊乱三,界面之间的通信手段贫乏等等,上述几个问题大大影响到我们的开发效率。
上述几个问题大大影响到我们的开发效率,因此针对上述问题,我在此分享一套简单易用的框架,这套框架是b站up小棋参考了网上的大量资料,并结合个人工作经验,一个代码一个代码敲出来的,绝对是良心干货,所以废话少说,让我们开始吧!
整套框架分为三大部分
在游戏运行时,我们会把界面配置关系配置在UIManager中,当我们创建好了一个界面,比如用户列表界面,那么我们就给这个界面取一个名,并且把它放在prefab下的一个文件夹,并且配置在这个配置关系表中,后面我们在新创建一些界面,比如菜单界面,也可以把它配置在这个界面关系配置表中
我总共使用了三个界面来举例,最后一个界面是创建新用户的一个界面,总共配了三个配置关系,包含名称、路径和预制体,比如下图
素材
效果
配置完成后,我们给UIManager提供两个最重要的方法,一个是OpenPanel
和ClosePanel
,用于打开界面和关闭界面,介绍完框架的设计
我们就可以开始书写代码了
打开游戏编辑器,我们首先在一个空场景中创建canvas画布,并且将其参数设置为合适的范围和类型,这个主要根据自己项目来设置
接着我们使用工程中的ui素材拼接界面,我这里分了如下几个界面,主菜单界面,用户列表界面和新用户界面等等,最后把这些界面拖拽到resources下的某个目录,将其制作成预制件执行
加入代码后,最终的运行效果就是这样的,默认只有一个Canvas组件
框架代码
UIConst.cs
// 用户界面路径
public class UIConst
{public const string MainPanel = "主界面";public const string UserListPanel = "用户列表";public const string UserAddPanel = "添加用户弹窗";
}
UIManager.cs
using System.Collections.Generic;
using UnityEngine;// 用户界面管理器
public class UIManager
{// 单例模式的实例private static UIManager _instance;// 用户界面的根节点private Transform _uiRoot;// 预制件缓存字典private Dictionary<string, GameObject> prefabDict;// 已打开界面的缓存字典public Dictionary<string, BasePanel> panelDict;// 获取单例模式的实例public static UIManager Instance{get{if (_instance == null){_instance = new UIManager();}return _instance;}}// 获取用户界面的根节点public Transform UIRoot{get{if (_uiRoot == null){if (GameObject.Find("Canvas")){_uiRoot = GameObject.Find("Canvas").transform;}else{_uiRoot = new GameObject("Canvas").transform;}};return _uiRoot;}}// 用户界面管理器的构造函数private UIManager(){InitDicts();}// 初始化字典private void InitDicts(){prefabDict = new Dictionary<string, GameObject>();panelDict = new Dictionary<string, BasePanel>();}// 打开面板public BasePanel OpenPanel(string name){BasePanel panel = null;// 检查是否已打开if (panelDict.TryGetValue(name, out panel)){Debug.Log("界面已打开: " + name);return null;}// 检查路径是否配置string path = name;// 使用缓存预制件GameObject panelPrefab = null;if (!prefabDict.TryGetValue(name, out panelPrefab)){string realPath = "Prefabs/Panel/" + path;Debug.Log(realPath);panelPrefab = Resources.Load<GameObject>(realPath) as GameObject;prefabDict.Add(name, panelPrefab);}// 打开界面GameObject panelObject = GameObject.Instantiate(panelPrefab, UIRoot, false);panel = panelObject.GetComponent<BasePanel>();panelDict.Add(name, panel);panel.OpenPanel(name);return panel;}// 关闭面板public bool ClosePanel(string name){BasePanel panel = null;if (!panelDict.TryGetValue(name, out panel)){Debug.Log("界面未打开: " + name);return false;}panel.ClosePanel();// panelDict.Remove(name);return true;}
}
BasePanel.cs
using UnityEngine;public class BasePanel : MonoBehaviour // 基础面板类,继承自MonoBehaviour
{protected bool isRemove = false; // 是否移除,默认为否protected new string name; // 面板名称public virtual void SetActive(bool active) // 设置面板活动状态{gameObject.SetActive(active); // 设置游戏对象活动状态}public virtual void OpenPanel(string name) // 打开面板方法{this.name = name; // 设置面板名称SetActive(true); // 设置面板为活动状态}public virtual void ClosePanel() // 关闭面板方法{isRemove = true; // 设置移除状态为是SetActive(false); // 设置面板为非活动状态Destroy(gameObject); // 销毁游戏对象if (UIManager.Instance.panelDict.ContainsKey(name)) // 如果UI管理器的面板字典包含该面板{UIManager.Instance.panelDict.Remove(name); // 从字典中移除该面板}}
}
调用
以我视频中所示的这些界面为例,每一个界面我都会给他们挂接上一个脚本,这些脚本继承自BasePanel
,比如在主菜单界面,当我点击修改用户时,则会弹出用户列表的这个界面,这时候我只需要调用UIManager.Instance.OpenPanel,然后打开这个界面即可
public void OnBtnChangeUser()
{print("OnBtnChangeUser");UIManager.Instance.OpenPanel(UIConst.UserPanel);
}
关闭界面,也是类似的道理,只要调用close panel即可
public void OnBtnCancel(){print("OnBtnRename");ClosePanel();
}
源码
https://gitcode.net/unity1/unity-ui-frame
参考
【视频】https://www.bilibili.com/video/BV1zT411b7L3/
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,以便我第一时间收到反馈,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~