【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可以极大的提高开发效率,让输入控制的管理变得更简单。

相关推荐
吾名招财6 天前
unity3d入门教程五
游戏引擎·unity3d
吾名招财6 天前
unity3d入门教程六
游戏引擎·unity3d
吾名招财6 天前
unity3d入门教程七
游戏引擎·unity3d
Thomas_YXQ8 天前
Unity3D 实现水体交互详解
开发语言·unity·编辑器·交互·unity3d·游戏开发
Coding小宇10 天前
静下心来我还是可以的-unitywebgl 滑动条增加
经验分享·unity·unity3d
吾名招财10 天前
unity3d入门教程二
游戏·unity3d
Doing2 个月前
Vue3+TS+Threejs封装一个3D动画框架
前端·unity3d·webgl
code梦想佳2 个月前
Unity 桥接 sdk 交互实现
前端·unity3d
Thomas_YXQ2 个月前
Unity3D 性能分析工具原理介绍及代码实现详解
游戏·unity·架构·unity3d·游戏开发
洞窝技术2 个月前
开发Blender全自动烘焙工具的挑战与解决方案
unity3d