【Unity】在游戏中实现虚拟摇杆功能

使用场景

在手机游戏开发中,使用虚拟摇杆控制角色进行移动。

虚拟摇杆预制体制作

  1. 在UI界面添加虚拟摇杆外圈图片
  2. 在外圈下添加内圈图片 将位置置于外圈中心位置
    在这里插入图片描述
    在这里插入图片描述
  3. 添加脚本
using Tools;
using UnityEngine;

    /// <summary>
    /// 虚拟摇杆管理器
    /// </summary>
    public class VirtualJoystickManager : SingletonMonoBehaviour<VirtualJoystickManager> {
        
        [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 = Input.mousePosition;

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

        /// <summary>
        /// 更新内环位置
        /// </summary>
        private void UpdateInsidePos() {
            inside.transform.position = 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 > (float)Screen.width / 2 || v.x < 0) {
                return false;
            } 
            if (v.y > (float)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;
        }
    }

注:SingletonMonoBehaviour为自己封装的基于MonoBehaviour类的单例实现
链接:添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Unity2D实现JoyStick摇杆功能的代码示例: ```csharp using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class JoyStick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler { private Image bgImg; private Image joystickImg; private Vector3 inputVector; private void Start() { bgImg = GetComponent<Image>(); joystickImg = transform.GetChild(0).GetComponent<Image>(); } public virtual void OnDrag(PointerEventData ped) { Vector2 pos; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(bgImg.rectTransform, ped.position, ped.pressEventCamera, out pos)) { pos.x = (pos.x / bgImg.rectTransform.sizeDelta.x); pos.y = (pos.y / bgImg.rectTransform.sizeDelta.y); inputVector = new Vector3(pos.x * 2 + 1, 0, pos.y * 2 - 1); inputVector = (inputVector.magnitude > 1.0f) ? inputVector.normalized : inputVector; joystickImg.rectTransform.anchoredPosition = new Vector3(inputVector.x * (bgImg.rectTransform.sizeDelta.x / 3), inputVector.z * (bgImg.rectTransform.sizeDelta.y / 3)); } } public virtual void OnPointerDown(PointerEventData ped) { OnDrag(ped); } public virtual void OnPointerUp(PointerEventData ped) { inputVector = Vector3.zero; joystickImg.rectTransform.anchoredPosition = Vector3.zero; } public float Horizontal() { if (inputVector.x != 0) return inputVector.x; else return Input.GetAxis("Horizontal"); } public float Vertical() { if (inputVector.z != 0) return inputVector.z; else return Input.GetAxis("Vertical"); } } ``` 这个代码实现了一个简单的JoyStick摇杆功能,可以通过Horizontal()和Vertical()方法获取摇杆的输入值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值