目录
前言:
一、InputSystem简介
1.安装InputSystem包
2.创建配置文件
3.创建自定义的Actions
二、自定义输入类
三、改键
四、全代码
前言:
新版inputsystem是Unity推出的一种新的输入方式,它将设备与行为进行分离,通过配置文件,更利于用户直接进行按键修改与配置。
一、InputSystem简介
这一部分主要是对InputSystem的简单介绍,我会通过代码形式来进行按键逻辑的编写,因为代码更加灵活。当然,如果是不复杂的项目,使用InputSystem内置的组件进行配置也是ok的,但这里就不会去介绍这一部分的操作了。就简单放张图吧
1.安装InputSystem包
首先到PackageManager里去安装包,然后会有提示框,进行重启就行。
到Edit=ProjectSetting里的Player中设置输入,当然可以使用Both,我这里用的是InputSystemPackage,Both就是会包括旧版的InputManager,既然是讲InputSystem的,我就只用它了。
2.创建配置文件
鼠标右键Create-InputAction,就会创建一个配置文件,给它重命名都行。
在InputAction文件中,可以生成C#类,它的路径,类命,命名空间都可以自定义,因为要使用脚本来处理短按长按逻辑,所以需要勾上生成C#类。
3.配置InputAction
点击InputAction文件中的Editasset按钮,就会进入下面的设置界面
其中
ActionMaps | 显示当前定义的 Action Maps 的列表。每个操作映射都是一组操作,您可以作为一个组一起启用或禁用这些操作。 |
Actions | 显示在当前选定的 Action Map 中定义的所有操作,以及与每个 Action 关联的绑定。 |
ActionProperties | 显示 Actions 面板中当前选定的 Action 或 Binding 的属性。此面板的标题会根据您在 Actions 面板中选择的是 Action 还是 Binding而发生变化。 |
有些不好理解是吧,实际呢,ActionMaps就像是一张表,这张表里有我们需要的一些操作,而且每个操作都有其对应的属性,这些属性可以是一个按钮,一个值。
3.创建自定义的Actions
稍微解释一下,这里呢我创建了一个名为Game的ActionMap,其中有一个叫做Tap的Action,它的行为类型是按钮。
Value | 提供一种连续状态变化事件,如果设置了多个输入,就会切换到最主要的一个。用它进行模拟控制,比如移动。 |
Button | 默认设置,包括按钮或者按键触发的一次性动作 |
Pass Through | 和Value很相似,但它不会像Value一样(如果有多个输入时,不会只选择最主要的那个,而把其他的输入忽略) |
在使用Value或者Pass Through Types时,你会看到一个额外的选项 Control Type为该Value的返回值类型
在Interactions一栏添加了一个Hold类型(长按类型)
Hold | 按下并按住至少设定的持续时间(默认为defaultHoldTime),则执行动作。(长按执行操作) |
MultiTap | 需要多次轻击(在tapTime内按下并释放),每次轻击之间的间隔不超过tapDelay秒(双击或多击) |
Press | 根据按钮的按下和释放顺序来触发特定的操作(例如:在按下按钮后执行某个动作或在释放按钮时执行某个操作) |
SlowTap | 按下并按住控件一段时间后释放时执行操作(长按释放后执行操作) |
Tap | 按下并按住小段时间内释放执行操作(点击) |
而添加的绑定则是1DAxis,即如果输入的是负,则返回-1,输入的正则返回1,不输入则无,这样的绑定可以处理两个按键的逻辑。
当点击键盘A的时候返回-1,当点击键盘D的时候返回1。
配置好后,就可以保存文件,Unity会开始生成C#类。
二、自定义输入类
inputControls就是生成的C#类,而Input则会是我们自定义得输入类。
短按很好处理,就只要在用户点击按钮的那一刻判断为点击就可
而长按则需要用户进入到特定的时间点才能触发,而且它的逻辑也需要单独处理。
在按键检测过程中若是进入了长按交互,就开始进行判断是否是对应的按键。
编写测试脚本来测试一下
测试结果:
三、改键
InputSystem在配置输入时可以看到有绑定按键的操作,我们改键的操作就是通过代码来修改这个路径。点击旁边的T可以看到路径是什么。
打开生成的C#类可以在开头看到一段Json格式的代码,我们可以将其保存为Json文件,这样就可以做成持久的改键设置。思路是如此,这里我就不做操作了,下面实现的将是直接修改按键的代码。
先上代码
原理很简单,就是通过输入的按键,获取其路径,然后将绑定的path修改为新的改键路径。
ApplyBindingOverride函数中的index就是层级顺序,下面标注出来顺序
写个测试脚本:
测试结果如下:
四、全代码
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;public enum InputBindlingEnum
{Left,Right
}public class Input
{private InputControls actions;public bool tap_left { get { return actions.Game.Tap.WasPressedThisFrame() && actions.Game.Tap.ReadValue<float>() == -1; } }public bool tap_right { get { return actions.Game.Tap.WasPressedThisFrame() && actions.Game.Tap.ReadValue<float>() == 1; } }public bool hold_left { get; private set; }public bool hold_right { get; private set; }public Input(){actions = new InputControls();actions.Game.Tap.started += ctx =>{hold_left = false;hold_right = false;};actions.Game.Tap.performed += ctx =>{if (ctx.interaction is HoldInteraction){hold_left = actions.Game.Tap.ReadValue<float>() == -1;hold_right = actions.Game.Tap.ReadValue<float>() == 1;}};actions.Game.Tap.canceled += ctx =>{hold_left = false;hold_right = false;};actions.Game.Enable();}public void ChangeBinding(InputBindlingEnum inputBindling, KeyCode key){if (actions == null)return;if (actions.Game.enabled)actions.Game.Disable();InputBinding binding = new InputBinding();switch (inputBindling){case InputBindlingEnum.Left:binding = actions.Game.Tap.bindings[1];break;case InputBindlingEnum.Right:binding = actions.Game.Tap.bindings[2];break;}string keyName = System.Enum.GetName(typeof(KeyCode), key);if (keyName.Contains("Alpha"))keyName = keyName.Substring(5);else if (keyName.Contains("Keypad"))keyName = keyName.Substring(6);else if (keyName.Length > 1)keyName = keyName.Substring(0, 1).ToLower() + keyName.Substring(1);elsekeyName = keyName.ToLower();binding.overridePath = $"<Keyboard>/{keyName}";switch (inputBindling){case InputBindlingEnum.Left:actions.Game.Tap.ApplyBindingOverride(1, binding);break;case InputBindlingEnum.Right:actions.Game.Tap.ApplyBindingOverride(2, binding);break;}#if UNITY_EDITORDebug.Log("成功绑定按键:" + inputBindling + ": from " + binding.path + " to " + binding.overridePath);
#endifif (!actions.Game.enabled)actions.Game.Enable();}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test : MonoBehaviour
{private Input input;private void Awake(){if (input == null)input = new Input();input.ChangeBinding(InputBindlingEnum.Left, KeyCode.LeftArrow);}private void Update(){if (input.tap_left){Debug.Log("tap_left");}if (input.tap_right){Debug.Log("tap_right");}if (input.hold_left){Debug.Log("hold_left");}if (input.hold_right){Debug.Log("hold_right");}}
}