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

【Unity学习笔记】New Input System 部分源码和测试用例补充

转载请注明出处:🔗https://blog.csdn.net/weixin_44013533/article/details/135630016
作者:CSDN@|Ringleader|

主要参考:

  • Unity官方Input System手册与API
  • 【Unity学习笔记】Unity TestRunner使用
  • 【Unity学习笔记】第十二 · New Input System 及其系统结构 和 源码浅析

注:本文使用的unity版本是2021.3.25f,InputSystem版本为1.5.1

deafault Interaction测试用例

  1. ButtonAndValue

    [Test]
    public void Actions_ButtonActions_RespectButtonPressPoints()
    {InputSystem.settings.defaultButtonPressPoint = 0.5f;InputSystem.settings.buttonReleaseThreshold = 0.9f; // Release at 90% of press point puts release at 0.45.// Customize gamepad with specific button press point on right trigger (but not on left).InputSystem.RegisterLayoutOverride(@"{""name"" : ""GamepadRightTriggerWithPressPoint"",""extend"" : ""Gamepad"",""controls"" : [{ ""name"" : ""rightTrigger"", ""parameters"" : ""pressPoint=0.75"" }]}");var gamepad = InputSystem.AddDevice<Gamepad>();var rightTriggerButton = new InputAction(type: InputActionType.Button, binding: "<Gamepad>/rightTrigger");var rightTriggerValue = new InputAction(type: InputActionType.Value, binding: "<Gamepad>/rightTrigger");var leftTriggerButton = new InputAction(type: InputActionType.Button, binding: "<Gamepad>/leftTrigger");var leftTriggerValue = new InputAction(type: InputActionType.Value, binding: "<Gamepad>/leftTrigger");rightTriggerButton.Enable();rightTriggerValue.Enable();leftTriggerButton.Enable();leftTriggerValue.Enable();using (var rightTriggerButtonTrace = new InputActionTrace(rightTriggerButton))using (var rightTriggerValueTrace = new InputActionTrace(rightTriggerValue))using (var leftTriggerButtonTrace = new InputActionTrace(leftTriggerButton))using (var leftTriggerValueTrace = new InputActionTrace(leftTriggerValue)){Set(gamepad.leftTrigger, 0.25f);Set(gamepad.rightTrigger, 0.25f);// Have crossed neither button threshold. Actions start but don't perform.Assert.That(leftTriggerButtonTrace, Started(leftTriggerButton, gamepad.leftTrigger, value: 0.25f));Assert.That(rightTriggerButtonTrace, Started(rightTriggerButton, gamepad.rightTrigger, value: 0.25f));Assert.That(leftTriggerValueTrace,Started(leftTriggerValue, gamepad.leftTrigger, value: 0.25f).AndThen(Performed(leftTriggerValue, gamepad.leftTrigger, value: 0.25f)));Assert.That(rightTriggerValueTrace,Started(rightTriggerValue, gamepad.rightTrigger, value: 0.25f).AndThen(Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.25f)));rightTriggerButtonTrace.Clear();rightTriggerValueTrace.Clear();leftTriggerButtonTrace.Clear();leftTriggerValueTrace.Clear();Set(gamepad.leftTrigger, 0.6f);Set(gamepad.rightTrigger, 0.6f);// Have grossed global but not right trigger threshold.Assert.That(leftTriggerButtonTrace, Performed(leftTriggerButton, gamepad.leftTrigger, value: 0.6f));Assert.That(rightTriggerButtonTrace, Is.Empty);Assert.That(leftTriggerValueTrace, Performed(leftTriggerValue, gamepad.leftTrigger, value: 0.6f));Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.6f));rightTriggerButtonTrace.Clear();rightTriggerValueTrace.Clear();leftTriggerButtonTrace.Clear();leftTriggerValueTrace.Clear();Set(gamepad.leftTrigger, 0.9f);Set(gamepad.rightTrigger, 0.9f);// No change on left trigger action, right trigger crossed threshold.Assert.That(leftTriggerButtonTrace, Is.Empty);Assert.That(rightTriggerButtonTrace, Performed(rightTriggerButton, gamepad.rightTrigger, value: 0.9f));Assert.That(leftTriggerValueTrace, Performed(leftTriggerValue, gamepad.leftTrigger, value: 0.9f));Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.9f));rightTriggerButtonTrace.Clear();rightTriggerValueTrace.Clear();leftTriggerButtonTrace.Clear();leftTriggerValueTrace.Clear();Set(gamepad.leftTrigger, 0.6f);Set(gamepad.rightTrigger, 0.6f);// No change on left trigger action, right trigger action cancels.Assert.That(leftTriggerButtonTrace, Is.Empty);Assert.That(rightTriggerButtonTrace, Started(rightTriggerButton, gamepad.rightTrigger, value: 0.6f));Assert.That(leftTriggerValueTrace, Performed(leftTriggerValue, gamepad.leftTrigger, value: 0.6f));Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.6f));rightTriggerButtonTrace.Clear();rightTriggerValueTrace.Clear();leftTriggerButtonTrace.Clear();leftTriggerValueTrace.Clear();Set(gamepad.leftTrigger, 0.4f);Set(gamepad.rightTrigger, 0.4f);// Left trigger cancels, right trigger *starts* again (but doesn't perform).Assert.That(leftTriggerButtonTrace, Started(leftTriggerButton, gamepad.leftTrigger, value: 0.4f));Assert.That(rightTriggerButtonTrace, Is.Empty);Assert.That(leftTriggerValueTrace, Performed(leftTriggerValue, gamepad.leftTrigger, value: 0.4f));Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.4f));rightTriggerButtonTrace.Clear();rightTriggerValueTrace.Clear();leftTriggerButtonTrace.Clear();leftTriggerValueTrace.Clear();Set(gamepad.leftTrigger, 0f);Set(gamepad.rightTrigger, 0f);// No change on left and right trigger actions.Assert.That(leftTriggerButtonTrace, Canceled(leftTriggerButton, gamepad.leftTrigger, 0f));Assert.That(rightTriggerButtonTrace, Canceled(rightTriggerButton, gamepad.rightTrigger, 0f));Assert.That(leftTriggerValueTrace, Canceled(leftTriggerValue, gamepad.leftTrigger, value: 0f));Assert.That(rightTriggerValueTrace, Canceled(rightTriggerValue, gamepad.rightTrigger, value: 0f));rightTriggerButtonTrace.Clear();leftTriggerButtonTrace.Clear();// Make sure that we start and cancel if we press the buttons just a little and then release.Set(gamepad.leftTrigger, 0.25f);Set(gamepad.rightTrigger, 0.25f);Assert.That(leftTriggerButtonTrace, Started(leftTriggerButton, gamepad.leftTrigger, value: 0.25f));Assert.That(rightTriggerButtonTrace, Started(rightTriggerButton, gamepad.rightTrigger, value: 0.25f));rightTriggerButtonTrace.Clear();leftTriggerButtonTrace.Clear();Set(gamepad.leftTrigger, 0f);Set(gamepad.rightTrigger, 0f);Assert.That(leftTriggerButtonTrace, Canceled(leftTriggerButton, gamepad.leftTrigger, value: 0f));Assert.That(rightTriggerButtonTrace, Canceled(rightTriggerButton, gamepad.rightTrigger, value: 0f));}
    }
    
  2. passthrough

    [Test]
    public void Actions_passthroughActions()
    {var gamepad = InputSystem.AddDevice<Gamepad>();var rightTriggerValue = new InputAction(type: InputActionType.PassThrough, binding: "<Gamepad>/rightTrigger");rightTriggerValue.Enable();using (var rightTriggerValueTrace = new InputActionTrace(rightTriggerValue)){Set(gamepad.rightTrigger, 0.25f);Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.25f));rightTriggerValueTrace.Clear();Set(gamepad.rightTrigger, 0.6f);Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.6f));rightTriggerValueTrace.Clear();Set(gamepad.rightTrigger, 0.9f);Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0.9f));rightTriggerValueTrace.Clear();Set(gamepad.rightTrigger, 0f);Assert.That(rightTriggerValueTrace, Performed(rightTriggerValue, gamepad.rightTrigger, value: 0f));rightTriggerValueTrace.Clear();}
    }
    

Press Interaction测试用例

using System.Diagnostics.CodeAnalysis;
using NUnit.Framework;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;namespace Scenes.TestAction
{[SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")]public class TestAction : InputTestFixture{[Test][TestCase(InputActionType.Value)][TestCase(InputActionType.Button)][TestCase(InputActionType.PassThrough)]public void Actions_PressOnly(InputActionType type){var gamepad = InputSystem.AddDevice<Gamepad>();InputSystem.settings.defaultButtonPressPoint = 0.5f;InputSystem.settings.buttonReleaseThreshold = 0.75f; // Puts release point at 0.375.var action = new InputAction(type:type, binding: "<Gamepad>/leftTrigger", interactions: "press(behavior=0)");action.Enable();using (var trace = new InputActionTrace(action)){Set(gamepad.leftTrigger, 0.35f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.35f));trace.Clear();Set(gamepad.leftTrigger, 0.5f);Assert.That(trace, Performed(action, control: gamepad.leftTrigger, value: 0.5f));trace.Clear();Set(gamepad.leftTrigger, 0.6f);Assert.That(trace, Is.Empty);Set(gamepad.leftTrigger, 0.4f);Assert.That(trace, Is.Empty);Set(gamepad.leftTrigger, 0.3f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.3f));trace.Clear();Set(gamepad.leftTrigger, 0);Assert.That(trace, Canceled(action, control: gamepad.leftTrigger, value: 0));}}[Test][TestCase(InputActionType.Value)][TestCase(InputActionType.Button)][TestCase(InputActionType.PassThrough)]public void Actions_RealeasOnly(InputActionType type){var gamepad = InputSystem.AddDevice<Gamepad>();InputSystem.settings.defaultButtonPressPoint = 0.5f;InputSystem.settings.buttonReleaseThreshold = 0.75f; // Puts release point at 0.375.var action = new InputAction(type:type, binding: "<Gamepad>/leftTrigger", interactions: "press(behavior=1)");action.Enable();using (var trace = new InputActionTrace(action)){Set(gamepad.leftTrigger, 0.35f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.35f));trace.Clear();Set(gamepad.leftTrigger, 0.5f);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.6f);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.4f);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.3f);Assert.That(trace,Performed(action, control: gamepad.leftTrigger, value: 0.3f).AndThen(Canceled(action, control: gamepad.leftTrigger, value: 0)));trace.Clear();Set(gamepad.leftTrigger, 0.1f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.1f));trace.Clear();Set(gamepad.leftTrigger, 0);Assert.That(trace, Canceled(action, control: gamepad.leftTrigger, value: 0));trace.Clear();Set(gamepad.leftTrigger, 0.4f);Set(gamepad.leftTrigger, 0.3f);//onlyRelease 不超过press-threshold只回落release是不会触发的Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.4f));trace.Clear();}}[Test][TestCase(InputActionType.Value)][TestCase(InputActionType.Button)][TestCase(InputActionType.PassThrough)]public void Actions_PressAndRelease(InputActionType type){var gamepad = InputSystem.AddDevice<Gamepad>();InputSystem.settings.defaultButtonPressPoint = 0.5f;InputSystem.settings.buttonReleaseThreshold = 0.75f; // Puts release point at 0.375.var action = new InputAction(type:type, binding: "<Gamepad>/leftTrigger", interactions: "press(behavior=2)");action.Enable();using (var trace = new InputActionTrace(action)){Set(gamepad.leftTrigger, 0.35f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.35f));trace.Clear();Set(gamepad.leftTrigger, 0.5f);Assert.That(trace, Performed(action, control: gamepad.leftTrigger, value: 0.5f));trace.Clear();Set(gamepad.leftTrigger, 0.6f);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.4f);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.3f);Assert.That(trace,Performed(action, control: gamepad.leftTrigger, value: 0.3f));trace.Clear();Set(gamepad.leftTrigger, 0);Assert.That(trace, Is.Empty);trace.Clear();Set(gamepad.leftTrigger, 0.9f);Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.9f).AndThen(Performed(action, control: gamepad.leftTrigger, value: 0.9f)));trace.Clear();Set(gamepad.leftTrigger, 0);Assert.That(trace, Performed(action, control: gamepad.leftTrigger, value: 0f).AndThen(Canceled(action, control: gamepad.leftTrigger, value: 0f)));trace.Clear();Set(gamepad.leftTrigger, 0.4f);Set(gamepad.leftTrigger, 0.3f);//press&release 不超过press-threshold只回落release是不会触发的Assert.That(trace, Started(action, control: gamepad.leftTrigger, value: 0.4f));trace.Clear();}}}}

UnityEvent方式注册回调关键逻辑

  1. PlayerInput.InitializeActions()
    UnityEvent方式注册回调的核心在于PlayerInput组件enable时进行InitializeActions初始化操作
    在这里插入图片描述
  2. PlayerInputEditor
    但对于上面ActionEvent的eventId怎么匹配上actionId,则要看PlayerInputEditor.OnInspectorGUI()OnActionAssetChange()
    在这里插入图片描述
  3. UnityEvent<T0>
    上面action触发后,对应actionEvent调用Invoke,但此时真正的回调方法并没有注册,是在下面的InvokableCall中注册的,最后在InvokableCall.Invoke中执行最终的方法回调,处理输入处理。
    在这里插入图片描述
  4. InvokableCall<T1> 注册回调
    在这里插入图片描述
    从上面看,UnityAction方式远比原生C#事件复杂得多。(而且我也并没完全弄懂)

相关文章:

  • 数学建模学习笔记||层次分析法
  • C# 创建多线程的函数
  • LeetCode59 螺旋矩阵 II
  • 轻量化CNN网络 - MobileNet
  • 知识笔记(八十九)———链式语句中partition和strict用法
  • spring和springboot、springMVC有什么区别?
  • C# CefSharp 根据输入日期段自动选择日期
  • LeetCode454. 四数相加 II和1.两数之和
  • 探索全球DNS体系 | 从根服务器到本地解析
  • Ubuntu 22.04 LTS 安装使用腾达(Tenda) W311MIv6 AX300 无线网卡
  • Elasticsearch:介绍 kNN query,这是进行 kNN 搜索的专家方法
  • 如何在科技创新中发挥国有企业的战略支撑作用?
  • 使用AFPN渐近特征金字塔网络优化YOLOv8改进小目标检测效果(不适合新手)
  • vue3-组件基础
  • Next-GPT: Any-to-Any Multimodal LLM
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Javascript基础之Array数组API
  • maya建模与骨骼动画快速实现人工鱼
  • QQ浏览器x5内核的兼容性问题
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Terraform入门 - 1. 安装Terraform
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Vue组件定义
  • 分布式任务队列Celery
  • 聊聊flink的BlobWriter
  • 那些被忽略的 JavaScript 数组方法细节
  • 深入浏览器事件循环的本质
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 数组的操作
  • 一个SAP顾问在美国的这些年
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 昨天1024程序员节,我故意写了个死循环~
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #Spring-boot高级
  • %@ page import=%的用法
  • (1)(1.9) MSP (version 4.2)
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (接口自动化)Python3操作MySQL数据库
  • (论文阅读40-45)图像描述1
  • (四)JPA - JQPL 实现增删改查
  • .netcore 获取appsettings
  • .net反编译的九款神器
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .net流程开发平台的一些难点(1)
  • .net网站发布-允许更新此预编译站点
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [Android]RecyclerView添加HeaderView出现宽度问题