Unity实现安卓虚拟摇杆多点触控

“Unity 输入变得简单:触摸事件和鼠标交互指南” 触摸输入是许多移动和基于触摸屏的游戏和应用程序的一个基本方面。无论您是在创建休闲手机游戏还是 VR 体验,了解如何在 Unity 中使用触摸输入都至关重要。在本综合指南中,我们将探讨什么是触摸输入、如何使用它以及如何确定触摸的位置以及对应的游戏对象 阅读详情
AI摘要

本文介绍Unity中实现触屏操作及多点触控的方法,重点讲解Touch结构体的应用,通过TouchEvent类管理触控与JoyStick类实现的虚拟摇杆间的交互。同时提供了鼠标模拟触控的解决方案。

=== 2024/5/23更新:添加鼠标模拟 ===

代码示例在最下面
效果如图:
在这里插入图片描述

1. Unity对于触屏操作的支持

1.1. Touch结构体

Unity使用结构体Touch定义触屏设备的输入,每一个触控点(可以理解为每一个手指)对应一个Touch,其中主要的属性如下:

属性含义
fingerId触控点的编号,在该触控点的生命周期内(从点下到抬起)是不变的
phase触控点的状态,是一个Touch.Phase枚举,包括:
Began(手指按下),
Move(手指滑动),
Stationary(手指已经按下且保持不动),
Ended(手指抬起),
Canceled(系统停止跟踪该触控点)
position触控点在屏幕的坐标(屏幕坐标系)
其他的属性参考https://docs.unity3d.com/ScriptReference/Touch.html

1.2. fingerId分配

需要注意的是对于fingerId的分配,类似于下面的过程:
使用一个数组表示哪些触控点当前被激活,初始为:
[0][0][0][0][0]
其中0表示未激活,1表示已激活。每按下一个手指时,从头寻找第一个未激活的空位,把它的索引赋给fingerId,例如按下第一个手指后,数组变为:
[1][0][0][0][0]
手指①的fingerId=0,这个时候再按下第二个手指,数组变为:
[1][1][0][0][0]
手指①的fingerId=0,手指②的fingerId=1,这个时候松开第一个手指,数组变为:
[0][1][0][0][0]
手指②的fingerId不变,还是1,这时候再按下第三个手指,数组变为:
[1][1][0][0][0]
手指②的fingerId不变,还是1,把数组的0号为给手指③,因此手指③的fingerId=0

1.3. Input类

Untiy的Input类中与Touch有关的API如下:

函数含义
Input.TouchCountint, 触控点数量,即当前按下的手指数
Input.touchesTouch[],当前所有的Touch结构体数组
Input.GetTouch(int index)返回第index个Touch,index与fingerId无关
Input.multiTouchEnabled{get;set;}是否支持多点触控

2. 多点触控

当存在多个摇杆时,需要控制每个摇杆对应的fingerId,这里把摇杆类命名为JoyStick,另外定义一个控制类TouchEvent用于管理Touch与JoyStick的对应关系,TouchEvent在每次Update中读取所有的Touch:

  1. 如果是新按下的就判断是否处于某个摇杆的可触发区域,如果是就绑定,并让该摇杆读取该Touch;
  2. 如果是已经按下的手指就判断是否有绑定的摇杆,如果有就让该摇杆读取该Touch;
  3. 如果是抬起的手指,也先判断是否有绑定并读取,然后移除这个绑定

代码如下:
TouchEvent.cs

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class TouchEvent : MonoBehaviour
{
    private Dictionary<int, JoyStick> id2JoyDic = new Dictionary<int, JoyStick>();//fingerId与摇杆的映射
    private List<JoyStick> joyList = new List<JoyStick>();//UI上所有的摇杆

    public void AddJoy(JoyStick joy)
    {
        joyList.Add(joy);//添加摇杆,由JoyStick在开始时调用
    }

    // Update is called once per frame
    void Update()
    {
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
        //鼠标模拟触控
        var touches = Input.touches.ToList();
        if(Input.GetMouseButtonDown(0))//如果有鼠标点击
        {
            var touch = new Touch();//模拟一个触控点
            touch.fingerId = 100;//给一个不会重复的fingerId
            touch.position = Input.mousePosition;//鼠标的位置
            touch.phase = TouchPhase.Began;//模拟按下
            touches.Add(touch);//加入到触控点列表
        }
        else if (Input.GetMouseButton(0))
        {
            var touch = new Touch();
            touch.fingerId = 100;
            touch.position = Input.mousePosition;
            touch.phase = TouchPhase.Moved;
            touches.Add(touch);
        }
        else if (Input.GetMouseButtonUp(0))
        {
            var touch = new Touch();
            touch.fingerId = 100;
            touch.position = Input.mousePosition;
            touch.phase = TouchPhase.Ended;
            touches.Add(touch);
        }
#endif

        foreach (var touch in touches)//遍历所有的触控点
        {
            if (touch.phase == TouchPhase.Began)//有新的触控点
            {
                foreach (var joy in joyList)
                {
                    if (joy.inTouchArea(touch.position) //判断是否在可触控范围内
                        && !id2JoyDic.ContainsValue(joy)) //如果对应的摇杆已经有触控点就忽略
                    {
                        id2JoyDic.Add(touch.fingerId, joy);//加入新的触控点,绑定摇杆
                    }
                }
            }

            if (id2JoyDic.ContainsKey(touch.fingerId))//如果该触控点已经绑定了摇杆
            {
                id2JoyDic[touch.fingerId].ReadTouch(touch);//读取触控操作
                if (touch.phase == TouchPhase.Canceled || touch.phase == TouchPhase.Ended)//已离开的触控点
                {
                    //移除触控点
                    id2JoyDic.Remove(touch.fingerId);
                }
            }
        }
    }
}

3. 摇杆实现思路

摇杆就是一个大圈+一个小圈组成,并且有一个可以触发的区域,如图:
在这里插入图片描述
矩形白色区域代表可以开始触控的区域,当手指按下时,把大圈的位置设为Touch的position,当手指滑动时,让小圈跟着动,并且限制它相对大圈的最大距离。
代码如下:
JoyStick.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class JoyStick : MonoBehaviour
{
    public TouchEvent touchEvent;//多点触控管理类
    public bool isFixedArea = false;//摇杆位置是否固定
    private RectTransform touchArea;//可以触控的范围
    public RectTransform circle;//摇杆的大圈
    public RectTransform point;//摇杆的小圈
    private float maxOffset;//摇杆离中心的最大距离
    //public float xAxis = 0;
    //public float yAxis = 0;
    public UnityEvent onDown, onDrag, onUp;//按下、滑动、抬起的事件
    // Start is called before the first frame update
    void Start()
    {
        touchArea = this.GetComponent<RectTransform>();
        maxOffset = Mathf.Min(circle.rect.width, circle.rect.height) / 2;//计算大圈的最小半径作为小圈的最大移动距离
        touchEvent.AddJoy(this);//注册摇杆
    }

    /// <summary>
    /// 读取触控操作,由TouchEvent调用
    /// </summary>
    /// <param name="touch"></param>
    public void ReadTouch(Touch touch)
    {
        if (touch.phase == TouchPhase.Began && !isFixedArea)
        {
            //如果手指按下
            circle.position = touch.position;//把大圈移动到手指按下的位置
            onDown.Invoke();//触发按下事件
        }
        else if ((touch.phase == TouchPhase.Began && isFixedArea) ||
            touch.phase == TouchPhase.Moved ||
            touch.phase == TouchPhase.Stationary)
        {
            //如果手指已经按下
            Vector3 prePointPos = point.position;//记录之前的位置
            Vector3 offset = new Vector3(touch.position.x, touch.position.y, 0) - prePointPos;//两帧的手指偏移量
            point.position += offset;//让小圈跟着动
            if ((point.position - circle.position).magnitude > maxOffset)
            {
                point.position = circle.position + (point.position - circle.position).normalized * maxOffset;//限制摇杆的移动
            }
            //xAxis = offset.x / maxOffset;//计算归一化偏移量
            //yAxis = offset.y / maxOffset;
            //print(string.Format("xAxis: {0} -- yAxis: {1}", xAxis, yAxis));

            onDrag.Invoke();//触发滑动事件
        }
        else if (touch.phase == TouchPhase.Ended)
        {
            //如果手指抬起
            point.position = circle.position;//重置小圈的位置到大圈的中心
            onUp.Invoke();//触发抬起事件
        }
    }

    /// <summary>
    /// 判断某一点是否在可触控范围(矩形)内,由TouchEvent调用
    /// </summary>
    /// <param name="pos"></param>
    /// <returns></returns>
    public bool inTouchArea(Vector2 pos)
    {
        Rect rect = touchArea.rect;
        rect.x += touchArea.position.x;
        rect.y += touchArea.position.y;
        return rect.Contains(pos);

    }

    public void OnDownTest()
    {
        print("down");
    }

    public void OnDragTest()
    {
        print("drag");
    }

    public void OnUpTest()
    {
        print("up");
    }
}

4. 代码使用

把TouchEven.cst挂在任意物体上,我这里挂在了EventSystem上
每一个摇杆如图中红框所示,

  1. Joy1是一个panel,它在屏幕上的大小就代表了可触发的区域
  2. circle是image,表示大圈
  3. joy是image,表示小圈
    在这里插入图片描述
    三个摇杆场景如图:
    在这里插入图片描述
    把JoyStick.cs挂在Joy1上,把circle赋给circle,joy赋给point,把TouchEvent也赋好值,如图:
    在这里插入图片描述

5. 在手机上实时调试

在手机上安装Unity Remote app,下载链接:
链接:https://pan.baidu.com/s/1moiz-4It5euHtpd86cLwgQ
提取码:z0fy
在Unity中点击edit->project settings,设置Editor,如图:
在这里插入图片描述
手机打开USB调试,连接电脑,然后运行,记得调整好分辨率
在这里插入图片描述

【unity3D】单点和多点触控 【狗刨学习网】 总结:     Input.touchCount获取当前的触摸点数目,若为1则是单点触控,大于1则是多点触控     点击事件用:Input.GetTouch(num).phase == TouchPhase.Began这样的格式 代码:     using UnityEngine;     using System.Collections; 阅读详情

相关推荐

Unity在移动端下禁用多点触控的方法

input事件与EventSystem分别对应的两种禁用多点触控的方法

woshi212534的博客 3324

Unity基础 单点和多点触摸

单点和多点触摸简单总结

weixin_45081191的博客 3734

Unity InputSystem移动端输入实战:虚拟摇杆与多点触控技能实现

在游戏开发中,输入处理是连接玩家与虚拟世界的桥梁,其核心在于将物理设备的操作信号转化为游戏逻辑可理解的动作指令。传统轮询式输入管理代码臃肿、难以维护,且难以优雅处理多点触控等复杂场景。Unity Input System 通过基于事件的架构,实现了输入逻辑与设备的解耦,开发者只需定义高层次的“动作”,系统便能自动处理底层输入事件。这一设计极大地提升了代码的可维护性和跨平台一致性,其技术价值在于为复杂交互提供了标准化、可扩展的解决方案。在移动游戏开发领域,这一特性尤为关键,能有效应对虚拟摇杆操控、多技能按钮同

weixin_28025327的博客 268

【Unity开发技能】TouchScript:多点触控解决方案

在移动设备或支持触摸输入的PC上进行项目开发时,我们经常需要实现一些基础的手势操作,如点击、平移、捏合和缩放。虽然这些手势可以通过Unity API或Asset Store中的包手动实现,但要让这些手势协同工作,例如在可缩放窗口上放置一个带点击手势的按钮,就需要一个更为强大的解决方案。这时,TouchScript便派上用场了,它使得在任何触摸表面上处理复杂的手势交互变得轻而易举。

Unity打怪升级 2541

Unity虚拟摇杆开发全攻略:从UGUI事件到移动端优化

虚拟摇杆作为移动端游戏和应用的核心交互组件,其原理基于触摸屏的坐标转换与事件处理机制。通过将屏幕触摸位置转换为标准化方向向量,实现了在触控设备上模拟传统手柄的精准方向控制。这一技术的价值在于为移动平台提供了复杂、连续的操作体验,是提升游戏可玩性和用户沉浸感的关键。在应用场景上,虚拟摇杆广泛用于移动游戏的角色移动、视角控制等需要精细操作的环节。本文深入探讨了在Unity中使用UGUI系统实现虚拟摇杆的完整方案,涵盖了事件处理、坐标转换、死区设置等核心细节,并针对移动端性能优化提供了实战建议,帮助开发者构建手感

weixin_29001419的博客 235

Unity虚拟摇杆开发实战:Joystick Pack插件集成与多模式适配方案

在移动端游戏开发中,虚拟摇杆是实现角色移动和视角控制的核心交互组件,其原理基于触控输入的事件捕获与向量转换。通过将屏幕触控位置映射为标准化方向向量,虚拟摇杆为玩家提供了直观的操控体验,其技术价值在于解决了移动设备缺乏物理输入设备的局限性。在动作、RPG和射击等游戏品类中,虚拟摇杆直接影响操作手感和玩家留存率。本文以Unity引擎的Joystick Pack插件为例,深入解析如何实现固定、浮动和动态三种操作模式的灵活适配,并分享屏幕自适应、性能优化等工程实践技巧,帮助开发者构建稳定高效的移动端操控系统。

weixin_34379433的博客 409

Unity3d_UGUI虚拟摇杆(简易)

之前的项目中有用虚拟摇杆来操纵角色移动,但是之前使用的是EasyTouch,属于NGUI下的一个插件,但是本身项目是基于UGUI的,觉得这样掺杂在一起有些不伦不类,就自己用UGUI做了一个简易的虚拟摇杆(可以实现给角色移动脚本发出摇杆的偏移参数类似于EasyTouch),若要实现更加复杂的功能,可以参照EasyTouch自行编写。        不多说下面开始实现步骤:(写这篇文章的时候离制作有

lfh719852029的博客 3197

Unity移动游戏输入系统设计:从多点触控到虚拟摇杆的完整解决方案

在移动游戏开发中,输入处理是连接玩家与虚拟世界的核心技术桥梁。其原理基于对触摸屏、陀螺仪等移动设备特有输入方式的精准捕获与解析,通过事件驱动架构将原始数据转化为游戏可用的高级指令。这一技术的核心价值在于,它能够将模糊、连续的触摸操作转化为精确、离散的游戏控制信号,从而解决多点触控手势识别、虚拟控制器手感优化等关键工程挑战。在应用场景上,无论是需要复杂手势的RPG、需要精准操控的ACT,还是依赖传感器输入的竞速游戏,一套健壮的输入框架都是保障操作流畅性与一致性的基石。本文聚焦于Unity引擎下的移动输入方案,

weixin_30706691的博客 334

Unity 2022 LTS虚拟摇杆开发:从架构设计到手感调校的工业级实现

在移动游戏开发中,输入控制是连接玩家与虚拟世界的核心桥梁。虚拟摇杆作为移动端最主流的输入方式之一,其原理是通过捕捉屏幕触摸坐标,将其转换为标准化的方向向量,驱动游戏角色或视角移动。这项技术的价值在于为触屏设备提供了精准、直观的操控体验,是动作、RPG及竞速等类型游戏的基石。在实际工程实践中,开发者需深入处理多点触控、坐标转换、性能优化及异形屏适配等挑战,以确保操作的稳定性和跟手性。本文将结合Unity 2022 LTS版本,详细解析如何构建一个高性能、手感出色的虚拟摇杆系统,涵盖从Input System集

weixin_34239592的博客 410

Unity移动端Input System实战:解决多点触控漂移、性能延迟与系统冲突

在移动游戏开发中,输入系统是连接玩家操作与游戏反馈的核心桥梁。其原理在于将屏幕触控、传感器等硬件信号转化为游戏可识别的逻辑事件。一个稳定高效的输入系统对于保障游戏操作手感、提升用户体验具有关键的技术价值,尤其在ARPG、MOBA等对实时性要求极高的应用场景中。然而,Unity新版Input System在移动平台上面临着碎片化设备与系统手势带来的独特挑战,例如多点触控ID漂移和GC(垃圾回收)压力导致的性能延迟。本文聚焦于这些移动端特有的痛点,提供经过项目验证的解决方案,帮助开发者构建更稳健的移动端输入架构

weixin_28693309的博客 265

Unity手游开发实录:用InputSystem优雅处理虚拟摇杆+多点触控(避坑iOS/Android)

本文详细介绍了在Unity手游开发中如何使用InputSystem优雅处理虚拟摇杆和多点触控,特别针对iOS和Android平台的适配问题提供了解决方案。通过优化摇杆手感、智能分区管理和输入优先级系统,开发者可以创建流畅、响应迅速的控制体验,有效解决移动设备上的输入精度和屏幕遮挡等核心挑战。

weixin_33793620的博客 385

Unity虚拟摇杆实现:UGUI事件系统与屏幕自适应全解析

在移动游戏开发中,触屏交互是连接玩家与虚拟世界的核心桥梁。其基本原理是将屏幕触摸的二维坐标,通过归一化处理映射为游戏逻辑可用的输入向量,从而实现角色移动、视角控制等操作。这一技术的核心价值在于解耦输入与具体行为,使同一套交互逻辑能够灵活适配不同的游戏状态和角色属性。在工程实践中,Unity的UGUI系统结合EventSystem提供了高效的事件管理方案,能够优雅处理多指触控与UI层级关系。对于虚拟摇杆这类高频交互组件,还需深入处理死区、非线性响应等手感调优细节,并应对不同设备分辨率和异形屏带来的适配挑战。本

既是过河之卒,惟有奋力向前。 439

避坑指南:Unity新版InputSystem在移动端的5个常见问题及解决方案

本文针对Unity新版InputSystem在移动端开发中的常见问题,提供了5个关键解决方案,包括虚拟摇杆灵敏度调节、多点触控冲突处理、按钮反馈延迟优化、手势识别与陀螺仪数据融合以及Android/iOS平台差异处理。这些实战经验帮助开发者高效解决触控适配难题,提升移动游戏体验。

soda5的博客 404

【Unity】InputSystem进阶:从UI控件到虚拟摇杆,打造跨平台输入适配方案

本文深入探讨Unity InputSystem在跨平台游戏开发中的应用,从UI控件到虚拟摇杆的实现,提供了一套完整的输入适配方案。通过InputSystem的输入抽象层,开发者可以轻松处理键盘、手柄和触摸屏等多种输入方式,显著提升开发效率和多平台兼容性。

weixin_29012677的博客 230

Unity虚拟摇杆完整实现:从UI搭建到角色移动与机型适配

移动端游戏缺少键盘鼠标,触摸输入成为核心交互方式,虚拟摇杆则是手游中控制角色移动与视角的通用方案。其原理并不复杂:通过触摸事件获取手指位置,借助RectTransformUtility将屏幕坐标转换到UI本地坐标,计算偏移量与归一化方向向量,再映射为角色的移动速度与朝向。技术价值在于统一的坐标转换与事件处理机制,能兼顾不同分辨率下的手感一致性和多点触控稳定性。该方案广泛应用于动作、MOBA、RPG等手游的操纵杆设计,也可扩展到固定摇杆/跟随摇杆、跳跃按钮、视角控制等组合交互。围绕Unity引擎,从UI搭建、

weixin_32479897的博客 250

基于Python的网络拓扑图绘制

最近写论文画了许多图,在这里记录一些。当然,如果仅仅是展示性图片的话也可以使用visio,但是这里我仍然想探究一下如何使用pyhon画出美观的网络拓扑图。(1)根据邻接矩阵画出网络拓扑图(2)画出网络拓扑图,并对节点和链路进行表示,包括对节点和链路的标号,颜色区分,以及尺寸区分。

m0_53961910的博客 7093

【Unity 移动端输入插件】Easy Mobile Input | 10 Joystick Images 提供了多种虚拟摇杆样式与按钮控制方式,使开发者能够轻松实现直观的移动、攻击、交互等操作

Easy Mobile Input | 10 Joystick Images 是一款专为Unity开发者设计的移动端输入插件,提供虚拟摇杆、触摸控制、按钮输入等功能,同时包含10种不同风格的摇杆图像。该插件适用于移动游戏,帮助开发者轻松实现直观的移动和交互控制。

2403_88403568的博客 680

动手学Moveit2|使用配置助手创建自己机械臂的功能包

今天没时间了,先生成功能包,下一步还需要装一些依赖才能运行,明天再补充下面的内容。

生活不止眼前的苟且 1万+

Unity3D学习交流(三)(萌新入)-安卓端触控方式的坑

oyStick 之前一直不知道移到手机上怎么操作,看到网上有人说,桌面端上的鼠标点击和手机上的触控点击是一样的,把电脑上的WSAD改成四个button就行,鼠标左键攻击也改成手机上的一个button,其他一些功能需要专门学习移动端的触控Touch方法,当时一想,改成button就很简单,Touch还是算了,懒得想,觉得很难。 后面实际操作时,又想到玩手机游戏都是左边有摇杆,想想还是摇杆更好,就搜了...

qq_39745907的博客 934

使用 Java + PaddleOCR 实现表格识别,支持导出 HTML 和 Excel(附源码)

使用Java+PaddleOCR快速搭建表格识别系统,无需处理底层模型细节。系统支持表格结构识别和内容识别,可将图片转换为可编辑表格格式。文章提供了完整的实现流程,包括Maven依赖引入、模型下载(包含检测、识别、分类和表格结构模型)及参数配置说明。SmartJavaAI支持多种高性能模型选择,适用于不同应用场景,帮助开发者快速实现表格识别功能。

deng775747758的博客 1473

Keras深度学习实战(32)——基于LSTM预测股价

股价预测是时间序列预测中最具挑战性的问题之一,研究股价预测问题具有重要的理论意义和应用价值。针对循环神经网络在股价预测中存在的长期依赖等缺点,本文引入了长短时记忆神经网络以提高股价预测的效果。同时,我们把有关公司的新闻标题的文本数据作为模型的输入变量时,发现预测效果更好,因此我们可以把有关公司的新闻标题的文本数据作为一个有效的输入变量。最后,通过利用 Keras 实现了以上两个股价预测模型,并进行了性能分析和对比。

盼小辉丶的博客 1万+

【Unity 触控输入系统插件】Touch Controls Kit 专门用于在移动设备(iOS、Android)或触屏平台上快速实现直观、灵活的操控体验

Touch Controls Kit 是一款为 Unity 设计的高质量触控输入系统插件,专门用于在移动设备(iOS、Android)或触屏平台上快速实现直观、灵活的操控体验。它提供了丰富的虚拟摇杆、按钮、滑动条等控件,适合开发动作、射击、驾驶、冒险等多类型游戏。

2403_88403568的博客 697

Qt —— 在Win11下“Qt for Android“开发环境,通过USB在真机(华为Meta60 PRO)上调试运行,并打包APK并在真实手机运行

Qt —— 在Win11下“Qt for Android“开发环境,打包APK并在真实手机运行

311
上一篇: python matplotlib调整图像比例
realfancy
博客等级 码龄9年 70粉丝 34原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值