鸟语天空
UGUI—赛车游戏方向盘摇杆
post by:追风剑情 2022-7-6 17:59

using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
/// <summary>
/// 方向盘
/// 通过左右滑动控制转向
/// </summary>
public class UISteeringWheel : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
    //约束拖动区域
    [SerializeField]
    private RectTransform m_RectBounds;
    private RectTransform m_RectTransform;
    private float halfBoundsWidth;
    private float halfWidth;

    [Serializable]
    public class Move_Event : UnityEvent<float> { }
    [Serializable]
    public class Stop_Event : UnityEvent { }

    [FormerlySerializedAs("onMove")]
    [SerializeField]
    public Move_Event MoveEvent = new Move_Event();

    [FormerlySerializedAs("onStop")]
    [SerializeField]
    public Stop_Event StopEvent = new Stop_Event();

    private void Awake()
    {
        m_RectTransform = this.GetComponent<RectTransform>();
        halfBoundsWidth = m_RectBounds.sizeDelta.x / 2;
        halfWidth = m_RectTransform.sizeDelta.x / 2;
    }

    public void OnPointerDown(PointerEventData eventData)
    {

    }

    //坑:必需要实现OnPointerDown,OnPointerUp才能响应
    public void OnPointerUp(PointerEventData eventData)
    {
        m_RectTransform.anchoredPosition = Vector2.zero;
        StopEvent?.Invoke();
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (!eventData.IsPointerMoving())
            return;
        var dragPosition = eventData.position;
        var localPosition = ScreenPointToLocalPointInRectangle(dragPosition);
        m_RectTransform.anchoredPosition = localPosition;
        //左右滑动值
        float slipX = localPosition.x;
        float sign = slipX < 0 ? -1 : 1;
        slipX = Mathf.Abs(slipX);
        //小幅度滑动时不触发转向事件
        float minSlip = halfWidth / 10;
        if (slipX <= minSlip)
            return;
        slipX = slipX - minSlip;
        //归一化
        float value = slipX / (halfBoundsWidth - minSlip);
        //降低转向灵敏度
        value = sign * Mathf.Pow(value, 4);
        MoveEvent?.Invoke(value);
    }

    private Vector2 ScreenPointToLocalPointInRectangle(Vector2 screenPoint)
    {
        Vector2 localPoint = Vector2.zero;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(m_RectBounds, screenPoint, null, out localPoint);
        return GetAdjustedPosition(localPoint);
    }

    private Vector2 GetAdjustedPosition(Vector2 pos)
    {
        pos.x = Mathf.Max(pos.x, -halfBoundsWidth);
        pos.x = Mathf.Min(pos.x, halfBoundsWidth);
        pos.y = 0;
        return pos;
    }
}

效果

11118.gif

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容