using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
///
/// 屏幕虚拟摇杆(移动轮盘)。挂在预制体根节点上,底盘和摇杆头两个引用
/// (background / handle)在 Inspector / 预制体里接好,代码里不按名字查找节点。
///
/// 鼠标按住拖拽或手指触摸都可以操作,对外输出归一化方向 :
/// x = 左右(右为正),y = 前后(上为正),模长 0~1 表示推杆幅度。
/// 松手后方向归零。
///
[DisallowMultipleComponent]
public class VirtualJoystick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
[Header("引用(必须在 Inspector / 预制体里指定)")]
[Tooltip("摇杆底盘(RectTransform)。拖拽位置以它的轴心为圆心换算,必须是捕获点击的那个节点")]
[SerializeField] private RectTransform background;
[Tooltip("摇杆头(RectTransform),跟着拖拽移动")]
[SerializeField] private RectTransform handle;
[Header("手感(距离单位是 UI 像素,以底盘轴心为圆心)")]
[Tooltip("摇杆头允许离开中心的最大距离。拖到这个距离就是满值输入(Value 模长 = 1),再往外拖摇杆头也不动。" +
"底盘 280、摇杆头 120 时,80 ≈ 摇杆头刚好贴到底盘边缘。")]
[SerializeField] private float maxDragRadius = 80f;
[Tooltip("死区:拖动距离小于「最大半径 × 该比例」时不输出,避免手抖")]
[Range(0f, 0.9f)]
[SerializeField] private float deadZone = 0.12f;
[Tooltip("松手后摇杆头是否弹回中心")]
[SerializeField] private bool returnToCenter = true;
[Tooltip("松手后是否隐藏整个轮盘(移动端常用)")]
[SerializeField] private bool hideOnRelease = false;
/// 归一化输入方向,x = 左右,y = 前后,模长 0~1。
public Vector2 Value { get; private set; }
/// 当前是否按住了轮盘。
public bool IsPressed { get; private set; }
private Canvas _canvas;
private Vector2 _handleHomePosition;
private void Awake()
{
if (background == null)
Debug.LogError("[VirtualJoystick] 没有指定摇杆底盘(background),请在 Inspector / 预制体里拖入。", this);
if (handle == null)
Debug.LogError("[VirtualJoystick] 没有指定摇杆头(handle),请在 Inspector / 预制体里拖入。", this);
_canvas = GetComponentInParent