推荐阅读

  • 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实现层级菜单相关推荐

  1. Unity3D 优化总篇

    转载[整理]unity3d优化总结篇 -- yxriyin 对项目优化有很多点,如:mesh合并 ,减少DrawCall和模型骨骼以及物理计算,合并材质球,优化代码等等, 优化: 1. 更新不透明贴图 ...

  2. docker omv 防火墙_我的软路由折腾之旅 篇三:在openmediavault上通过Docker实现OPENWRT旁路由功能...

    我的软路由折腾之旅 篇三:在openmediavault上通过Docker实现OPENWRT旁路由功能 2020-06-20 11:28:38 57点赞 415收藏 74评论 你是AMD Yes党?还 ...

  3. java comparable接口_Java面试题之Java集合篇三

    Java面试题之Java集合篇三1.HashMap和HashTable有何不同? (1)HashMap允许key和value为null,而HashTable不允许. (2)HashTable是同步的, ...

  4. 【word2vec】篇三:基于Negative Sampling 的 CBOW 模型和 Skip-gram 模型

    系列文章: [word2vec]篇一:理解词向量.CBOW与Skip-Gram等知识 [word2vec]篇二:基于Hierarchical Softmax的 CBOW 模型和 Skip-gram 模 ...

  5. SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

    SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行) 原文:SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行) 前言 本篇继续玩转模块 ...

  6. 阅读书源最新2020在线导入_书源篇三及6.5.0版本介绍

    书源篇三及6.5.0版本介绍 魔幻2020 魔幻的2020,开启不一样的生活状态,作为一名技术宅,不出门虽我愿,但看到空荡荡的街头,心中却有种难言的难过与害怕.我不向往繁华.但喜欢车马如龙,街灯繁华. ...

  7. Android日志[进阶篇]三-Logcat 命令行工具

    Android日志[进阶篇]一-使用 Logcat 写入和查看日志 Android日志[进阶篇]二-分析堆栈轨迹(调试和外部堆栈) Android日志[进阶篇]三-Logcat命令行工具 Androi ...

  8. 圆形界面 开启相机_「基础篇三」手机摄影拍照界面详解

    ​[基础篇三]手机摄影拍照界面详解 手机拍照对我们来说已习以为常,每天我们都会用手机相机功能或多或少的拍出几张照片.故手机拍照界面对我们来说也不陌生,但手机拍照界面上的那些按钮,那些功能你都用过吗?你 ...

  9. pve安装黑群晖直通硬盘_蜗牛星际装机教程篇三:手把手教你安装黑群晖NAS

    原文作者:范俩仟 蜗牛星际装机教程篇三:手把手教你安装黑群晖NAS 有很多评论说软路由没必要,我想说我就是把这东西当个玩意儿来消遣的,您喜欢看电影,我就喜欢玩电子产品.还有就是我没钱,所以想花最少的钱 ...

最新文章

  1. 删除指定文件夹下的小于 4K的所用文件...
  2. 批处理清除VisualStudio解决方案文件夹
  3. web开发者工具,261页前端面试题宝典,通用流行框架大全
  4. LeetCode 333. 最大 BST 子树(递归)*
  5. c++ array容器 传参_C++ 顺序容器基础知识总结
  6. maven更换阿里云源
  7. 新站快速收录同时也提高内页的收录
  8. Cacti监控Varnish
  9. 随机数算法 java_最全的java随机数生成算法
  10. graphpad折线图教程_GraphPad Prism 8.0绘制误差连线并填充颜色图
  11. Unity3D水下动物模型大集合
  12. linux保险箱软件,手机加密App哪个好?手机加密软件推荐
  13. android手机电视投影,教程向 | 手机投屏激光电视操作指南
  14. 关于ios 卡顿检测分析
  15. Netty里面的Boss和Worker【Server篇】
  16. 第六周组会摘要工作计划与分工
  17. 规约——前置条件和后置条件
  18. 制作Retropie系统树莓派掌机(三)
  19. 利用js和jquary制作轮播图
  20. h5物体拖动_网易爆款H5 的交互方法参考

热门文章

  1. 代码审计之scms——search.php注入漏洞
  2. Vue封装公告信息无缝滚动展示
  3. android 隐私伪装原理,加锁、隐藏和伪装!三招严防私密App被偷看
  4. 安徽大学计算机学硕复试线,安徽大学2020年考研复试分数线
  5. CrystalDiskMark中文版
  6. 使用python批量重命名b站视频文件
  7. OpenCASCADE:OCCT应用框架OCAF之可视化属性
  8. 数据存储方式之 Excel
  9. 社区团购小程序需要服务器吗,开发社区团购小程序
  10. openGauss Summit 2021圆满落幕,海量数据助力数据库跨越式发展