【Unity】在游戏中实现虚拟摇杆功能
使用场景
在手机游戏开发中,使用虚拟摇杆控制角色进行移动。
虚拟摇杆预制体制作
-
在UI界面添加虚拟摇杆外圈图片
-
在外圈下添加内圈图片 将位置置于外圈中心位置
-
添加脚本
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
类的单例实现
本文来自博客园,作者:星空探险家,转载请注明原文链接:https://www.cnblogs.com/PuppetLazy/p/17849877.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库