一个弧形滑动条的制作

参考了文章https://blog.csdn.net/shenmifangke/article/details/53582505,在该文的基础上进行了修改。滑动滑动条c#调用Lua事件,Lua下可通过响应方法给滑动条赋值。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XLua;
using System;

[LuaCallCSharp]
public class ArcSlider : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    [System.Serializable]
    // 各个档位的位置信息
    public class ButtonPos
    {
        public Vector3 pos;     // 
        public Vector3 rotate;
        public float angle;
    }

    public Image handleButton;
    float circleRadius = 0.0f;

    bool isPointerDown = false;
    public Image baseCircle;

    //忽略圈内的交互

    public float ignoreInTouchRadiusHandleOffset = 10;


    [Tooltip("初始角度到终止角度")]
    public float firstAngle = 30;
    public float secondAngle = 150;

    public float _tempAngle = 30;//用来缓动

    public float CurAngle {
        get {
            return _tempAngle;
        }
        set
        {
            
            _tempAngle = value;
            SetAngle(value);
        }
    }

    public float waitSeconds = 3f;

    public List<ButtonPos> ButtonPosList;

    Coroutine m_coroutine = null;
    private Action _waitLuaCall = null;

    [CSharpCallLua]
    public Action WaitLuaCall
    {
        get { return _waitLuaCall; }
        set {
            _waitLuaCall = value;
            m_coroutine = StartCoroutine(PointerExit());
        }
    }

    [CSharpCallLua]
    public Action<float> angleChangeCall = null;


    private RectTransform m_btnRect = null;

    public void Start()
    {
        InitCircleRadius();
    }

    private void InitCircleRadius()
    {
        if (m_btnRect == null)
        {
            m_btnRect = handleButton.GetComponent<RectTransform>();
        }
        if (circleRadius == 0)
        {
            circleRadius = Mathf.Sqrt(Mathf.Pow(m_btnRect.localPosition.x, 2) + Mathf.Pow(m_btnRect.localPosition.y, 2));
            ignoreInTouchRadiusHandleOffset = circleRadius - ignoreInTouchRadiusHandleOffset;
        }
    }

    public void SetBtnPos(int index)
    {
        ButtonPos info = ButtonPosList[index];
        m_btnRect.localEulerAngles = info.rotate;
        m_btnRect.anchoredPosition3D = info.pos;

    }

    public void SetRoundSlider(int index, float step)
    {
        ButtonPos startPos = ButtonPosList[index];
        ButtonPos endPos = ButtonPosList[index + 1];
        float angle = (endPos.angle - startPos.angle) * step;
        CurAngle = angle + startPos.angle;
    }

    private void SetAngle(float angle)
    {
        InitCircleRadius();
        m_btnRect.localPosition = new Vector3(Mathf.Cos(-angle / Mathf.Rad2Deg + 45.0f * Mathf.PI) * circleRadius, Mathf.Sin(-angle / Mathf.Rad2Deg + 45.0f * Mathf.PI) * circleRadius, 0);
        handleButton.transform.localEulerAngles = new Vector3(0, 0, secondAngle - _tempAngle + firstAngle);
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        StartCoroutine("TrackPointer");
    }

    //如果需要移动到外部时仍然有效可以去掉这里的
    public void OnPointerExit(PointerEventData eventData)
    {
        StopCoroutine("TrackPointer");
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        isPointerDown = true;
        if (m_coroutine != null)
        {
            StopCoroutine(m_coroutine);
            m_coroutine = null;
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        isPointerDown = false;
        if (m_coroutine != null)
        {
            StopCoroutine(m_coroutine);
            m_coroutine = null;
        }
        m_coroutine = StartCoroutine(PointerExit());
    }

    IEnumerator PointerExit()
    {
        yield return new WaitForSeconds(waitSeconds);
        if (_waitLuaCall != null)
        {
            _waitLuaCall();
        }
        angleChangeCall = null;
        yield return 0;
    }

    IEnumerator TrackPointer()
    {
        var ray = GetComponentInParent<GraphicRaycaster>();
        var input = FindObjectOfType<StandaloneInputModule>();

        //var text = GetComponentInChildren<Text>();

        if (ray != null && input != null)
        {
            while (Application.isPlaying)
            {
                //这个是左侧的
                if (isPointerDown)
                {
                    Vector2 localPos;
                    //获取鼠标当前位置out里赋值
                    RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, Input.mousePosition, ray.eventCamera, out localPos);

                    localPos.x = -localPos.x;

                    //半径
                    float mouseRadius = Mathf.Sqrt(localPos.x * localPos.x + localPos.y * localPos.y);

                    //阻止圆内部点击的响应,只允许在一个圆环上进行响应
                    if (mouseRadius > ignoreInTouchRadiusHandleOffset)// && handleButton.GetComponent<RectTransform>().localPosition.x <= 0
                    {
                        //0-180  -180-0偏移后的角度 从第一象限校正到0-360
                        float angle = (Mathf.Atan2(localPos.y, localPos.x)) * Mathf.Rad2Deg;
                        if (angle < 0) angle = 360 + angle; ;

                        if (angle < firstAngle) angle = firstAngle;
                        if (angle > secondAngle) angle = secondAngle;

                        angle = (_tempAngle + angle) / 2f;
                        _tempAngle = angle;

                        CurAngle = angle;
                        if (angleChangeCall != null)
                        {
                            angleChangeCall(angle);
                        }
                    }
                }
                yield return 0;
            }
        }
    }


    private void OnDisable()
    {
        isPointerDown = false;
        _waitLuaCall = null;
        angleChangeCall = null;
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值