初入江湖
- 麒麟币
- 31 枚
- 任务币
- 15 枚
- 威望
- 0 点
- 贡献
- 0 点
- 主题
- 1贴
- 在线时间
- 1 小时
|
本帖最后由 洛神同学 于 2020-5-29 09:43 编辑
1.为什么要有组件化思想: 楼主认为,组件就是能够满足一定功能的能够挂在到对象上面的控件,就比如unity自己封装的Transform组件、Renderer组件等,其实都是满足了一定功能的,而且组件与组件之间的联系很低,这也就是所谓的“高内聚,低耦合”。
2.如何实现组件化:
想要实现组件化,首先你要明确自己要做怎么的组件,它能够满足什么功能,它里面需要包含哪些数据等,当你清楚了,你就可以开始去写,写的过程中也可能需要写多个类来控制,但是要遵守一点,那就是你挂载到对象上的脚本只能是一个,就比如Transform组件中包含Vector3的类,却不需要挂载一样的道理;
想要写好一个组件,那就需要充分的了解这个组件的所有可能性,以下面我自己写的一个UI工具组件为例:
我的需求是:
1、点击按钮保持选中状态图标,
2、选中状态文字会改变颜色,可以保持,
3、高亮状态,文字颜色改变,
4、点击完毕能够保持状态或不保持状态。
制作这个组件需要考虑:
1、Img加文本式btn
2、RawImg加文本式btn
3、仅Text式Btn
4、仅Img式Btn
5、仅RawImg式Btn
常见的Btn也就这几种了,还有一些其他比较特殊的Btn类型,反正笔者从未用过,所以不在考虑范围内,也不作为组件考虑范围内,毕竟组件也是够用就行,太过复杂就会使得脚本过于臃肿,反而影响效率。
好了,废话不多说,开始上代码
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
- using UnityEngine.EventSystems;
- [ExecuteInEditMode]
- [RequireComponent(typeof(Button))]
- public class UIButtonState : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler , IPointerUpHandler {
- [Header("选中状态的图片")]
- public Sprite selectSprite;
- [Header("是否保持选中状态")]
- public bool isKeepSelect = true;
- [Header("高亮颜色")]
- public Color hightLightColor = new Color(0,0,0,1);
- [Header("点击颜色")]
- public Color pressColor = new Color(0, 0, 0, 1);
- [Header("需要改变颜色的文本")]
- public Text text;
- private Button m_Btn;
- private Color m_oldColor;
- private Color m_curColor;
- private Image m_Img;
- private RawImage m_RawImg;
- private Texture m_NomalRawImg;
- void Awake () {
- m_Btn = GetComponent<Button>();
- m_Img = m_Btn.GetComponent<Image>();
- m_RawImg = m_Btn.GetComponent<RawImage>();
- if (text == null) text = m_Btn.GetComponentInChildren<Text>();
- if (text) { m_oldColor = text.color; m_curColor = m_oldColor; }
- if (m_Img)
- {
- if (selectSprite == null) selectSprite = m_Btn.spriteState.pressedSprite;
- m_Btn.spriteState = new SpriteState() { highlightedSprite = m_Btn.spriteState.highlightedSprite, pressedSprite = m_Btn.spriteState.pressedSprite, disabledSprite = m_Img.sprite};
- }
- else if (m_RawImg)
- {
- if (selectSprite == null) selectSprite = m_Btn.spriteState.pressedSprite;
- m_NomalRawImg = m_RawImg.texture;
- }
- }
- public void Select()
- {
- CancelAll();
- m_Btn.enabled = false;
- if (m_Img)
- m_Img.sprite = selectSprite;
- else if (m_RawImg)
- m_RawImg.texture = selectSprite.texture;
- if (text) text.color = pressColor;
- UnityEngine.EventSystems.EventSystem.current.SetSelectedGameObject(null);
- }
- void CancelAll()
- {
- UIButtonState[] uIButtonStates = m_Btn.transform.parent.GetComponentsInChildren<UIButtonState>(true);
- for (int i = 0; i < uIButtonStates.Length; i++)
- {
- uIButtonStates.CancelSelect();
- }
- }
- public void CancelSelect()
- {
- m_Btn.enabled = true;
- if (m_Img)
- m_Img.sprite = m_Btn.spriteState.disabledSprite;
- else if (m_RawImg)
- m_RawImg.texture = m_NomalRawImg;
- if (text)
- {
- text.color = m_oldColor;
- m_curColor = m_oldColor;
- }
- }
- public void OnPointerEnter(PointerEventData eventData)
- {
- if (text && m_Btn.enabled)
- text.color = hightLightColor;
- }
- public void OnPointerExit(PointerEventData eventData)
- {
- if (text && m_Btn.enabled)
- text.color = m_curColor;
- }
- public void OnPointerUp(PointerEventData eventData)
- {
- if (!isKeepSelect)
- {
- CancelSelect();
- }
- }
- public void OnPointerDown(PointerEventData eventData)
- {
- Select();
- }
- }
[color=rgb(106, 205, 243) !important]复制代码
代码其实是比较简单的,就是定义好变量,初始化阶段通过拖拽好的3类型Btn图标,将第四种图标设置为nomalSprite,然后选中时,改变图标为选中图标,并释放UI选中(此部不可省略,原因是你选中时,对其失活后,UGUI内部仍处于悬浮状态,此时改变图标后可能会与此冲突,而显示悬浮图标),取消选中时,更改为第四种状态的Btn图标,这就是楼主的思路了,相对来说脚本的实现是相当简单了,就这样轻松的满足了需求。
考虑其组件化的意义,本来我的按钮事件完全可以以用自己模拟NGUI封装的监听脚本,通过UIListener.Get的方式来注册,但是毕竟是要当做一个组件来用的,就必须要减少与其他脚本的关联,所以就改为了UGUI自带的那么那么长的接口,虽然我也是非常的不愿意,但是没有办法,毕竟代码优化重要,其中还有好几点是可以优化的地方,但是楼主也是比较懒的人,就懒得再优化了,喜欢的可以优化一下。
如果有更好的意见,欢迎在在下方回复栏里留言,让我们一起学习,一起进步。
|
|