首页 > 其他分享 >【Unity】在游戏中实现虚拟摇杆功能

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

时间:2023-11-22 17:36:51浏览次数:36  
标签:inside Vector3 摇杆 Unity 虚拟 Input public

使用场景

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

虚拟摇杆预制体制作

  1. 在UI界面添加虚拟摇杆外圈图片

  2. 在外圈下添加内圈图片 将位置置于外圈中心位置
    image
    image

  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类的单例实现

标签:inside,Vector3,摇杆,Unity,虚拟,Input,public
From: https://www.cnblogs.com/PuppetLazy/p/17849877.html

相关文章

  • 【Unity】伪随机算法之PRD
    概念在游戏制作中通常会有暴击等概率性事件,有两种方法实现,一种就是正常使用随机算法实现,真随机受人品影响,对游戏体验极不友好,所以就提出了伪随机概念,常见的就是PRD算法。P(N)=C*NP为最终概率C为概率增量N为次数随着攻击次数增加概率增加,当暴击时将N重置为1,没有......
  • KVM虚拟化架构
    手把手教学kvm虚拟化使用原创 对抗一下 步步运维步步坑 2023-11-2211:40 发表于四川收录于合集#虚拟化2个kvm概念kvm是做为内核模块嵌入linux的,所以并不会剥夺kernel的cpu和内存的控制权kvm的管理方式是将运来的用户空间作为控制台,对kvm进行管理,包括创建,......
  • 虚拟机的联网
    Nat本身的意思为网络地址转换即将内网地址转换为公网地址,因此使用nat可以节省ip资源,但是又想要虚拟机可以联网,那么使用nat模式是最好的选择,Nat模式使用虚拟nat设备和虚拟DHCP服务器与虚拟网卡相连,而虚拟nat设备和虚拟DHCP服务器与主机网卡相连,Vmnet8与主机上的VMwareNetworkAda......
  • vm虚拟机联网
    一:虚拟机网络连接在VM软件中,选项栏的“编辑”下的“虚拟网络编辑器”中可以看到三个虚拟网卡VMnet0、VMnet1、VMnet8,而我们的虚拟机就是通过这三个虚拟网卡,实现的三种不同的网络连接,让我们的虚拟机达到连接的目的。  二:在VM中如何配置网络连接1、打开电脑上的网络适配器......
  • VMware虚拟机如何联网、Xshell连接Linux虚拟机
     VMware虚拟机联网1、首先,在VMware界面单击虚拟机,点击编辑虚拟机设置,将网络适配器中的网络连接改为NAT模式。如下图所示: 2、然后,开启虚拟机,以root用户登录,进入终端,输入命令ifconfig查看当前系统所用的网卡接口,找到ens33。如下图: 3、输入以下指令:vim /etc/sysco......
  • kvm-虚拟机登陆方式VNC、virsh console
    阅读目录(Content)1、虚拟机多,VNC登陆问题2、多虚拟机,VNC登陆的实战3、使用virsh console登陆实战3.1、需求3.2、虚拟机开启支持console 3.3、登陆测试3.4、退回virshconsole方法回到顶部(gototop)1、虚拟机多,VNC登陆问题当我们虚拟机过多的时候,如果想用vn......
  • Unity AssetBundle Browser 使用
    https://blog.csdn.net/WenHuiJun_/article/details/113178688 参数说明BuildTarget-构建捆绑包的目标平台OutputPath-用于保存构建的捆绑包的路径。默认为AssetBundles/。可以手动编辑该路径,也可以选择“Browse”。要恢复默认命名约定,请点击“Reset”。ClearF......
  • Unity Asset Bundle Browser 导入
    https://github.com/Unity-Technologies/AssetBundles-Browser 有时候使用packManager来下载,但会下载不下来,超时无法连接服务器将上面链接内容下载下来后直接丢到工程Asset下随便目录就行,然后回报错,Boo什么错的,无脑删除掉Tests测试目录就行了 最后在Unity菜单栏[Windo......
  • Unity InputField 输入框
    参数text:输入框中显示的文本内容。placeholder:输入框中未输入内容时显示的占位符文本。characterLimit:输入框中可输入的最大数字符限制。contentType:输入框中可输入的内容类型,如整数、小数、密码等。onValueChanged:输入框内容改变时触发的事件。 函数用常A......
  • Unity中欧拉角
    什么是欧拉角?(1)使用单个角度来保存方位(2)X与Z沿自身坐标系旋转,Y沿世界坐标旋转(3)API:Vector3eulerAngle=this.tranform.rulerAngles;优点:(1)仅使用三个数字表达方位,占用空间小(2)沿坐标轴旋转的单位维角度,符合人的思考方式(3)任意三个数字都是合法的,不存在不合法的欧拉角缺点:(1)方......