当前位置: 首页 > backend >正文

【Unity输入系统】自定义与双击不冲突的单击Interaction

一、背景

unity自带的两种默认interaction——单击(tap)、多击(multip tap)在实际使用时可以发现,假设有多个action,action A绑定了按键A单击,action B绑定了按键A双击,则双击按键A时会导致action A也触发。为了规避这种情况,自定义了一个与双击不冲突的单击Interaction

二、思路及代码

  • 在检测到点击后延迟一小段时间(clickDelay)再判断(确认是否有第二次点击)是否进入perform状态

  • 如果在 clickDelay 期间没有再次点击,并且按住的时间不超过 holdThreshold,就判定为 单击

  • 如果超过 holdThreshold 就是 长按(取消单击逻辑)。

  • 如果在 clickDelay 时间内再次按下,则判断为 双击,取消单击逻辑。

using System.Diagnostics;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.Utilities;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SingleClickOnlyIfNotDouble : IInputInteraction
{public float clickDelay = 0.3f;      // 点击后的等待时间,用于检测是否为双击(单位:秒)public float holdThreshold = 0.3f;   // 判定为长按的最小时间(单位:秒)private double m_TapStartTime;       // 记录第一次按下的时间点bool hasClicked = false;            // 标记是否已经处理过一次点击#if UNITY_EDITOR[UnityEditor.InitializeOnLoadMethod]
#else[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
#endifpublic static void Initialize(){InputSystem.RegisterInteraction<SingleClickOnlyIfNotDouble>();}public void Process(ref InputInteractionContext context){switch (context.phase){case InputActionPhase.Waiting:if (context.control is ButtonControl button && button.wasPressedThisFrame){m_TapStartTime = context.time;context.Started();context.SetTimeout(clickDelay);}break;case InputActionPhase.Started:if (context.control is ButtonControl button2){if (button2.wasReleasedThisFrame && !hasClicked){// UnityEngine.Debug.Log("按住时间" + (context.time - m_TapStartTime) + hasClicked);if (context.time - m_TapStartTime <= holdThreshold)//松手且未超时才判定为单击{// UnityEngine.Debug.Log("按住时间" + (context.time - m_TapStartTime) + hasClicked);hasClicked = true;// UnityEngine.Debug.Log("单击检测");}else{context.Canceled();// UnityEngine.Debug.Log("Hold detected → canceled");}}if (hasClicked){if (context.time - m_TapStartTime >= clickDelay){context.Performed();// UnityEngine.Debug.Log("Single click performed");}else if (button2.wasPressedThisFrame){context.Canceled();// UnityEngine.Debug.Log("Double click detected → canceled");}}}break;}}public void Reset(){hasClicked = false;}
}

需要注意的是,

  •  m_TapStartTime不能被context.startTime替代,context.startTime和context.time并不会在每次触发该interaction时重置,startTime是一个固定值,time是一个累计值,这会导致算出的时间差越来越长
  • clickDelay和holdThreshold的时间设置无关,因为一个是针对第一次按住检测,一个是针对第一次按下后检测。
  • holdThreshold设置应短于Hold的HoldTime,否则会导致其单击操作无法与Hold区分
  • clickDelay设置应长于MultiTap的Max Tap Spacing,否则会导致其单击操作无法与双击区分

三、参考

【Unity】Input Systemでシングルタップとマルチタップを判別する | ねこじゃらシティ

【Unity】Input SystemのInteractionの仕組みと使い方 | ねこじゃらシティ

https://docs.unity3d.com/Packages/com.unity.inputsystem@1.7/manual/Interactions.html#default-interaction

http://www.xdnf.cn/news/17192.html

相关文章:

  • 零基础-动手学深度学习-9.3. 深度循环神经网络
  • 深度学习(2):自动微分
  • 数据结构——栈、队列
  • STM32——STM32CubeMX
  • Keil MDK-ARM V5.42a 完整安装教程
  • Git Status 命令深度指南:洞悉仓库状态的核心艺术
  • 【YOLOv8改进 - C2f融合】C2f融合SFS-Conv(空间 - 频率选择卷积)提升特征多样性,同时减少参数和计算量
  • cuda编程笔记(13)--使用CUB库实现基本功能
  • 一个自动定位并查询天气的工具(c语言)
  • Liberica JDK 和普通JDK(如Oracle JDK、OpenJDK等)的差异
  • 经营帮:重构企业经营全流程,打造产业互联网新生态
  • Spring IoC 容器核心流程(面试必懂)
  • QT项目 -仿QQ音乐的音乐播放器(第五节)
  • 光伏电站巡检的智能化转型
  • 《算法导论》第 10 章 - 基本数据结构
  • Spark Memory 内存设计的核心组件、对比Flink内存配置
  • Moses工具的配置和小语种平行语料训练SMT完整实现
  • iptables封堵实验
  • NFS 服务器
  • 贪心+矩阵算法
  • Go语言Ebiten坦克大战
  • mysql 索引失效分析
  • 【数据结构】二叉树练习
  • 从BaseMapper到LambdaWrapper:MyBatis-Plus的封神之路
  • 【Unity3D实例-功能-镜头】第三人称视觉-镜头优化
  • Oracle 12c + Pl/Sql windows系统下表空间创建、迁移,dmp备份导入,数据库字符集更改
  • Oracle exp imp expdp impdp 命令详解
  • 如何快速开发符合Matter标准的智能家居设备?
  • 一个程序通过 HTTP 协议调用天气 API,解析 JSON 格式的天气数据,提取关键信息并格式化输出:日期、天气状况、温度范围、风向、湿度等核心气象数据。
  • 锡膏种类多,不同的锡膏有什么区别,该如何正确选择?