参考了文章https://blog.youkuaiyun.com/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;
}
}