Unity3D基于UGUI实现虚拟摇杆
作者:一缕残阳 发布时间:2023-03-15 15:42:37
标签:Unity3D,UGUI,虚拟摇杆
虚拟摇杆在移动游戏开发中,是很常见的需求,今天我们在Unity中,使用UGUI来实现一个简单的虚拟摇杆功能。
1.打开Unity,新创建一个UIJoystick.cs脚本,代码如下:
using UnityEngine;
using UnityEngine.EventSystems;
public class UIJoystick : MonoBehaviour, IDragHandler, IEndDragHandler
{
/// <summary>
/// 被用户拖动的操纵杆
/// </summary>
public Transform target;
/// <summary>
/// 操纵杆可移动的最大半径
/// </summary>
public float radius = 50f;
/// <summary>
/// 当前操纵杆在2D空间的x,y位置
/// 摇杆按钮的值【-1,1】之间
/// </summary>
public Vector2 position;
//操纵杆的RectTransform组件
private RectTransform thumb;
void Start()
{
thumb = target.GetComponent<RectTransform>();
}
/// <summary>
/// 当操纵杆被拖动时触发
/// </summary>
public void OnDrag(PointerEventData data)
{
//获取摇杆的RectTransform组件,以检测操纵杆是否在摇杆内移动
RectTransform draggingPlane = transform as RectTransform;
Vector3 mousePos;
//检查拖动的位置是否在拖动rect内,
//然后设置全局鼠标位置并将其分配给操纵杆
if (RectTransformUtility.ScreenPointToWorldPointInRectangle (draggingPlane, data.position, data.pressEventCamera, out mousePos)) {
thumb.position = mousePos;
}
//触摸向量的长度(大小)
//计算操作杆的相对位置
float length = target.localPosition.magnitude;
//如果操纵杆超过了摇杆的范围,则将操纵杆设置为最大半径
if (length > radius) {
target.localPosition = Vector3.ClampMagnitude (target.localPosition, radius);
}
//在Inspector显示操纵杆位置
position = target.localPosition;
//将操纵杆相对位置映射到【-1,1】之间
position = position / radius * Mathf.InverseLerp (radius, 2, 1);
}
/// <summary>
/// 当操纵杆结束拖动时触发
/// </summary>
public void OnEndDrag(PointerEventData data)
{
//拖拽结束,将操纵杆恢复到默认位置
position = Vector2.zero;
target.position = transform.position;
}
}
2.如图创建UGUI,所用资源可在网上自行下载。
效果图如下:
3.打包运行即可。这样一个简单的虚拟摇杆就实现了。
下面是对以上虚拟摇杆代码的扩展(ps:只是多了一些事件,便于其他脚本访问使用)废话不多说来代码了
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//
// Joystick component for controlling player movement and actions using Unity UI events.
// There can be multiple joysticks on the screen at the same time, implementing different callbacks.
//
public class UIJoystick : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
///
/// Callback triggered when joystick starts moving by user input.
///
public event Action onDragBegin;
///
/// Callback triggered when joystick is moving or hold down.
///
public event Action onDrag;
///
/// Callback triggered when joystick input is being released.
///
public event Action onDragEnd;
///
/// The target object i.e. jostick thumb being dragged by the user.
///
public Transform target;
///
/// Maximum radius for the target object to be moved in distance from the center.
///
public float radius = 50f;
///
/// Current position of the target object on the x and y axis in 2D space.
/// Values are calculated in the range of [-1, 1] translated to left/down right/up.
///
public Vector2 position;
//keeping track of current drag state
private bool isDragging = false;
//reference to thumb being dragged around
private RectTransform thumb;
//initialize variables
void Start()
{
thumb = target.GetComponent();
//in the editor, disable input received by joystick graphics:
//we want them to be visible but not receive or block any input
#if UNITY_EDITOR
Graphic[] graphics = GetComponentsInChildren();
// for(int i = 0; i < graphics.Length; i++)
// graphics[i].raycastTarget = false;
#endif
}
///
/// Event fired by UI Eventsystem on drag start.
///
public void OnBeginDrag(PointerEventData data)
{
isDragging = true;
if(onDragBegin != null)
onDragBegin();
}
///
/// Event fired by UI Eventsystem on drag.
///
public void OnDrag(PointerEventData data)
{
//get RectTransforms of involved components
RectTransform draggingPlane = transform as RectTransform;
Vector3 mousePos;
//check whether the dragged position is inside the dragging rect,
//then set global mouse position and assign it to the joystick thumb
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(draggingPlane, data.position, data.pressEventCamera, out mousePos))
{
thumb.position = mousePos;
}
//length of the touch vector (magnitude)
//calculated from the relative position of the joystick thumb
float length = target.localPosition.magnitude;
//if the thumb leaves the joystick's boundaries,
//clamp it to the max radius
if (length > radius)
{
target.localPosition = Vector3.ClampMagnitude(target.localPosition, radius);
}
//set the Vector2 thumb position based on the actual sprite position
position = target.localPosition;
//smoothly lerps the Vector2 thumb position based on the old positions
position = position / radius * Mathf.InverseLerp(radius, 2, 1);
}
//set joystick thumb position to drag position each frame
void Update()
{
//in the editor the joystick position does not move, we have to simulate it
//mirror player input to joystick position and calculate thumb position from that
#if UNITY_EDITOR
target.localPosition = position * radius;
target.localPosition = Vector3.ClampMagnitude(target.localPosition, radius);
#endif
//check for actual drag state and fire callback. We are doing this in Update(),
//not OnDrag, because OnDrag is only called when the joystick is moving. But we
//actually want to keep moving the player even though the jostick is being hold down
if(isDragging && onDrag != null)
onDrag(position);
}
///
/// Event fired by UI Eventsystem on drag end.
///
public void OnEndDrag(PointerEventData data)
{
//we aren't dragging anymore, reset to default position
position = Vector2.zero;
target.position = transform.position;
//set dragging to false and fire callback
isDragging = false;
if (onDragEnd != null)
onDragEnd();
}
}
来源:https://blog.csdn.net/m0_37998140/article/details/78259041


猜你喜欢
- 当使用spring-Boot时,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet规范的所有 * (
- 前言本篇文章主要介绍关于我在SpringBoot中使用MyBatis-Plus是如何解决Invalid bound statement (n
- 若要在 C++ 中实现异常处理,你可以使用 try、throw 和 catch 表达式。首先,使用 try 块将可能引发异常的一个或多个语句
- lombok插件使用引入依赖,在项目中使用Lombok可以减少很多重复代码的书写。比如说getter/setter/toString等方法的
- 本文实例讲述了C#中Memcached缓存的用法,分享给大家供大家参考。具体方法如下:ICacheStrategy.cs文件如下:publi
- 一、使用嵌入式关系型SQLite数据库存储数据在Android平台上,集成了一个嵌入式关系型数据库——SQLite,SQLite3支持NUL
- 程序设计成为简单的服务端和客户端之间的通信, 但通过一些方法可以将这两者进行统一起来, 让服务端也成为客户端, 让客户端也成为服务端, 使它
- 在实际工作中,重试重发请求处理是一个非常常见的场景,比如:1、发送消息失败。2、调用远程服务失败。3、争抢锁失败。这些错误可能是因为网络波动
- 1.Knife4j在线API文档基本使用Knife4j是一款基于Swagger 2的在线API文档框架。使用Knife4j的基础步骤:添加依
- 实践过程效果代码public partial class frmSend : Form{ public frmSe
- 本文实例讲述了C#实现的xml操作类,分享给大家供大家参考,具体如下:using System;using System.Data;usin
- 前言之前写的progress其实根本没有起到进度条的作用,太显眼,而且并不好看,所以有了新的想法,我们将ProgressBar控件换成See
- Android Studio下载(下文统称AS)AS最新版下载请戳:AS下载Android SDK下载SDK安装器下载SDK安装器下载请戳:
- 引言内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑。不过世界上不存在
- 前言前不久遇到一个问题,是公司早期的基础库遇到的,其实很低级,但是还是记录下来。出错点是一个 IO 流的写入bug,我们项目会有一种专有的数
- Criteria的and和or进行联合查询DemoExample example=new DemoExample ();DemoExampl
- 游标查询(scroll)简介scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种
- 混乱的URI编码 JavaScript中编码有三种方法:escape、encodeURI、encodeURIComponent C#中编码主
- 【引用】迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。 它的主要特点是以起始点为中心
- 本文实例讲述了C#使用winform简单导出Excel的方法。分享给大家供大家参考,具体如下:using Excel;在项目中引入Excel