using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 基于UGUI的摇杆
/// </summary>
public class JoystickUGUI : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler, IPointerDownHandler, IPointerUpHandler
{
private Transform cacheTransform;
private GameObject cacheGameObject;
private RectTransform rect;//范围
private RectTransform center;//中心球
private Canvas canvas;//画布
public delegate void JoystickTouchEvent();//点击事件
public delegate void JoystickDragEvent(Vector2 joystickAxis);//拖拽事件
public JoystickTouchEvent OnJoystickDragStart;//开始拖拽
public JoystickDragEvent OnJoystickDrag;//拖拽中
public JoystickTouchEvent OnJoystickDragEnd;//拖拽结束
public JoystickTouchEvent OnTouchStart;//开始点击
public JoystickTouchEvent OnTouchUp;//点击结束
private float radio = 200;//球拖拽最大距离
private Vector2 lastJoystickAxis;//上一次计算分发的向量
private bool isDraging;//是否在拖拽中
void Awake()
{
cacheGameObject = gameObject;
cacheTransform = transform;
rect = cacheTransform.Find("Border").GetComponent<RectTransform>();
center = cacheTransform.Find("Border/Center").GetComponent<RectTransform>();
canvas = cacheTransform.parent.GetComponent<Canvas>();
}
void Update()
{
if (isDraging && OnJoystickDrag != null)//没有松开时,以最后一次拖拽位置执行事件
{
OnJoystickDrag(lastJoystickAxis);
}
}
//Unity Method
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log($"OnBeginDrag {eventData.position}");
isDraging = true;
if (OnJoystickDragStart != null)
{
OnJoystickDragStart();
}
}
//Unity Method
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log($"OnEndDrag {eventData.position}");
isDraging = false;
center.anchoredPosition = Vector2.zero;
if (OnJoystickDragEnd != null)
{
OnJoystickDragEnd();
}
}
//Unity Method
public void OnDrag(PointerEventData eventData)
{
Vector2 uiPos = ScreenToRectPos(eventData.position);
//Debug.Log($"OnDrag {eventData.position}, screen pos:{eventData.position},uiPos:{uiPos}");
float dis = Vector2.Distance(uiPos, Vector2.zero);//如果pivot不是(0.5,0.5),距离计算需要修改
if (dis > radio)//超过最大移动半径,按照相似三角形,算坐标
{
uiPos = new Vector2(radio * uiPos.x / dis, radio * uiPos.y / dis);
}
center.anchoredPosition = uiPos;
if (OnJoystickDrag != null)
{
lastJoystickAxis = uiPos.normalized;//归一化后分发给事件,限定范围在-1,1之间
OnJoystickDrag(lastJoystickAxis);
}
}
//Unity Method
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log($"OnPointerDown {eventData.position}");
if (OnTouchStart != null)
{
OnTouchStart();
}
}
/// <summary>
/// 屏幕坐标转矩形内坐标
/// </summary>
/// <param name="screentPos"></param>
/// <returns></returns>
private Vector2 ScreenToRectPos(Vector2 screentPos)
{
Vector2 uiPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screentPos, canvas.worldCamera, out uiPos);
return uiPos;
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log($"OnPointerUp {eventData.position}");
if (OnTouchUp != null)
{
OnTouchUp();
}
}
}