• untiy 新输入系统 InputSytem


    一 前言

    新输入系统的名字就叫InputSystem,新是相对于旧的InputManager来说的

    核心思想是添加一个动作(action)的概念,代码只监听动作的触发,由动作去绑定物理输入,这样无论什么平台,无论如何重新指定物理输入,我们都不需要修改代码
    同时也可以将同一个物理输入同时绑定到不同的输入动作集中,随时切换输入动作集,例如上车后,从走路的动作集切换到开车的动作集。

    此外还提供了一些方便的功能,例如使用代码重新绑定按键、屏幕按键等、检测设备接入拔出、组合键、次要绑定等。

    二 安装

    InputSystem不是默认安装的,我们需要使用packagemanager来安装他。
    建议使用2019之后的版本
    打开packageManager,在unityRegistery里搜索,然后安装即可,安装过程中你的编辑器会需要重启一次。
    如果你打开包管理器不显示包,那么你需要退出编辑器,刷新一下通行证,重新打开即可。
    在这里插入图片描述

    新建一个输入资产

    有两种方法可以创建输入
    1 通过Project面板右键菜单Create/InputAction创建一个新的输入资产,这将创建一个全新的资产。
    2 为一个物体添加一个PlayerInput组件,点击create按钮,这会创建一个带有默认输入的资产。
    在这里插入图片描述
    创建新的输入资产的时候必须小心的命名,不要随便起个名字,因为之后创建的带有输入动作的c#脚本会叫这个名字,瞎起名字是给自己找麻烦

    三 InputActions面板

    这个面板的作用是管理一个InputActionAssets的action和对应的映射。
    双击一个输入资产即可打开这个面板。
    在这里插入图片描述
    以下是详细解释

    区域1 工具栏

    controlSchemes 控制方案

    在这里插入图片描述
    默认是只有AllControlSchemes的,可以使用AddControlScheme创建新的输入方案,随后可以为action的一个物理输入指定自己的输入方法,当我们切换输入方案时,就可过滤这个方案下的action了,注意方案只是一个名字,没有任何实际意义,你完全可以起一个名字叫gamepad的方案,但是为keyboard action指定这个方案。

    删除控制方案时,如果由物理输入会让我们选择是否要连同绑定的物理输入一同删除,选yes会删除所有指定为当前方案的物理输入绑定,选no只会删除这个控制方案,而保留绑定的物理输入
    在这里插入图片描述

    saveAsset和Auto-Save

    不建议使用Auto-Save,因为我们需要为aciton创建一个c#文件才能在脚本中调用,使用了Auto-Save时,如果我们已经创建了这个脚本,每当我们做出改变,都会重新编译脚本,这将非常痛苦

    区域2 actionMaps 动作映射集

    我们可以在这里定义不同的映射集,走路动作映射集、开车动作映射集、UI动作集等
    点击+号即可创建新的动作集

    区域3 actions 区域4 属性面板

    这两个要一起看
    actions: 一个actionMaps里的所有action,用于创建action并为action绑定物理按键
    Properties: action或binding的属性

    1 action与bingding的创建与删除

    点击atcions的加号即可创建一个新的action(绿色),新action默认自带一个绑定(蓝色),只不过目前这个绑定还没有绑定任何物理按键
    在这里插入图片描述
    右键action即可删除action
    点击action后的+号并选择一个绑定类型即可创建一个新的bingding(蓝色)
    右键bindging即可选择删除

    2 action的属性

    Action 这是action属性栏里第一个属性
    创建好aciton后,我们第一步要确定action的类型,选中一个action(绿色),右侧属性面板会显示这个action的选项
    有value和button和Pass Through三种类型

    • value:可以将输入转化为值,可以在ControlType属性中选择具体的类型,通常使用Axis(一维)、Vector2、Vector3,通常用来制作移动、视角旋转、读取摇杆输入值等。
    • button:按下触发,没什么好说的
    • Pass Through: 例如你插了多个手柄,那么所有的手柄都会同时影响这个action,上面两种方式是只有当前有输入传入的手柄会影响这个action,除非你希望你的action同时被多个物理设备控制,否则不要使用这个选项

    注意修改了aciton的类型后,会影响action可以创建的物理输入的选项
    在这里插入图片描述
    Interactions 如何交互
    可以指定这个action如何交互
    点击+号添加一个新的交互方式
    常用的交互有Hold按住一段时间后触发,MultiTop,多次点击等,见名知意,不多废话。
    如果什么都不加,则为默认的交互方式。
    Processors 定义如何处理获取到的值
    可选项有

    • Axis Deadzone:轴死区 当摇杆输入小于Min,不会触发摇杆,通常用于防止摇杆漂移问题。如果输入大于Max,认为都是1。在Min和Max之间插值
    • Clamp:钳制输入的值,不能小于Min,不能大于Max
    • Invert: 翻转输入的值,例如输入的值为1,则实际得到的值为-1
    • Normalize: 归一化值,你总能得到1 0 -1,通常用于摇杆
    • Scale:缩放输入的值
    3 Bindin属性

    创建绑定的注意事项
    点击一个action后的+号,然后选择一个具体类型,即可创建一个绑定
    根据action的类型不同,可以选择的binding类型是不同的
    当action的ActionType为Button时,我们可以创建的类型有

    • Binding:普通按钮,只能绑定一个按键
    • Positive/Negative:,需要分别为Positive和Negative绑定两个按键
    • Binding With Modifier: 组合键

    当action为Value类型时,我们可以创建的类型通常有Binding和Up/Down/Left/Right,显然这是用来用键盘控制方向的
    在这里插入图片描述
    这里绑定类型过多,无法全部列举,但我们最常用的就是Button和键盘摇杆的轴输入
    绑定一个物理输入
    新创建的binding是没有按键绑定的,需要我们手动绑定。
    选中一个binding,点击他的属性栏里的Binding分类,然后点击Path/Listen,然后按下按键或移动摇杆,再从监听到的列表里点选我们需要的输入即可
    在这里插入图片描述在这里插入图片描述
    例如我按下了space键,我就在列表里选择space键,注意你可以按下多个按键。

    对于摇杆,例如你坚挺了XBOX的摇杆,你可选择这个动作是仅用于Xbox还是通用的,如果是通用的,使用其他品牌的摇杆按下对应的键同样可以起作用,否则只会相应Xbox摇杆,如下图,第一选项是通用输入,第二选项是仅相应Xbox摇杆。
    在这里插入图片描述
    为绑定选择一个ControlSchemes
    如果我们之前建立了一个控制方案,我们可以为这个Binding指定属于的控制方案,这方便我们过滤。
    如何新建控制方案可以参考本章“区域一”部分。
    Interactions和Processors
    和action相同,只不过banding的这两个选项会覆盖action的。

    4 实例演示,创建一个跳跃action

    请添加图片描述

    四 C#调用InputsSystem

    这里介绍三中监听输入的方式,但是只有第三种是重要的,前两种知道就行。

    方法1 传统高耦合方式调用

    虽然inputSystem提供了acion这个概念,但我们同样可以直接去访问键盘按键
    首先引入nameSpace

    using UnityEngine.InputSystem;
    
    • 1
    //键盘
    if (Keyboard.current.aKey.wasPressedThisFrame)
    {
         print("A键按下");
    }
    //鼠标输入
    print(Mouse.current.delta.ReadValue());
    //鼠标按下
    if(Mouse.current.leftButton.wasPressedThisFrame)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这种用法最好只用来做测试,不要真的用它做项目,因为他还没InputManager好用,至少InputManagerAPI更好找。

    方法2 使用PlayerInput组件

    为一个物体挂载一个PlayerInput组件,然后选择一个InputAcionsAssets。
    在这里插入图片描述
    使用DefaultMap选择一个acitonMaps。
    使用Behavior来选择一个消息传递方式,这里推荐用第3,4个,以下分别介绍这两种模式
    InokeUnityEvnets:
    这个模式的优点在于可以直接拖拽事件
    在这里插入图片描述
    切换到Behavior的第三个模式后,会出现Events选项,其中Player和UI是我创建的两个actionMaps,其中Jump和 Movement是Player这个acionMaps里的两个action,我们需要如何只需像给UIButton绑定事件一样,为action拖拽事件即可。
    我们可以这样声明事件:

    //有参
     public void Jump(InputAction.CallbackContext context)
        {
            //Debug.Log(context);
            //context.performed||context.started||context.canceled 按下 开始按 松开
            if (context.performed)//只在按下时触发
            {
                rig.AddForce(Vector3.up * 5f, ForceMode.Impulse);
            }
        }
        //无参
        public void Jump()
        {
            rig.AddForce(Vector3.up * 5f, ForceMode.Impulse);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    需要注意的是,一个按钮被按下时,会触发3次事件,因为一个按钮包含三个阶段,开始按/按下/松开,所以我们最好用带参的方法绑定事件,并自行在方法中判断阶段

    Inoke CSharp Evnets
    在这里插入图片描述
    这种方式需要我们在脚本里查找inputManager组件,并绑定委托,类似于用脚本为UIButton绑定事件

     private Rigidbody rig;
        private PlayerInput playerInput;
        private void Start()
        {
            playerInput = GetComponent<PlayerInput>();
            //查找组件的方式切换输入控制集
            playerInput.SwitchCurrentActionMap("Player");
            playerInput.onActionTriggered += PlayerInput_onActionTriggered;
        }
        private void PlayerInput_onActionTriggered(InputAction.CallbackContext obj)//使用InvokeCSharpEvents模式监听事件
        {
            Debug.Log(obj);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    方法3 创建C#脚本

    这是唯一推荐使用的方式
    首先我们要生成c#文件
    找到InputActionAssets,勾选生成C#类,即可自动生成c#类,此时最好关闭InputAcionts面板的Auto-Save选项,否则每次我调整输入,都会立刻重新生成这个类
    在这里插入图片描述

    生成的c#类名字和InputAcionsAssets名字相同,这就是为什么不要乱起名字。

    在代码中监听action按键输入,获取value类型的值
    目前的输入资产
    在这里插入图片描述

    编写脚本

     	PlayerInputActions playerInputActions;
        private void Start()
        {
            playerInputActions = new PlayerInputActions();注意是new 一个对象,不是查找组件
            playerInputActions.Player.Enable();//激活一个控制集 注意必须要激活一个acitonMaps
            playerInputActions.Player.Jump.performed += Jump;//绑定事件
            playerInputActions.Player.Movement.performed += Movement_performed;//按一下动一下,做移动输入应该按下方FixedUpdate里的方式,这里只是演示如何做值类型的输入监听
        }
        private void FixedUpdate()
        {
        	//直接监听value类型的action的输入
            Vector2 inputVector = playerInputActions.Player.Movement.ReadValue<Vector2>();
         	Debug.Log(inputVector);
        }
    
    	//注册跳跃的方法
        public void Jump(InputAction.CallbackContext context)
        {
            Debug.Log(context);
        }
        //注册移动的方法
        public void Movement_performed(InputAction.CallbackContext context) 
        {
            Vector2 inputVector = context.ReadValue<Vector2>();//读取value类型的action,注意泛型要用和输入匹配的类型
            float speed = 5f;
            rig.AddForce(new Vector3(inputVector.x, 0, inputVector.y) * speed, ForceMode.Force);
        }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    非常简单

    切换输入控制集

            playerInputActions = new PlayerInputActions();
            //C#方式切换输入控制集
            playerInputActions.UI.Disable();//禁用一个actionMaps
            playerInputActions.Player.Enable();//启用一个actionMaps
    
    • 1
    • 2
    • 3
    • 4

    重新绑定按键 恢复默认按键

    为action重新指定按键
    //重新绑定按键,重新绑定按键前,需要确保已经关闭了所有的输入动作集,否则一旦开启监听,就会立刻绑定当前输入的值,这里边肯定有我们不想要的值,例如鼠标位置,滑移的摇杆等
                playerInputActions.Player.Disable();
                playerInputActions.UI.Disable();
                playerInputActions.Player.Jump.PerformInteractiveRebinding(0)//参数0 修改首要绑定 1 修改次要绑定 默认为0
                    .WithCancelingThrough(Keyboard.current.escapeKey)//指定一个按键用于取消重新绑定
                    .OnCancel(callBack =>
                    {
                        print("取消绑定");
                        callBack.Dispose();//取消绑定要释放资源
                        playerInputActions.Player.Enable();//重新激活输入动作
                    })
                    .WithControlsExcluding("Mouse")//禁止绑定鼠标按键 参数的值可以从绑定界面看一下都有什么输入分类
                    .OnComplete(callback =>
                    {
                        Debug.Log("结束绑定");
                        callback.Dispose();//完成重新绑定后需要释放对象
                        playerInputActions.Player.Enable();//重新激活输入动作
                    })
                    .Start();//开始监听重新绑定的按键
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    保存并加载修改后的按键绑定

    如果我们不手动保存重新绑定的按键,那么下次启动时,还是会使用最开始的按键
    我们手动保存了按键后,每次启动,都需要读取,并且重新赋值给inputsystem
    在绑定的OnComplete()里添加保存

    .OnComplete(callback =>
                    {
                        Debug.Log("结束绑定");
                        Debug.Log(callback);
                        
                        //inputSystem1.1版本以后的保存重新绑定方式
                        string rebinds = callback.action.SaveBindingOverridesAsJson();
                        PlayerPrefs.SetString("rebinds", rebinds);//静态方法,参数1 固定字符串,表示重新绑定
                        print("重新绑定的内容" + rebinds);
    
                        callback.Dispose();//完成重新绑定后需要释放对象
                        playerInputActions.Player.Enable();//重新激活输入动作
                    })
    ``
    在游戏启动时读取上次保存的重新绑定json
    
    ```csharp
            playerInputActions = new PlayerInputActions();
            //C#方式切换输入控制集
            playerInputActions.Player.Enable();
            string rebinds = PlayerPrefs.GetString("rebinds");
            playerInputActions.LoadBindingOverridesFromJson(rebinds);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    恢复默认按键
    playerInputActions.Player.Jump.RemoveBindingOverride();
    
    • 1

    获取action和名字和action绑定的按键

            playerInputActions = new PlayerInputActions();
            playerInputActions.Player.Enable();
    
            print(playerInputActions.Player.Jump.name);//action的名字
            print(playerInputActions.Player.Jump.GetBindingDisplayString(1));//列出次要绑定  参数为0是首要绑定
            print(playerInputActions.Player.Jump.GetBindingDisplayString());//列出action的首要和次要绑定
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    Midjourney 实现角色一致性的新方法
    Matlab地理信息绘图—研究区域绘制
    LeetCode:261. 以图判树 - Python
    vue使用pinia存储数据并保持数据持久化
    如何远程操控桌面实现远程管理运维?
    Leetcode55&&LeetCode45
    【golang学习之旅】Go语言常用转义字符
    面试题: 字符串转整型 终结者
    运算放大器实现多路同向反向加减运算电路公式推导(二)
    LeetCode 104. 二叉树的最大深度
  • 原文地址:https://blog.csdn.net/weixin_44568736/article/details/133914942