最近越来越觉得Unity3D的UI很好玩,所以我尝试去制作可折叠的公告牌。先上个成品图:
首先新建Canvas,在Canvas里面新建两个Panel,一个Panel用于放置背景,一个Panel用于公告牌。在公告牌的Panel里面新建3个Button和3个Image和3个Text。具体设置如图
然后新建一个空物体命名为BoardManager,挂上脚本BoardManager.cs,用于控制公告的显示,折叠式公告牌原理是点击按钮,使Image(公告)为active,通过2D刚体碰撞,让其他按钮向下移。
public class BoardManager : MonoBehaviour { public void ControlBoard(GameObject obj) { bool open = obj.GetComponent<Board>().Open; open = !open; obj.GetComponent<Board>().Open = open; obj.SetActive(open);//选择激活或者灭活 } }
然后在3个Image上都挂载Board.cs,记录公告状态显示
public class Board : MonoBehaviour { public bool Open = false;//初始状态都为关 }
因为要利用在Button属性面板如图设置
因为需要利用到2D物体的碰撞,需要加入2D刚体,和2D的碰撞体,这是一个巨大无比的坑。
首先给3个Button都添加刚体和碰撞体,然后给3个图片都添加碰撞体
2D碰撞体贼坑,本来用OnCollisionEnter2D检测碰撞,但是却死活检测不到,刚体也加了,碰撞体也加了就是没卵用,百度谷歌大法都用了,也没啥用,后来幸好我点击编辑碰撞体,才发现,2D碰撞体最初是给一个点而不是一个形状,所以即使看起来碰撞了,其实只要碰撞框没重合就没有碰撞信息
然后给第二个Button加上Button2_Move.cs
public class Button2_Move : MonoBehaviour { public GameObject Panel;//公告牌面板 float x = 0;//第二个Button初始位置x float y = 25;//第二个Button初始位置y float cur_x;//第二个Button当前位置 float cur_y;//第二个Button当前位置 void Start() { cur_x = x;// cur_y = y;//初始化当前位置x,y } // Update is called once per frame void Update() { if (Panel.transform.FindChild("Image1").gameObject.activeSelf == false) { Return0();//如果第一个公告不显示就退回起始点 } Panel.transform.FindChild("Image2").gameObject.GetComponent<RectTransform>().localPosition = new Vector3(cur_x, cur_y - 155, 0);//实时更新Image2的位置保证它是跟在按钮2下方 } void Return0() { GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);//返回 cur_y = y;//记录当前位置 } void OnCollisionEnter2D(Collision2D coll) { RectTransform coll_Tranform = coll.gameObject.GetComponent<RectTransform>(); GetComponent<RectTransform>().localPosition = new Vector3(x, y - coll_Tranform.sizeDelta.y, 0);//位置改为x不变,y加上碰撞Image的height cur_y = y - coll_Tranform.sizeDelta.y;//记录当前位置 } }然后为第三个Button加上Button3_Move.cs。本来按道理将button的行为应该一样,可是考虑到Button3比Button2多了一个可能位置,然后我也暂时没想到优化的办法,先将就着吧。
public class Button3_Move : MonoBehaviour { public GameObject Panel; float cur_x; float cur_y;//当前位置的x,y float x = 0; float y = -95;//初始位置的x,y float x1 = 0; float y1 = -299;//中间位置的x,y void Start() { cur_x = x; cur_y = y; } // Update is called once per frame void Update() { Panel.transform.FindChild("Image3").gameObject.GetComponent<RectTransform>().localPosition = new Vector3(cur_x, cur_y - 165, 0);//实时更新Image3,保证Image3在Button3下方 if (Panel.transform.FindChild("Image1").gameObject.activeSelf == true) { if(Panel.transform.FindChild("Image2").gameObject.activeSelf == false) { Return2();//当第一个公告牌打开,第二个隐藏时 } } else { if (Panel.transform.FindChild("Image2").gameObject.activeSelf == false) { Return1();//当两个公告牌都隐藏时 } } } void Return1() { GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0); cur_y = y;//记录当前位置 } void Return2() { GetComponent<RectTransform>().localPosition = new Vector3(x1, y1, 0); cur_y = y1;//记录当前位置 } void OnCollisionEnter2D(Collision2D coll) { RectTransform coll_Tranform = coll.gameObject.GetComponent<RectTransform>(); Debug.Log(coll.gameObject.name); GetComponent<RectTransform>().localPosition = new Vector3(cur_x, cur_y - coll_Tranform.sizeDelta.y, 0);//位置下移 cur_y = cur_y - coll_Tranform.sizeDelta.y;//记录当前位置 } }至于第二个公告牌的滚动字幕则是用了Mask和动画录制后的效果,其他额外效果都是动画录制播放
公告牌就到这了下期再见
有兴趣可以去我的Github看可折叠公告牌
