【Unity】UGUI实现摇杆功能

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

public class InputJoystick : MonoBehaviour
{
    //摇杆根节点
    [SerializeField] RectTransform joystickRoot;
    //摇杆节点
    [SerializeField] RectTransform joystickNode;
    //摇杆方向节点
    [SerializeField] RectTransform joystickDirection;

    //摇杆半径
    [SerializeField] int joystickRadius = 200;
    //抬手摇杆复位速度
    [SerializeField, Range(0.01f, 1)] float revertPositionSpeed = 0.75f;
    //单击判定时间范围
    [SerializeField] float tapDuration = 0.1f;

    //摇杆事件回调
    public static Action OnJoystickMoveStart;
    public static Action OnJoystickMoving;
    public static Action OnJoystickMoveEnd;
    public static Action OnJoystickTap;

    //屏幕宽高
    private int screenWidth = Screen.width;
    private int screenHeight = Screen.height;

    //摇杆默认位置
    private Vector3 joystickDefaultPos;
    //按下时摇杆中心位置
    private Vector3 curJoystickOrigin;
    //按下时摇杆方向
    private Vector3 curJoystickDirection;

    private bool isInputing = false;        //是否按下摇杆
    private bool needToRevertRoot = false;  //根节点是否需要回位
    private bool needToRevertNode = false;  //遥感节点是否需要回位
    private bool isReadyToTap = false;      //是否判定单击
    private bool isActived = true;          //是否激活摇杆

    //摇杆按下时间
    private float startInputTime;

    private void Awake()
    {
        joystickDefaultPos = joystickRoot.anchoredPosition;
    }
    private void Start()
    {
        joystickDirection.gameObject.SetActive(false);
    }

    private void Update()
    {
        if (!isActived)
            return;
        if (Input.GetMouseButtonDown(0))
        {
            if (IsRaycastUI())
                return;
            OnInputStart(Input.mousePosition);
            isInputing = true;
        }
        else if (Input.GetMouseButton(0))
        {
            if (isInputing)
                OnInputIng(Input.mousePosition);
        }
        else if (Input.GetMouseButtonUp(0))
        {
            if (isInputing)
            {
                OnInputEnd(Input.mousePosition);
                isInputing = false;
            }
        }
        else if (!isInputing)
        {
            if (needToRevertRoot)
            {
                RevertJoystickRootPos();
            }
            if (needToRevertNode)
            {
                RevertJoystickNodePos();
            }
        }
    }

    private bool IsRaycastUI()
    {
        //鼠标点击事件
        return (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject());
    }

    //激活/取消激活 摇杆
    public void ActiveJoystick(bool active)
    {
        if (isActived == active)
            return;

        isActived = active;

        if (!isActived)
        {
            if (isInputing)
                OnJoystickMoveEnd?.Invoke();
        }

        joystickRoot.gameObject.SetActive(active);
        joystickRoot.anchoredPosition = joystickDefaultPos;
        joystickNode.localPosition = Vector3.zero;
    }

    #region --- 输入回调 ---

    private void OnInputStart(Vector3 point)
    {
        curJoystickOrigin = point;

        startInputTime = Time.unscaledTime;
        isReadyToTap = true;

        Vector3 joystickPos = Vector3.zero;
        joystickPos.x = -0.5f * screenWidth + point.x;
        joystickPos.y = -0.5f * screenHeight + point.y;
        joystickRoot.anchoredPosition = joystickPos;
        joystickNode.localPosition = Vector3.zero;

        joystickDirection.gameObject.SetActive(true);

        OnJoystickMoveStart?.Invoke();
    }
    float tempLength;
    private void OnInputIng(Vector3 point)
    {
        tempLength = (point - curJoystickOrigin).magnitude;

        if (tempLength < 0.01f)
        {
            curJoystickDirection = Vector3.zero;
            OnJoystickMoving?.Invoke(curJoystickDirection);

            if (isReadyToTap)
            {
                if (Time.unscaledTime - startInputTime >= tapDuration)
                {
                    isReadyToTap = false;
                }
            }
        }
        else if (tempLength <= joystickRadius)
        {
            curJoystickDirection = (point - curJoystickOrigin).normalized * tempLength / joystickRadius;
            isReadyToTap = false;
        }
        else
        {
            curJoystickDirection = (point - curJoystickOrigin).normalized;
            isReadyToTap = false;
        }

        joystickNode.localPosition = curJoystickDirection * joystickRadius;
        if (curJoystickDirection == Vector3.zero)
            joystickDirection.up = Vector3.up;
        else
            joystickDirection.up = curJoystickDirection;

        OnJoystickMoving?.Invoke(curJoystickDirection);
    }
    private void OnInputEnd(Vector3 point)
    {
        curJoystickOrigin = joystickDefaultPos;

        needToRevertRoot = true;
        needToRevertNode = true;

        joystickDirection.gameObject.SetActive(false);

        if (isReadyToTap)
        {
            OnJoystickTap?.Invoke();
            isReadyToTap = false;
        }

        OnJoystickMoveEnd?.Invoke();
    }

    #endregion

    #region --- 摇杆复位 ---

    private void RevertJoystickRootPos()
    {
        if ((joystickRoot.position - joystickDefaultPos).sqrMagnitude > 0.1f)
        {
            joystickRoot.anchoredPosition = Vector3.Lerp(joystickRoot.anchoredPosition, joystickDefaultPos, revertPositionSpeed);
        }
        else
        {
            joystickRoot.anchoredPosition = joystickDefaultPos;
            needToRevertRoot = false;
        }
    }
    private void RevertJoystickNodePos()
    {
        if (joystickNode.localPosition.sqrMagnitude > 0.1f)
        {
            joystickNode.localPosition = Vector3.Lerp(joystickNode.localPosition, Vector3.zero, revertPositionSpeed);
        }
        else
        {
            joystickNode.localPosition = Vector3.zero;
            needToRevertNode = false;
        }
    }

    #endregion

}

 

你可能感兴趣的:(功能Demo)