【Unity】NewInputSystem系统的基本使用

概述

Unity的新输入系统(New Input System)是一个更加灵活和可扩展的输入解决方案,它提供了比传统的UnityEngine.Input更多的功能和改进。

安装和激活

要安装新输入系统,你需要打开Unity的包管理器(菜单:Window > Package Manager),选择Input System包进行安装。安装完成后确认窗口,这将导致编辑器重启且关闭旧输入系统(InputManager)的使用。

安装过程

如果希望同时使用两种输入系统,可以在(菜单:Edit > Project Settings > Player)中找到Active Input Handling属性,将属性值改为Both,就可以同时开启两种输入系统。

新输入系统需要Unity 2019.4或更高版本,并且需要.NET 4运行时。它不适用于使用旧.NET 3.5运行时的项目。

简单原理介绍

新输入系统基于事件,将输入设备和动作逻辑分离,并通过配置映射来处理输入信息。这使得它在多设备和多平台输入处理时更加强大和灵活。新输入系统设计时考虑了多设备支持,包括键盘、鼠标、游戏手柄、触摸、VR和XR等。这使得它在处理各种输入设备时更加高效和一致。

假设玩家A使用Gamepad时,按下Gamepad上的X键,通过InputSystem资源配置文件中对设备输入和玩家自定义的多种输入方式进行匹配,最终通过相关方法调用,可在脚本中获取所需要的值。

配置文件基本介绍

在安装NewInputSystem后,可以在Project窗口中创建InputActions资源配置文件进行;也可以给场景物体先挂载一个PlayerInput组件(配置文件创建完后可删除),在组件中创建InputActions资源配置文件,通过PlayerInput组件创建的InputActions会配置好一些基本的按键映射,可供直接使用(资源配置文件放置在自己创建的配置文件夹中)。

InputActions资源配置文件分为三个部分

第一区域

Action Maps是用于设置不同使用场景的映射表,项目中对于玩家角色的操作,UI的操作,汽车驾驶操作等等场景的相同按键进行不同的操作配置。新增新的映射表直接点击右上角的+号。

第二区域

Actions 对不同操作进行配置。例如玩家的操作可以有移动,跳跃,射击等等,就可以通过右上角的+号新增新的动作映射。在动作下还可以配置不同设备对于当前动作的控制映射。

第三区域

Action Properties 是对Actions中各类属性的设置内容。

例如:现在我需要为当前Player映射表新增一个新的动作Jump。

1.点击 + 新建新的操作(Action)并重命名,设置操作输出的值类型。Action Type选择Value,Controller Type则可以进行输出值类型选择。Button则是布尔类型,Vector2则是二维数组类型,以此类推。通常按键选择Botton(也可以直接在ActionType中直接选择Button),摇杆或者用于移动控制则是使用Vector2。

2.点击 + ,选择Add Binding,新建新的控制映射。

3.选定当前按键映射,在Path属性下选择当前设备中连接的所有输入设备的按钮,随后选择需要的按钮。也可以通过监听的方式直接获取需要的设备按键,点击红框中的Listen,当前Listen显示高亮(不懂什么Bug被遮挡了)后再在输入设备上按下需要的按键。

4.选定当前按键映射进行约束设置,也就是为当前按钮设定一个类型,减少出现错误识别的问题。

5.点击Save Asset或者勾选Auto Save对配置文件InputActions进行保存。(这很重要!!!)

脚本中使用NewInputSystem的工作流

直接使用控制器控制

csharp 复制代码
using UnityEngine;
using UnityEngine.InputSystem;

public class InputByDecive : MonoBehaviour
{
    //物体移动速度
    public float speed;

    void Update()
    {
        //获取手柄控制器对象
        var gamePad = Gamepad.current;
        if (gamePad != null)
        {
            //读取手柄控制器左摇杆的输入值
            Vector2 moveInput = gamePad.leftStick.ReadValue();
            {
                if (moveInput != Vector2.zero)
                {
                    //位移控制
                    moveInput = moveInput.normalized;
                    var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                    transform.Translate(moveDirection * speed * Time.deltaTime);
                }
            }
        }
    }
}

将脚本挂载在物体上,对物体(红色小球)进行移动控制。

这通常是设置一些响应输入的代码的最快方法,但它是最不灵活的。无法有效的管理所有的输入,到开发后期输入增多代码混乱。

直接操作InputAction(按键映射对象)

InputAction是新输入系统中的一个关键类,代表一种动作逻辑,可以绑定到多个物理输入上。每个动作逻辑在任何时刻都有一个状态阶段,例如Started, Performed, Canceled等,你可以根据这些阶段来响应输入。

csharp 复制代码
using UnityEngine;
using UnityEngine.InputSystem;

public class InputByInputAction : MonoBehaviour
{
    //InputAction动作对象引用
    public InputAction moveAction;
    public float speed;

    void Start()
    {
        //第一种
        //moveAction.performed += OnMove1;
    }

    void Update()
    {
        //第二种
        OnMove2();
    }
    
    //第一种通过事件绑定的方式事项控制
    //事件回调函数
    private void OnMove1(InputAction.CallbackContext context)
    {
        通过回调获取输入值
        Vector2 moveInput = context.ReadValue<Vector2>();
        {
            if (moveInput != Vector2.zero)
            {
                moveInput = moveInput.normalized;
                var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                transform.Translate(moveDirection * speed * Time.deltaTime);
            }
        }
    }
    
    //第二种直接获取输入值
    private void OnMove2()
    {
        if (moveAction != null)
        {
            Vector2 moveInput = moveAction.ReadValue<Vector2>();
            {
                if (moveInput != Vector2.zero)
                {
                    moveInput = moveInput.normalized;
                    var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                    transform.Translate(moveDirection * speed * Time.deltaTime);
                }
            }
        }
    }
    //InputAction在使用前需要开启功能,不然接收不到输入
    void OnEnable()
    {
        moveAction.Enable();
    }
    
    void OnDisable()
    {
        moveAction.Disable();
    }
}

将脚本挂载在物体上,在Inspector窗口中创建新的InputAction对象并配置按键后,对物体(红色小球)进行移动控制。

使用 InputActions 还可以更轻松地实现输入控制,以允许用户在运行时重新映射新的按键输入。直接读取设备状态更灵活,但不如使用InputActionAssets灵活。

操作InputActionAssets按键映射表

InputActionAssets 这是一种资源文件,用于存储动作绑定关系,扩展名为.InputActions,数据格式为JSON。

csharp 复制代码
using UnityEngine;
using UnityEngine.InputSystem;

public class InputByInputActionAsset : MonoBehaviour
{
    //InputActionAsset资源配置文件引用
    public InputActionAsset inputActions;

    //在当前InputActionAsset中需要使用的InputAction动作对象
    private InputAction moveAction;
    public float speed;

    void Start()
    {
        if (inputActions != null)
        {
            //从资源配置文件中获取InputAction
            moveAction = inputActions.FindActionMap("Player").FindAction("Move");
        }
        if (moveAction != null)
        {
            //方法1
            moveAction.performed += Move1;
        }
    }

    void Update()
    {
        //方法2
        // Move2();
    }

    //第一种通过事件绑定的方式事项控制
    //事件回调函数
    private void Move1(InputAction.CallbackContext context)
    {
        Vector2 moveInput = context.ReadValue<Vector2>();
        {
            if (moveInput != Vector2.zero)
            {
                moveInput = moveInput.normalized;
                var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                transform.Translate(moveDirection * speed * Time.deltaTime);
            }
        }
    }

    //第二种直接获取输入值
    private void Move2()
    {
        if (moveAction != null)
        {
            Vector2 moveInput = moveAction.ReadValue<Vector2>();
            {
                Debug.Log("Move:" + moveInput);
                if (moveInput != Vector2.zero)
                {
                    moveInput = moveInput.normalized;
                    var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                    transform.Translate(moveDirection * speed * Time.deltaTime);
                }
            }
        }
    }

    //InputActionAssets和InputAction在使用前都需要开启功能,不然接收不到输入
    void OnEnable()
    {
        if (inputActions != null)
        {
            inputActions.FindActionMap("Player").Enable();
            if (moveAction != null)
            {
                moveAction.Enable();
            }
        }
    }

    void OnDisable()
    {
        if (inputActions != null)
        {
            inputActions.FindActionMap("Player").Disable();
            if (moveAction != null)
            {
                moveAction.Disable();
            }
        }
    }
}

将脚本挂载在物体上,在Inspector窗口中配置创建的InputActions资源配置文件,对物体(红色小球)进行移动控制。

InputActions非常有用,因为它意味着所有操作定义都存储为单个资源文件中,可以让脚本和预制件分开。这可以使输入控制文件的管理更简单。

使用PlayerInput组件

PlayerInput组件将输入事件高度封装,只需要在组件中对需要调用的方法进行事件配置,就可以实现物体的控制操作。

ini 复制代码
using UnityEngine;
using UnityEngine.InputSystem;

public class InputByPlayerInput : MonoBehaviour
{
    public float speed=5f;

    //方法需要传入InputAction.CallbackContext,满足时间绑定的条件
    public void OnMove(InputAction.CallbackContext context)
    {
        Vector2 moveInput = context.ReadValue<Vector2>();
        {
            if (moveInput != Vector2.zero)
            {
                moveInput = moveInput.normalized;
                var moveDirection = new Vector3(moveInput.x, 0, moveInput.y);
                transform.Translate(moveDirection * speed * Time.deltaTime);
            }
        }
    }
}

1.将脚本挂载在物体上

2.为对象新增PlayerInput组件

2.1 在Inspector窗口中的Actions属性下配置创建的InputActions资源配置文件或者选择创建好的资源配置文件

2.2 在Behavior属性中选择Invoke Unity Events,也就可以读取到InputActions资源配置文件中Actions下设置好的动���的事件对象。

2.3在Events -> Player属性中找到要设置的动作事件,点击 +

2.4将脚本挂载在当前属性中,

2.5在左侧方法中选择当前到本的相关方法。

3.对物体(红色小球)进行移动控制。

与前面的工作流代码示例相比,您可以看到此方法需要更少的代码,因为您不必在自己的脚本中引用 Actions 资源配置文件或设置事件处理程序方法。但是,它确实需要在编辑器中进行更多设置,并且可能会使调试更加困难,因为操作和代码之间的连接不是硬编码的。

与描述的其他工作流一样,在灵活性、简单性和实现速度之间需要权衡。

总结

使用InputSystem可以极大的提高开发效率,让输入控制的管理变得更简单。

相关推荐
古力德14 小时前
Unity中造轮子:定时器
c#·unity3d
Mapmost3 天前
【数据融合实战手册·进阶篇】模型融合总出错?先看看这些“对齐”了没!
unity3d
北桥苏4 天前
如何在 Unity3D 导入 Spine 动画
unity3d
Thomas游戏开发6 天前
Unity3D状态管理器实现指南
前端框架·unity3d·游戏开发
土豆宝11 天前
Unity Visual Scripting(可视化脚本) 自定义节点 踩坑教程
unity3d
Thomas游戏开发11 天前
Unity3D光照层级与动态切换指南
前端框架·unity3d·游戏开发
Thomas游戏开发22 天前
Unity3D 崩溃分析工具的集成与优化
前端框架·unity3d·游戏开发
Thomas游戏开发1 个月前
Unity3D网格简化与LOD技术详解
前端框架·unity3d·游戏开发
Thomas_YXQ1 个月前
Unity3D 图形渲染(Graphics & Rendering)详解
开发语言·unity·图形渲染·unity3d·shader
Thomas游戏开发1 个月前
Unity3D 图形渲染(Graphics & Rendering)详解
前端·unity3d·游戏开发