Unity 自主学习之用设计模式模拟王者荣耀(三)-- Easytouch实现技能指示器

技能指示器就是王者荣耀里面的技能按钮,这个按钮在点击之前是一个按钮的样子,但是点击之后,技能图标会缩小一定大小,并且会出现一个可以拖动的范围按钮,更joystick一样,但是经过从尝试发现单纯使用Easytouch提供的Joystick并不能够符合要求,所以我通过对其进行一下封装来实现这个技能指示器。

UI结构如下:

最外层是一个空物体,用来当作技能指示器来挂载脚本,Icon用于显示 技能图标,以及实现技能按钮缩小的效果,SkillJoystick 就是Easytouch的遥感 组件,用来实现拖动。

代码结构:

我这里的遥感的事件与其他逻辑是相互分离的,我只提供按钮 相应事件的接口, 具体实现是在其它地方,这里相当于使用了桥接者模式。​​​​​​​

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

namespace WangZhe.UI
{
    public class SkillIndicator : MonoBehaviour
    {
        private static int s_skillJoysticNum = 0;

        private ETCJoystick m_skillJoystic;
        private Image m_skillBg;
        private Image m_thumbIcon;
        private Image m_skillIcon;
        private Color m_skillBgColorShow;
        private Color m_skillBgColorHide;
        private Sprite m_skillIconSprite;
        private Sprite m_thumbIconSprite;

        #region 对外交互的数据
        public float DragDisPersent { get; private set; }
        public string Name { get; set; }
        public int ID { get; private set; }
        public Vector2 DragDir { get; private set; }
        public UnityEvent OnDrag;
        public UnityEvent OnDragEnd;
        #endregion

        private void Awake()
        {
            s_skillJoysticNum++;

            m_skillJoystic = transform.GetComponentInChildren();                         
            m_skillBg = m_skillJoystic.GetComponent();
            m_thumbIcon = m_skillJoystic.transform.Find("Thumb").GetComponent();
            m_skillIcon = transform.Find("Icon").GetComponent();
            m_skillBgColorShow = m_skillBg.color;
            m_skillBgColorHide = new Color(0, 0, 0, 0);
            m_skillIconSprite = m_skillIcon.sprite;
            m_thumbIconSprite = m_thumbIcon.sprite;

            #region 对外数据初始化
            DragDisPersent = 0;
            DragDir = Vector2.zero;
            Name = transform.name;
            ID = s_skillJoysticNum;
            #endregion

            m_skillIcon.gameObject.SetActive(false);
            m_skillBg.color = m_skillBgColorHide;
            m_thumbIcon.sprite = m_skillIconSprite;

            m_skillJoystic.onMove.AddListener(OnThumbMove);
            m_skillJoystic.onMoveEnd.AddListener(OnThumbMoveEnd);
        }

        public void OnThumbMove(Vector2 moveDir)
        {
            m_skillIcon.gameObject.SetActive(true);                                                     //显示技能图标
            m_skillBg.color = m_skillBgColorShow;                                                       //显示拖动范围背景
            m_thumbIcon.sprite = m_thumbIconSprite;                                                     //修改拖动按钮的背景
            Vector3 thumbPos = m_thumbIcon.transform.localPosition;                                     //偏移位置
            Vector3 bgPos = m_skillBg.transform.localPosition;                                          //中心点位置
            DragDisPersent = Vector3.Distance(thumbPos, bgPos) / m_skillJoystic.GetRadius();            //偏移距离除以半径得到拖动偏移的百分比
            DragDir = moveDir;                                                                          //设置位移方向
            OnDrag.Invoke();                                                                            //提供接口做处理
        }

        public void OnThumbMoveEnd()
        {
            m_skillIcon.gameObject.SetActive(false);                            //隐藏技能图标
            m_skillBg.color = m_skillBgColorHide;                               //隐藏拖动范围图标
            m_thumbIcon.sprite = m_skillIconSprite;                             //修改拖动按钮图标
            DragDisPersent = 0;                                                 //设置拖动距离百分比为0
            DragDir = Vector2.zero;                                             //设置拖动方向为0
            OnDragEnd.Invoke();                                                 //提供接口
        }
    }
}

最上面的一些数据是控制按钮本身的UI显示用的变量,还有一部分是用来与外界交互的变量(后面可能会添加一些,后面不够用了再添就是)。

初始化里面就不说了, 都是些绑定操作,最后两句就是将joystick的move 事件与函数相绑定,重点在这 两个函数里面。

 这两个函数里面主要都是对自身按钮UI显示的操作,而对外提供的接口就是OnDrag和OnDragEnd这两个委托函数,这两个使得我可以在其它地方去绑定具体的按钮事件。

使用:

这只是一个技能指示器按钮,相当于一个控制里面的 一个部分,而 王者荣耀的控制按钮中,左边的移动按钮永远是不变的,只是 右边的按钮会根据技能个数而改变,所以我讲右边的部分整体做成 一个预制体,根据技能个数来加载对应的预制体,所以控制 逻辑与实现逻辑分开是必要的。

这个使用如下:

using HedgehogTeam.EasyTouch;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using WydUtility.Extension;
using WangZhe.Battle.Charactor;
using WangZhe.UI;

namespace WangZhe.Battle.UI
{
    public enum Skill_ID
    {
        ATK,
        Skill1,
        Skill2,
        Skill3,
        Skill4
    }

    public class BattleControlPanel : MonoBehaviour
    {
        protected ETCButton m_ATKBtn;
        protected ETCJoystick m_joystick;
        protected SkillIndicator[] m_skillIndicators;

        private void Awake()
        {
            m_joystick = GameObject.Find("CharaJoystic").GetComponent();
            m_skillIndicators = transform.GetComponentsInChildren();

            if (null == m_joystick)
                Debug.LogWarningFormat("未找到遥感");

            if (m_skillIndicators.Length <= 0)
                Debug.LogWarningFormat("未找到任何技能控制器");

            m_joystick.onMove.AddListener(OnJoysticMove);
            foreach(SkillIndicator si in m_skillIndicators)
            {
                si.OnDrag.AddListener(new UnityAction(() => OnSkillStart(si)));
            }
        }

        protected virtual void OnJoysticMove(Vector2 moveDir)
        {
            PlayerSystem.Instance.PlayerMove(moveDir);
        }

        protected virtual void OnSkillStart(SkillIndicator skillIndicator)
        {
            Vector2 skillDir = skillIndicator.DragDir;
            float skillDisPercent = skillIndicator.DragDisPersent;
            PlayerSystem.Instance.SkillReleasBegin(skillDir, skillDisPercent);
        }

        protected virtual void OnSkillRelease()
        {
            
        }

        protected virtual void InitOnAwake() { }
    }
}

 

当这个按钮使用的时候回去通知PlayerSystem去实现相对应的技能效果。

效果:

Unity 自主学习之用设计模式模拟王者荣耀(三)-- Easytouch实现技能指示器_第1张图片​​​​​​​

你可能感兴趣的:(学习理解)