using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace AscensionGame.UI
{
public class MyJoystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
[Header("摇杆类型")]
public EJoystickType EJoystickType = EJoystickType.Fixed;
public RectTransform BgRect;
public RectTransform HandleRect;
public Camera Camera;
public Button Btn;
private RectTransform mBaseRect;
private Canvas mCanvas;
public float MoveThreshold;
private float deadZone = 0;
public float DeadZone
{
get { return deadZone; }
set { deadZone = Mathf.Abs(value); }
}
public Vector2 input = Vector2.zero;
private Vector2 center = new Vector2(0.5f, 0.5f);
private Vector2 fixedPosition = Vector2.zero;
public GameObject CubeObj;
public float MoveSpeed = 8f;
private Vector3 StartVec3;
protected virtual void Start()
{
mBaseRect = GetComponent<RectTransform>();
mCanvas = GetComponentInParent<Canvas>();
fixedPosition = BgRect.anchoredPosition;
InitData();
Btn.onClick.AddListener(OnClickBtn);
}
private void SetMode()
{
if (this.EJoystickType == EJoystickType.Fixed)
{
BgRect.anchoredPosition = fixedPosition;
BgRect.gameObject.SetActive(true);
}
else
{
BgRect.gameObject.SetActive(false);
}
}
public void OnPointerDown(PointerEventData eventData)
{
if (eventData.pointerEnter != null)
{
Debug.Log($"OnPointerDown{eventData.pointerEnter.name}");
}
else
{
Debug.Log($"OnPointerDown null");
}
if (this.EJoystickType != EJoystickType.Fixed)
{
BgRect.anchoredPosition = ScreenPointToAnchoredPosition(eventData.position);
BgRect.gameObject.SetActive(true);
}
}
public void OnDrag(PointerEventData eventData)
{
if (eventData.pointerEnter != null)
{
Debug.Log($"OnDrag:{eventData.pointerEnter.name}");
}
else
{
Debug.Log($"OnDrag:null");
}
Vector2 position = Camera.WorldToScreenPoint(BgRect.position);//将ui坐标中的background映射到屏幕中的实际坐标
Vector2 radius = (BgRect.sizeDelta - HandleRect.sizeDelta) / 2;
input = (eventData.position - position) / (radius * mCanvas.scaleFactor);//将屏幕中的触点和background的距离映射到ui空间下实际的距离
HandleInput(input.magnitude, input.normalized, radius); //对输入进行限制
HandleRect.anchoredPosition = input * radius ; //实时计算handle的位置
}
private void Update()
{
CubeObj.transform.position += new Vector3(input.x, 0f, input.y) * Time.deltaTime * MoveSpeed;
}
public void OnPointerUp(PointerEventData eventData)
{
if (eventData.pointerEnter != null)
Debug.Log($"OnPointerUp{eventData.pointerEnter.name}");
else
{
Debug.Log($"OnPointerUp null");
}
if (this.EJoystickType != EJoystickType.Fixed)
BgRect.gameObject.SetActive(false);
input = Vector2.zero;
HandleRect.anchoredPosition = Vector2.zero;
}
public void HandleInput(float magnitude, Vector2 normalised, Vector2 radius)
{
if (this.EJoystickType == EJoystickType.Dynamic && magnitude > MoveThreshold)
{
Vector2 difference = normalised * (magnitude - MoveThreshold) * radius;
BgRect.anchoredPosition += difference;
}
if (magnitude > deadZone)
{
if (magnitude > 1)
input = normalised;
}
else
input = Vector2.zero;
}
private Vector2 ScreenPointToAnchoredPosition(Vector2 screenPosition)
{
Vector2 localPoint = Vector2.zero;
RectTransformUtility.ScreenPointToLocalPointInRectangle(mBaseRect, screenPosition, Camera, out localPoint);
return localPoint;
}
private void OnClickBtn()
{
switch (EJoystickType)
{
case EJoystickType.Fixed:
EJoystickType = EJoystickType.Floating;
break;
case EJoystickType.Floating:
EJoystickType = EJoystickType.Fixed;
break;
default:
EJoystickType = EJoystickType.Fixed;
break;
}
InitData();
}
private void InitData()
{
BgRect.pivot = center;
HandleRect.anchorMin = center;
HandleRect.anchorMax = center;
HandleRect.pivot = center;
HandleRect.anchoredPosition = Vector2.zero;
SetMode();
}
}
}