目前已知的有两种方法实现,一种是通过继承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);
}
}