Unity学习笔记——虚拟摇杆实现笔记(事件触发器的使用、UGUI 坐标转换)

虚拟摇杆实现笔记(事件触发器的使用、UGUI 坐标转换)

一、核心逻辑

通过 EventTrigger 监听摇杆的拖拽/结束拖拽事件,控制摇杆位置,再将摇杆偏移量转为玩家移动方向,实现虚拟摇杆控制角色移动。

主要学习:事件触发器的使用、UGUI 坐标转换

二、代码结构与注释

1. 摇杆事件注册

csharp 复制代码
//从外部获取摇杆物体上的EventTrigger组件
public EventTrigger et;

// 为摇杆添加拖拽事件
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.Drag; // 拖拽事件ID(枚举类型)
entry.callback.AddListener(JoyDrag);   // 绑定拖拽回调方法
et.triggers.Add(entry);

// 为摇杆添加结束拖拽事件
entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.EndDrag; // 结束拖拽事件ID
entry.callback.AddListener(EndJoyDrag);   // 绑定结束拖拽回调方法
et.triggers.Add(entry);

2. 拖拽事件回调(控制摇杆位置+玩家移动)

csharp 复制代码
// 摇杆拖拽时执行
private void JoyDrag(BaseEventData data)
{
    // 把基础事件数据转为指针事件数据(获取拖拽相关信息)
    PointerEventData eventData = data as PointerEventData;

    // 旧方法:通过当前摇杆位置 + 拖拽偏移量更新位置
    // 缺点:受UI相机、Canvas模式影响,多分辨率适配较差
    // imgJoy.position += new Vector3(eventData.delta.x, eventData.delta.y, 0);

    // 新方法:使用RectTransformUtility完成屏幕坐标转UI局部坐标,适配性更强
    Vector2 nowPos;
    // 将鼠标/触摸屏幕坐标,转换为摇杆父物体下的局部坐标
    RectTransformUtility.ScreenPointToLocalPointInRectangle(
        imgJoy.parent as RectTransform,  // 目标父物体RectTransform
        eventData.position,              // 原始屏幕坐标
        eventData.enterEventCamera,       // 渲染UI的相机
        out nowPos                        // 输出转换后的局部坐标
    );
    // 赋值局部坐标,实现摇杆精准跟随拖拽点
    imgJoy.localPosition = nowPos;

    // 防止摇杆超出范围:限制摇杆的锚点偏移量最大为110
    if (imgJoy.anchoredPosition.magnitude > 110)
    {
        // 将摇杆位置归一化(保持方向不变),再乘以最大范围,拉回临界位置
        imgJoy.anchoredPosition = imgJoy.anchoredPosition.normalized * 110;
    }

    // 调用玩家移动方法,传入摇杆当前偏移量作为移动方向
    player.Move(imgJoy.anchoredPosition);
}

3. 结束拖拽回调(摇杆复位+玩家停止移动)

csharp 复制代码
// 摇杆拖拽结束时执行
private void EndJoyDrag(BaseEventData data)
{
    // 摇杆锚点位置回归中心点(Vector2.zero)
    imgJoy.anchoredPosition = Vector2.zero;
    // 传入零向量,让玩家停止移动
    player.Move(Vector2.zero);
}

4. 玩家移动控制(Update 帧更新)

csharp 复制代码
void Update()
{
    // 如果当前移动方向不为零(摇杆被拖动)
    if (nowMoveDir != Vector3.zero)
    {
        // 角色沿自身前方移动,速度由 moveSpeed 控制,乘以 Time.deltaTime 保证帧率无关
        this.transform.Translate(Vector3.forward * (moveSpeed * Time.deltaTime));
        // 角色平滑转向目标方向(Slerp实现缓动效果,rotateSpeed控制转向速度)
        this.transform.rotation = Quaternion.Slerp(
            this.transform.rotation, 
            Quaternion.LookRotation(nowMoveDir), 
            rotateSpeed * Time.deltaTime
        );
    }
}

5. 移动方向设置(供摇杆调用)

csharp 复制代码
// 外部调用:将摇杆二维偏移量转为角色三维移动方向
public void Move(Vector2 dir)
{
    nowMoveDir.x = dir.x;   // 摇杆X偏移量 → 角色水平方向
    nowMoveDir.y = 0;       // Y轴(竖直方向)固定为0,不影响高度
    nowMoveDir.z = dir.y;   // 摇杆Y偏移量 → 角色前后方向
}

三、关键知识点

1. EventTrigger 事件绑定(标准四步流程)

a. EventTrigger.Entry entry = new EventTrigger.Entry(); 创建事件条目

b. entry.eventID = EventTriggerType.Drag; 绑定事件枚举类型

c. entry.callback.AddListener(JoyDrag); 绑定拖拽回调方法

d. et.triggers.Add(entry); 把事件添加到EventTrigger组件,事件正式生效

2. 两种摇杆位置更新方式对比

  • 旧方案position + delta 偏移叠加

    直接累加拖拽增量,逻辑简单,但依赖屏幕空间,不同Canvas渲染模式、分辨率下容易错位。

  • 新方案RectTransformUtility.ScreenPointToLocalPointInRectangle 坐标转换

    将屏幕坐标转为UI父物体局部坐标,适配所有UI模式,拖拽跟随更精准,是UGUI拖拽通用写法。

    参数说明:目标父物体RectTransform、屏幕坐标、UI相机、输出局部坐标。

3. 摇杆范围限制

  • anchoredPosition:UI元素相对于锚点的偏移量,适合做摇杆位置控制
  • magnitude:向量长度,用于判断摇杆是否超出最大范围
  • normalized:向量归一化,保持方向不变,仅缩放长度到1,再乘以最大范围实现"拉回"限位

4. 方向转换逻辑

  • 摇杆的二维 Vector2 偏移量 → 角色三维 Vector3 移动方向(X→水平,Y→前后,Y轴固定为0)
  • Quaternion.LookRotation:根据方向向量生成目标旋转
  • Quaternion.Slerp:实现平滑转向,避免角色瞬间转头

5. 帧率无关移动

  • 所有移动/旋转逻辑乘以 Time.deltaTime,保证不同帧率下移动速度保持一致
相关推荐
晓py1 小时前
音视频基础概念入门_FFmpeg学习笔记
学习·ffmpeg·音视频
red_redemption1 小时前
自由学习记录(196)
学习
魔士于安1 小时前
unity volumefog带各种demo第一人称 wsad 穿墙控制
游戏·unity·游戏引擎·贴图·模型
踏着七彩祥云的小丑2 小时前
AI学习——记忆系统
人工智能·学习·ai
xcLeigh2 小时前
Python入门:Python3 operator模块全面学习教程
开发语言·python·学习·教程·python3·operator
Dest1ny-安全2 小时前
2026最新CTF知识库:12大Web漏洞深度文章+1156篇历年大赛WP+50+脚本+Payload速查 +AI/RAG离线在线知识库
java·学习·安全·web安全·servlet
魔法阵维护师2 小时前
从零开发游戏需要学习的c#模块,第三十二章(Boss 战系统)
学习·游戏·c#
洵有兮2 小时前
Shell 脚本编程学习总结(基础 + 变量 + 条件 + 流程控制 + 函数数组)
linux·学习
疯狂打码的少年2 小时前
流水线冒险(结构冒险/数据冒险/控制冒险)
笔记