unityUI实现虚拟摇杆

目前已知的有两种方法实现,一种是通过继承ScrollRect类来实现一个摇杆的功能
对于这个方案可以参考这篇文章【Unity】虚拟摇杆控制的实现-CSDN博客
这个方案的最大的优点是简单方便,但存在不少问题,比如想要拨动摇杆时必须要使用拖动的方式去拖动摇杆,而不能通过点击摇杆区域去拨动摇杆

而下面的方案至少能解决不能通过点击摇杆区域去操作的问题
 

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

public class TestRocker : UIBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler
{

    [Tooltip("摇杆对象")]
    [SerializeField]
    private RectTransform m_Rocker;
    [Tooltip("摇杆背景")]
    [SerializeField]
    private RectTransform m_ViewRect;
    [Tooltip("摇杆的最大活动范围")]
    [SerializeField]
    private float m_Radius = 90f;

    private Vector2 m_RockerStartPostion;//摇杆的原点

    protected override void Start()
    {
        m_RockerStartPostion = m_Rocker.localPosition;
    }

    public Action<Vector2> OnRockerMoveAction ;//玩家拨动摇杆时触发的Action
    public Vector2 CurrentRockerPoint;//当前摇杆的值

    //刚开始拖动
    public void OnBeginDrag(PointerEventData eventData)
    {
    }
    //拖动时
    public virtual void OnDrag(PointerEventData eventData)
    {
        MoveRocker(eventData);
    }
    /// <summary>
    /// 结束拖动
    /// </summary>
    /// <param name="eventData"></param>
    public void OnEndDrag(PointerEventData eventData)
    {
        MoveEndRocker(eventData);
    }
    //点击摇杆区域
    public void OnPointerDown(PointerEventData eventData)
    {
        OnDrag(eventData);
    }
    //点击松开后
    public void OnPointerUp(PointerEventData eventData)
    {
        MoveEndRocker(eventData);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////.
    /////////////////////////////////////////////////////////////////////////////////////////////////


    private void MoveRocker(PointerEventData eventData)
    {
        Vector2 localCursor;

        if (eventData.button != PointerEventData.InputButton.Left)//只有左键点击有效
        {
            Debug.Log("左键");
            return;
        }
        if (!IsActive())
        {
            Debug.Log("IsActive()");
            return;
        }
        if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(m_ViewRect, eventData.position, eventData.pressEventCamera, out localCursor))
        {
            Debug.Log("没有点击");
            return;
        }

        if (localCursor.magnitude <= m_Radius)//判断摇杆是否超出范围
        {
            m_Rocker.anchoredPosition = localCursor;
        }
        else 
        {
            m_Rocker.anchoredPosition = localCursor.normalized*m_Radius;
        }
        OnRockerHasAction(m_Rocker.anchoredPosition);
    }
    private void MoveEndRocker(PointerEventData eventData)
    {
        m_Rocker.anchoredPosition = m_RockerStartPostion;
        OnRockerMoveAction?.Invoke(Vector2.zero);//结束时将输出重新调整为0
        CurrentRockerPoint = Vector2.zero;
    }
    private void OnRockerHasAction(Vector2 RockerPostion)
    {
        float DistanceOfRockerWithrockerStart = Vector2.Distance(RockerPostion,m_RockerStartPostion);//当前摇杆与原点的距离
        float TravelRatio = DistanceOfRockerWithrockerStart / m_Radius;//摇杆距离摇杆原点的比例
        Debug.Log($"形成比例:{TravelRatio}");

        Vector2 point = (RockerPostion - m_RockerStartPostion).normalized* TravelRatio;
        OnRockerMoveAction?.Invoke( point );
        CurrentRockerPoint = point;
    }
    public override bool IsActive()
    {
        return base.IsActive() && m_Rocker != null;
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawWireSphere(this.transform.position , m_Radius);

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值