【Unity3D-UGUI应用篇】(三)使用UGUI实现层级菜单
推荐阅读
- CSDN主页
- GitHub开源地址
- Unity3D插件分享
- 简书地址
- 我的个人博客
- QQ群:1040082875
大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
一、前言
前段时间分享了UGUI的每个组件的属性和使用方法,比如Text、Button、Image、Toggle、InputField、ScrollView等等。
接着分享了UGUI的一些原理,比如说UGUI的渲染模式、UGUI的缩放计算、UGUI的描点定位、UGUI的自动布局等等。
相信大家看完后会对UGUI有一个比较全面的认识了。
下面,就继续分享UGUI的UI组件进行应用的实例。
这是本系列文章的第三篇:
【Unity3D-UGUI应用篇】(一)使用Text实现进度等待动画
【Unity3D-UGUI应用篇】(二)使用Image实现进度条动画
【Unity3D-UGUI应用篇】(三)使用UGUI实现层级菜单
【Unity3D-UGUI应用篇】(四)使用UGUI弹窗显示模型及弹窗模型交互
【Unity3D-UGUI应用篇】(五)使用Button完成鼠标移动到UI上面显示文字功能
【Unity3D-UGUI应用篇】(六)屏幕自适应(多分配率适配)
【Unity3D-UGUI应用篇】(七)UGUI实现窗口的自由拖拽
【Unity3D-UGUI应用篇】(八)Image实现画线、画三角形、画正方形、画圆
二、介绍及效果图
层级菜单在Unity中用到的并不多,主要是做分类的时候用的比较多,今天就给大家分享几个层级代码,扩充一下,写成插件也是不错的。
首先看一下效果吧。
第一种效果:
第二种效果:
第三种效果:
第四种效果:
第五种效果:
源文件:
源文件下载
Github下载地址:
LayerMenu.unitypackage
三、实现
第一种实现效果
实现原理:
这个是用系统自带的UGUI Scroll View组件,脚本控制创建父物体,父物体身上挂载有初始化子物体的脚本
优缺点:
优点是实现简单,不需要多与的插件,代码量也不大,控制比较方便
缺点是只能实现两个层级的显示
实现过程:
1、新建一个Scrpll View
2、制作预制体
界面就这么设计就行:
名字改一下
Content:父节点容器
ParentMenu:父节点
TextParent:父节点文本
ChildMenu:子节点容器
item:子节点
TextChild:子节点文本
然后将父节点改名字叫parentMenu,做成预制体:
预制体放到Resources文件夹中:
将子物体也制作成预制体:
3、编写脚本ParentMenu.cs
这个脚本主要是作用是创建子物体:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;public class ParentMenu : MonoBehaviour
{private GameObject childMenu;//子菜单的parentprivate RectTransform[] childs;//所有子菜单的rectprivate RectTransform itemRect;//子菜单的prefabprivate Vector3 offset;//单个子菜单的高度private int count;//子菜单的个数public bool isOpening { get; private set; }//父菜单是否展开public bool isCanClick { get; set; }//父菜单是否可以点击public void Init(RectTransform rect, int count){//找到子节点childMenu = transform.Find("childMenu").gameObject;itemRect = rect;this.count = count;childs = new RectTransform[this.count];offset = new Vector3(0, itemRect.rect.height);for (int i = 0; i < this.count; i++){childs[i] = Instantiate(itemRect, childMenu.transform);}childMenu.gameObject.SetActive(false);isOpening = false;isCanClick = true;GetComponent<Button>().onClick.AddListener(OnButtonClick);}void OnButtonClick(){if (!isCanClick) return;if (!isOpening)StartCoroutine(ShowChildMenu());elseStartCoroutine(HideChildMenu());}IEnumerator ShowChildMenu(){childMenu.gameObject.SetActive(true);for (int i = 0; i < count; i++){childs[i].localPosition -= i * offset;yield return new WaitForSeconds(0.1f);}isCanClick = true;isOpening = true;}IEnumerator HideChildMenu(){for (int i = count - 1; i >= 0; i--){childs[i].localPosition += i * offset;yield return new WaitForSeconds(0.1f);}childMenu.gameObject.SetActive(false);isCanClick = true;isOpening = false;}
}
4、编写脚本FoldableMenu.cs
这个脚本主要是为了创建父物体,以及控制折叠菜单
using System.Collections;
using UnityEngine;
using UnityEngine.UI;public class FoldableMenu : MonoBehaviour
{private RectTransform content;//父物体的parentprivate TextAsset textAsset;//所有菜单信息private RectTransform parentRect;//父菜单的prefabprivate RectTransform[] parentArr;//所有父菜单的数组private RectTransform childRect;//子菜单的prefabprivate Vector3 parentOffset;//单个父菜单的高度private Vector3 childOffset;//单个父菜单的高度private int[] cntArr;//所有父菜单拥有的子菜单个数void Awake(){Init();}void Init(){//获取到父节点content = transform.Find("Viewport/Content").GetComponent<RectTransform>();//获取到menuinfo里面的信息 3 3 4 4 5 5textAsset = Resources.Load<TextAsset>("menuInfo");//获取到父物体 设置父物体的高度parentRect = Resources.Load<RectTransform>("parentMenu");parentOffset = new Vector3(0, parentRect.rect.height);//获取到子物体 设置子物体的高度childRect = Resources.Load<RectTransform>("item");childOffset = new Vector3(0, childRect.rect.height);//分割字符串 info = 3 3 4 4 5 5var info = textAsset.text.Split(',');//获取子菜单个数信息//数组的长度cntArr = new int[info.Length];//父菜单的数组parentArr = new RectTransform[info.Length];//初始化content高度 宽度不变 高度是所有父物体的总长content.sizeDelta = new Vector2(content.rect.width, parentArr.Length * parentRect.rect.height);//i = 6for (int i = 0; i < cntArr.Length; i++){//创建服务器parentArr[i] = Instantiate(parentRect, content.transform);//坐标为 上一个父物体的宽度parentArr[i].localPosition -= i * parentOffset;//赋值cntArr[i] = int.Parse(info[i]);//父物体上面加载子物体 子物体数量为3 3 4 4 5 5parentArr[i].GetComponent<ParentMenu>().Init(childRect, cntArr[i]);int j = i;//父物体上面的button绑定事件parentArr[i].GetComponent<Button>().onClick.AddListener(() => { OnButtonClick(j); });}}void OnButtonClick(int i){//如果iscanclick为false则return 因为已经点击过了 不能再点击了 除非升起来的时候将isCanClick改为trueif (!parentArr[i].GetComponent<ParentMenu>().isCanClick)return;parentArr[i].GetComponent<ParentMenu>().isCanClick = false;//isopening 为true 执行 menuup 为flase执行menuDownif (!parentArr[i].GetComponent<ParentMenu>().isOpening)StartCoroutine(MenuDown(i));elseStartCoroutine(MenuUp(i));}IEnumerator MenuDown(int index){ for (int i = 0; i < cntArr[index]; i++){//更新content高度content.sizeDelta = new Vector2(content.rect.width,content.rect.height + childOffset.y);for (int j = index + 1; j < parentArr.Length; j++){parentArr[j].localPosition -= childOffset;}yield return new WaitForSeconds(0.1f);} }IEnumerator MenuUp(int index){for (int i = 0; i < cntArr[index]; i++){//更新content高度content.sizeDelta = new Vector2(content.rect.width,content.rect.height - childOffset.y);for (int j = index + 1; j < parentArr.Length; j++){parentArr[j].localPosition += childOffset;}yield return new WaitForSeconds(0.1f);}}
}
将这个脚本挂载到Scroll View上面:
运行,搞定!
第二种实现效果
实现原理:
这个也是用UGUI做的,不一样的是不需要容器组件,主要是寻找父节点,然后保存父节点的信息,下一个节点以父节点为目标进行偏移,或者以父节点为目标做子节点
优缺点:
优点是代码清晰,可扩展性强,不需要设计UGUI
缺点结构比较简单,没有实现多层级的功能
实现过程:
1、创建预制体
结构比较简单,两个Image,箭头的图片带Button组件(可以下拉和合并)
然后将预制体放到Resources文件夹中:
2、编写PublicData.cs脚本
一个数据类
using UnityEngine;public class PublicData
{public static Transform parent;public static Vector2 currentPosition;
}
3、编写脚本Options_Triangle.cs
初始化子节点的函数
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Options_Triangle : MonoBehaviour
{public Button triangle;public Image content;public List<Transform> children = new List<Transform>();void Start(){triangle.onClick.AddListener(() =>{if (triangle.transform.eulerAngles.z == 270){triangle.transform.eulerAngles = Vector3.zero;for (int i = 0; i < children.Count; i++){children[i].gameObject.SetActive(false);}}else{triangle.transform.eulerAngles = new Vector3(0, 0, -90);for (int i = 0; i < children.Count; i++){children[i].gameObject.SetActive(true);}}});}
}
4、编写ClickEvent.cs
这是一个层级菜单的编辑功能的脚本
using UnityEngine;
using UnityEngine.UI;public class ClickEvent : MonoBehaviour
{public Button add_options_t;public Button add_options;public Transform canvasParent;void Start(){add_options_t.onClick.AddListener(() =>{if (PublicData.parent == null){PublicData.parent = Instantiate(Resources.Load<Transform>("Options_triangle"));PublicData.parent.transform.SetParent(canvasParent, false);PublicData.currentPosition = new Vector2(PublicData.parent.position.x, PublicData.parent.position.y);}else{Transform option = Instantiate(Resources.Load<Transform>("Options_triangle"));option.transform.SetParent(PublicData.parent, false);option.transform.position = new Vector3(PublicData.currentPosition.x + 30, PublicData.currentPosition.y - 32, 0);PublicData.parent.GetComponent<Options_Triangle>().triangle.transform.eulerAngles = new Vector3(0, 0, -90);PublicData.parent.GetComponent<Options_Triangle>().children.Add(option);PublicData.parent = option;PublicData.currentPosition = new Vector2(PublicData.parent.position.x, PublicData.parent.position.y);}});add_options.onClick.AddListener(() =>{if (PublicData.parent == null){return;}PublicData.parent.GetComponent<Options_Triangle>().triangle.transform.eulerAngles = new Vector3(0, 0, -90);Transform content = Instantiate(Resources.Load<Transform>("Options"));content.transform.SetParent(PublicData.parent, false);content.transform.position = new Vector3(PublicData.currentPosition.x + 16, PublicData.currentPosition.y - 32, 0);PublicData.parent.GetComponent<Options_Triangle>().children.Add(content);PublicData.currentPosition = new Vector2(content.position.x - 16, content.position.y);});}
}
OK。将ClickEvent脚本挂载在场景中的任一物体身上就可以了
第三种实现效果
实现原理:
这个也是用UGUI做的,比较有特点的地方是没有使用一行代码,使用VerticalLayoutGroup和ContentSizeFitter组件的自动排序功能和Button的OnClick组件控制子物体的显示与隐藏来实现层级菜单的功能。
优缺点:
优点是不需要代码控制,简单易用
缺点是需要提前堆砌UI,工作量比较大,然后改动的时候耗费精力大
实现过程:
1、新建Scroll View
2、父节点
父节点有一个Button和一个隐藏的Image
Button
有两个功能
第一个就是显示跟自己位置坐标一样的子物体BtnSelecteStyle,因为BtnSelecteStyle是Button的子物体,所以BtnSelecteStyle就会挡住Button,为啥要挡住呢,因为还需要BtnSelecteStyle的OnClick将子节点收起来
BtnSelecteStyle的OnClick挂载的功能:
第二个就是显示子节点的容器也就是ImgBtnParentLayout
这个ImgBtnParentLayout就是子节点的容器
下面是几个子节点
OK。可以了
第四种实现效果
实现原理:
这个是用代码动态生成的,其中一个脚本主要用来创建父物体和子物体,以及父级关系,另一个脚本是设置位置,箭头变化,按钮功能的初始化
优缺点:
优点是代码清晰,结构明了,可以实现层级多级显示、多级目录的设置、树级菜单等
缺点是没有判断最后一个节点的代码,最后一个节点无法设置图片,最后一个节点的功能没有添加
实现过程:
1、首先也是制作预制体
ArrowButton和ArrowButton2都是为了控制子节点的关闭和显示,不同的是ArrowButton是左边的小按钮,还有一个图片显示的功能,ArrowButton2是整体的按钮,不显示,但是点击整体都可以实现显示和隐藏子节点的功能
资源:
图片是白的,仔细看一下还是能看到的 - -,然后保存下载,放到项目中去
2、编写脚本ItemPanelBase.cs
这个脚本是设置节点的位置,以及箭头切换的脚本
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public enum NameSort
{Default,Active,Passive
}
public class ItemPanelBase : MonoBehaviour
{private List<ItemPanelBase> childList;//子物体集合[HideInInspector]public Button downArrow;//下箭头按钮public Button downArrow2;//下箭头按钮public Sprite down, right, dot;public bool isOpen { get; set; }//子物体开启状态private Vector2 startSize;//起始大小NameSort m_NameSore = NameSort.Default;string m_Name;private void Awake(){childList = new List<ItemPanelBase>();downArrow = this.transform.Find("ContentPanel/ArrowButton").GetComponent<Button>();downArrow.onClick.AddListener(() =>{if (isOpen){CloseChild();isOpen = false;}else{OpenChild();isOpen = true;}});downArrow2 = this.transform.Find("ContentPanel/ArrowButton2").GetComponent<Button>();downArrow2.onClick.AddListener(() =>{if (isOpen){CloseChild();isOpen = false;}else{OpenChild();isOpen = true;}});startSize = this.GetComponent<RectTransform>().sizeDelta;isOpen = false;}//添加子物体到集合private void AddChild(ItemPanelBase parentItemPanelBase){childList.Add(parentItemPanelBase);if (childList.Count >= 1){downArrow.GetComponent<Image>().sprite = right;}}//设置当前对象的名字值public void SetName(string _name,NameSort m_sort){m_Name = _name;m_NameSore = m_sort;}/// <summary>/// 设置父物体,父物体不为一级菜单/// </summary>/// <param name="parentItemPanelBase"></param>public void SetItemParent(ItemPanelBase parentItemPanelBase){this.transform.parent = parentItemPanelBase.transform;parentItemPanelBase.AddChild(this);this.GetComponent<VerticalLayoutGroup>().padding = new RectOffset((int)parentItemPanelBase.downArrow.GetComponent<RectTransform>().sizeDelta.x, 0, 0, 0);if (parentItemPanelBase.isOpen){this.GetComponent<ItemPanelBase>().AddParentSize((int)this.gameObject.GetComponent<RectTransform>().sizeDelta.y);}else{this.transform.gameObject.SetActive(false);}}/// <summary>/// 设置父物体,父物体为一级菜单/// </summary>/// <param name="tran"></param>public void SetBaseParent(Transform tran){this.transform.parent = tran;}/// <summary>/// 填充Item数据/// </summary>/// <param name="_name">名字</param>public void InitPanelContent(string _name){transform.Find("ContentPanel/Text").GetComponent<Text>().text = _name;}/// <summary>/// 增加一个子物体后更新Panel大小/// </summary>/// <param name="change"></param>public void UpdateRectTranSize(int change){this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(startSize.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y + change);}/// <summary>/// 增加父物体高度/// </summary>/// <param name="parentItem"></param>/// <param name="change"></param>public void AddParentSize(int change){if (this.transform.parent.GetComponent<ItemPanelBase>() != null){this.transform.parent.GetComponent<ItemPanelBase>().UpdateRectTranSize(change);this.transform.parent.GetComponent<ItemPanelBase>().AddParentSize(change);}}/// <summary>/// 关闭子物体列表/// </summary>public void CloseChild(){if (childList.Count == 0) return;foreach (ItemPanelBase child in childList){child.gameObject.SetActive(false);child.GetComponent<ItemPanelBase>().AddParentSize(-(int)child.gameObject.GetComponent<RectTransform>().sizeDelta.y);}downArrow.GetComponent<Image>().sprite = right;}/// <summary>/// 打开子物体列表/// </summary>public void OpenChild(){if (childList.Count == 0){if (m_Name == "125K读卡器" && m_NameSore == NameSort.Active){Debug.Log("125k设备");}return;}foreach (ItemPanelBase child in childList){child.gameObject.SetActive(true);child.GetComponent<ItemPanelBase>().AddParentSize((int)child.gameObject.GetComponent<RectTransform>().sizeDelta.y);}downArrow.GetComponent<Image>().sprite = down;}
}
3、编写脚本PullDownList.cs
这个就是创建层级菜单的脚本:
比较繁琐
using System.Collections.Generic;
using UnityEngine;public class PullDownList : MonoBehaviour
{private List<GameObject> itemPanelList;public GameObject itemPanel;private void Awake(){itemPanelList = new List<GameObject>();}void Start(){for (int i = 0; i < 27; i++){//一级菜单if(i == 0){GameObject newItemPanel = Instantiate(itemPanel);itemPanelList.Add(newItemPanel);newItemPanel.GetComponent<ItemPanelBase>().SetBaseParent(this.transform);newItemPanel.GetComponent<ItemPanelBase>().InitPanelContent("层级一");}//二级菜单if (i == 1){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[0].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级二");}else if (i == 2){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[0].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级二");}//三级菜单else if (i == 3){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 4){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 5){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 6){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 7){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 8){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 9){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}else if (i == 10){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");}//四级菜单else if (i == 11){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[3].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 12){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[3].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 13){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[4].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 14){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[4].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 15){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[5].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 16){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[5].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 17){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[6].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 18){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[6].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);}else if (i == 19){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[7].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 20){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[7].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 21){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[8].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 22){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[8].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 23){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[9].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 24){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[9].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 25){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[10].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}else if (i == 26){GameObject newItemPanel2 = Instantiate(itemPanel);itemPanelList.Add(newItemPanel2);newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[10].GetComponent<ItemPanelBase>());newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);}}}
}
将脚本挂载在Panel上面
OK,大功告成
第五种实现效果
实现原理:
这个是用UI硬堆砌起来的层级菜单,然后通过代码控制对象的隐藏和显示,即可实现层级菜单的折叠与下拉功能,主要用到GridLayoutGroup组件来排序与更新
优缺点:
优点是操作简单,代码也简单,不需要太多的理解,然后可以显示多级菜单,多级内容,以及最后一个节点的功能与图片的设置功能
缺点是需要提前堆砌UI,可扩容性差,前期工作量大,然后后期修改工作量大,最重要的是我觉得这种实现方式蛮low的
实现过程:
1、显示制作UI
Panel上面挂载GridLayoutGroup组件
制作UI
UI的话就很简单,一个Button下面两个子物体一个text一个Image,text是显示内容,image是显示箭头
这时候就有人问了,那子物体怎么办,子物体也是同样的结构
就是把image往后拉了一下
三级菜单也一样:
再加一个一级菜单:
是不是so easy…哈哈哈 真的好low
脚本功能就很简单
一级菜单控制它往下的所有子节点的隐藏于显示
二级菜单控制它往下的所有子节点的隐藏于显示
以此类推。。。。
2、编辑代码PullDown.cs
using UnityEngine;
using UnityEngine.UI;public class PullDown : MonoBehaviour
{public Button m_Btn1;//一级菜单按钮public Button m_Btn2;//二级菜单按钮public Button m_Btn3;//三级菜单按钮bool m_is1;//全局参数 控制开关bool m_is2;//全局参数 控制开关void Start(){m_is1 = true;m_is2 = true;m_Btn1.onClick.AddListener(Btn1_Event);m_Btn2.onClick.AddListener(Btn2_Event);}public void Btn1_Event(){if (m_is1){m_Btn2.gameObject.SetActive(false);m_Btn3.gameObject.SetActive(false);m_is1 = false;}else{m_Btn2.gameObject.SetActive(true);m_Btn3.gameObject.SetActive(true);m_is1 = true;}}public void Btn2_Event(){if (m_is2){m_Btn3.gameObject.SetActive(false);m_is2 = false;}else{m_Btn3.gameObject.SetActive(true);m_is1 = true;}}
}
OK了,快去试试吧
【Unity3D-UGUI应用篇】(三)使用UGUI实现层级菜单相关推荐
- Unity3D 优化总篇
转载[整理]unity3d优化总结篇 -- yxriyin 对项目优化有很多点,如:mesh合并 ,减少DrawCall和模型骨骼以及物理计算,合并材质球,优化代码等等, 优化: 1. 更新不透明贴图 ...
- docker omv 防火墙_我的软路由折腾之旅 篇三:在openmediavault上通过Docker实现OPENWRT旁路由功能...
我的软路由折腾之旅 篇三:在openmediavault上通过Docker实现OPENWRT旁路由功能 2020-06-20 11:28:38 57点赞 415收藏 74评论 你是AMD Yes党?还 ...
- java comparable接口_Java面试题之Java集合篇三
Java面试题之Java集合篇三1.HashMap和HashTable有何不同? (1)HashMap允许key和value为null,而HashTable不允许. (2)HashTable是同步的, ...
- 【word2vec】篇三:基于Negative Sampling 的 CBOW 模型和 Skip-gram 模型
系列文章: [word2vec]篇一:理解词向量.CBOW与Skip-Gram等知识 [word2vec]篇二:基于Hierarchical Softmax的 CBOW 模型和 Skip-gram 模 ...
- SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)
SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行) 原文:SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行) 前言 本篇继续玩转模块 ...
- 阅读书源最新2020在线导入_书源篇三及6.5.0版本介绍
书源篇三及6.5.0版本介绍 魔幻2020 魔幻的2020,开启不一样的生活状态,作为一名技术宅,不出门虽我愿,但看到空荡荡的街头,心中却有种难言的难过与害怕.我不向往繁华.但喜欢车马如龙,街灯繁华. ...
- Android日志[进阶篇]三-Logcat 命令行工具
Android日志[进阶篇]一-使用 Logcat 写入和查看日志 Android日志[进阶篇]二-分析堆栈轨迹(调试和外部堆栈) Android日志[进阶篇]三-Logcat命令行工具 Androi ...
- 圆形界面 开启相机_「基础篇三」手机摄影拍照界面详解
[基础篇三]手机摄影拍照界面详解 手机拍照对我们来说已习以为常,每天我们都会用手机相机功能或多或少的拍出几张照片.故手机拍照界面对我们来说也不陌生,但手机拍照界面上的那些按钮,那些功能你都用过吗?你 ...
- pve安装黑群晖直通硬盘_蜗牛星际装机教程篇三:手把手教你安装黑群晖NAS
原文作者:范俩仟 蜗牛星际装机教程篇三:手把手教你安装黑群晖NAS 有很多评论说软路由没必要,我想说我就是把这东西当个玩意儿来消遣的,您喜欢看电影,我就喜欢玩电子产品.还有就是我没钱,所以想花最少的钱 ...
最新文章
- 删除指定文件夹下的小于 4K的所用文件...
- 批处理清除VisualStudio解决方案文件夹
- web开发者工具,261页前端面试题宝典,通用流行框架大全
- LeetCode 333. 最大 BST 子树(递归)*
- c++ array容器 传参_C++ 顺序容器基础知识总结
- maven更换阿里云源
- 新站快速收录同时也提高内页的收录
- Cacti监控Varnish
- 随机数算法 java_最全的java随机数生成算法
- graphpad折线图教程_GraphPad Prism 8.0绘制误差连线并填充颜色图
- Unity3D水下动物模型大集合
- linux保险箱软件,手机加密App哪个好?手机加密软件推荐
- android手机电视投影,教程向 | 手机投屏激光电视操作指南
- 关于ios 卡顿检测分析
- Netty里面的Boss和Worker【Server篇】
- 第六周组会摘要工作计划与分工
- 规约——前置条件和后置条件
- 制作Retropie系统树莓派掌机(三)
- 利用js和jquary制作轮播图
- h5物体拖动_网易爆款H5 的交互方法参考