Unity实现虚拟摇杆

面板上设置一些属性,比如摇杆拖拽的距离,是否始终可视,是否限制虚拟摇杆位置(我是把虚拟摇杆限制在了屏幕的左下区域)。
使用GetDirAndLength()方法去获得移动的方向和长度即可

using UnityEngine;

/// <summary>
/// 虚拟摇杆管理器
/// </summary>
public class VirtualJoystickManager : MonoBehaviour
{
    private static VirtualJoystickManager _instance;
    public static VirtualJoystickManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<VirtualJoystickManager>();
            }
            return _instance;
        }
    }

    [Header("是否始终可视")]
    public bool alwaysVisible;//是否始终可视
    [Header("是否限制虚拟摇杆位置")]
    public bool restrictVirtualJoystickPos;//是否限制虚拟摇杆位置

    [Header("虚拟摇杆物体")]
    [Header("==========")]
    public GameObject virtualJoystick;//虚拟摇杆父物体
    public GameObject inside;//内环
    public GameObject outside;//外环

    [Header("最大拖拽距离")]
    [Header("==========")]
    public float maxDragLength;//最大拖拽距离

    private Vector3 virtualJoystickCenter;//虚拟轴中心

    private void Update()
    {
        //如果限制虚拟轴位置并且虚拟轴位置超出了限制范围则不进行任何操作
        if (restrictVirtualJoystickPos && JudgeIsValidRange() == false)
        {
            return;
        }

        //更新显示
        UpdateShow();

        //更新虚拟摇杆位置
        if (Input.GetMouseButtonDown(0))
        {
            UpdateVirtualJoystickPos();
        }
        else if (Input.GetMouseButtonUp(0))
        {
            inside.transform.position = virtualJoystickCenter;
        }

        //更新内环位置(限制拖拽范围)
        if (Input.GetMouseButton(0))
        {
            UpdateInsidePos();
        }
    }

    /// <summary>
    /// 更新显示
    /// </summary>
    private void UpdateShow()
    {
        if (alwaysVisible)
        {
            inside.SetActive(true);
            outside.SetActive(true);
        }
        else if (alwaysVisible == false)
        {
            if (Input.GetMouseButtonDown(0))
            {
                inside.SetActive(true);
                outside.SetActive(true);
            }
            if (Input.GetMouseButtonUp(0))
            {
                inside.SetActive(false);
                outside.SetActive(false);
            }
        }
    }

    /// <summary>
    /// 更新虚拟摇杆位置
    /// </summary>
    private void UpdateVirtualJoystickPos()
    {
        //得到虚拟轴的中心位置
        virtualJoystickCenter = ScreenToWorld(Input.mousePosition);

        //设置虚拟轴的位置
        virtualJoystick.transform.position = virtualJoystickCenter;
    }

    /// <summary>
    /// 更新内环位置
    /// </summary>
    private void UpdateInsidePos()
    {
        inside.transform.position = ScreenToWorld(Input.mousePosition);
        if (Vector3.Distance(inside.transform.position, virtualJoystickCenter) > maxDragLength)
        {
            Vector3 normalizedPos = (inside.transform.position - virtualJoystickCenter).normalized;
            inside.transform.position = normalizedPos * maxDragLength + virtualJoystickCenter;
        }
    }

    /// <summary>
    /// 判断是否为有效的范围
    /// </summary>
    /// <returns>是否为有效的范围</returns>
    private bool JudgeIsValidRange()
    {
        if (inside.activeInHierarchy)
        {
            return true;
        }

        Vector2 v = Input.mousePosition;
        if (v.x > Screen.width / 2 || v.x < 0)
        {
            return false;
        }
        else if (v.y > Screen.height / 2 || v.y < 0)
        {
            return false;
        }
        return true;
    }

    /// <summary>
    /// 屏幕坐标转世界坐标
    /// </summary>
    /// <param name="screenPos">屏幕坐标位置</param>
    /// <param name="camera">相机</param>
    /// <returns>转换后的世界坐标</returns>
    public static Vector3 ScreenToWorld(Vector3 screenPos, Camera camera = null)
    {
        if (camera == null)
        {
            camera = Camera.main;
        }
        Vector3 _screenPos = new Vector3(screenPos.x, screenPos.y, -camera.transform.position.z);
        Vector3 v = camera.ScreenToWorldPoint(_screenPos);
        return v;
    }

    /// <summary>
    /// 得到运动的方向和长度
    /// </summary>
    /// <returns>方向和长度</returns>
    public Vector3 GetDirAndLength()
    {
        return inside.transform.position - virtualJoystickCenter;
    }
}
发布了169 篇原创文章 · 获赞 370 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/105485460
今日推荐