Unity-Input System新输入系统插件学习

2023-09-20 10:14:32

1.键盘、鼠标操作

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class NewInputSystem : MonoBehaviour
{
    public float SpaceKeyValue;
    public float RightMouseValue;
    public Image Icon;
    public Vector2 MousePos;
    public Vector2 MouseScroll;

    void Update()
    {
        if(Keyboard.current != null)        //判断是否有键盘外设接入
        {
            if(Keyboard.current.spaceKey.wasPressedThisFrame)       //判断是否按下
            {
                Debug.Log("Space Pressed - New");
            }
            else if(Keyboard.current.spaceKey.wasReleasedThisFrame) //判断是否抬起
            {
                Debug.Log("Space Released - New");
            }
            //值为0表示没有按住,值为1表示正在按住
            SpaceKeyValue = Keyboard.current.spaceKey.ReadValue();
            if(SpaceKeyValue > 0)
                Debug.Log("Space");
        }

        if(Mouse.current != null)       //判断是否有鼠标外设接入
        {
            if(Mouse.current.rightButton.wasPressedThisFrame)       //判断鼠标邮件是否按下
                Debug.Log("RightMouse Released - New");

            //值为0表示没有按住,值为1表示正在按住
            RightMouseValue = Mouse.current.rightButton.ReadValue();

            //鼠标右键按住
            if(Mouse.current.rightButton.ReadValue() == 1)
                Debug.Log("RightMouse");

            //获取鼠标位置
            Icon.rectTransform.anchoredPosition = Mouse.current.position.ReadValue();
            MousePos = Mouse.current.position.ReadValue();
            //获取鼠标滚轮值
            MouseScroll = Mouse.current.scroll.ReadValue();
        }

        //手柄
        if(Gamepad.current != null)
        {

        }
    }
}

2.Input Action

Action Maps---动作表(一般分为两个表1.GamePlay-游戏时用的表,2.UI)

Action—动作   

配置:

(1)Action Maps(方案):点击右侧加号新建一个方案,输入方案名称,然后选中该方案在Action与Action Properties设置该方案具体内容。

(2)Action(输入行为):点击“+”添加一个action,选中添加的action在右侧Action Properties内配置Action Type(value—通过值判断,提供一种连续状态变化事件,如果设置了多个输入,就会切换到最主要的一个。用它进行模拟控制,比如移动;Button—通过按钮,默认设置,包括按钮或者按键触发的一次性动作;Pass Through—和Value很相似,但它不会像Value一样(如果有多个输入时,不会只选择最主要的那个,而把其他的输入忽略,适用于一台机器有多人进行游戏)。在使用Value或者Pass Through Types时,你会看到一个额外的选项 Control Type为该Value的返回值类型)。

(3)然后点击添加的Action右侧的“+”,有下列4项选择:

Add Binding:添加普通绑定

Add Up\Down\Left\Right Composite:添加上下左右绑定,Action中的Control Type为Vector2时存在此选项

Add Binding With One Modifier:添加组合按钮(1+1组合按键)

Add Binding With Two Modifiers:添加组合按键(1+2组合按键)

(4)点击添加的绑定,在右侧Binding PropertiesàBindingàPath内选择要绑定的按键(可以是键盘、手柄、鼠标等输入设备),也可以点击搜索框左侧的“Listen”按钮,然后按下要绑定的按键,然后选择对应按键即可完成绑定。

(5)配置Interactions:设置Action中的Interactions,该设置会影响Action下所有Binding,设置Binding的Interactions只会影响该Binding。

详细请看【Unity_Input System】Input System新输入系统(二)_铃兰148的博客-CSDN博客的第5节

(6)配置Processors:详细请看【Unity_Input System】Input System新输入系统(二)_铃兰148的博客-CSDN博客的第6节

(7)然后点击“Save Asset”即可保存该InputAction

(8)然后单击创建的InputAction在Inspector面板勾选“Generate C# Class”并配置文件路径,类名,命名空间名称,点击Apply即可生成C#类代码文件。

(9)最后就是编写代码脚本进行使用,示例代码如下

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.InputSystem;

public class InputSystemBall : MonoBehaviour
{
    /// <summary>
    /// 移动的值,范围为-1到1,类似旧版系统中GetAxis获取到的值
    /// </summary>
    public Vector2 Movement;
    /// <summary>
    /// 移动速度
    /// </summary>
    public float MoveSpeed = 5f;

    /// <summary>
    /// 横向偏移值(-1,1),模拟旧版GetAxis(“Horizontal”)的值
    /// </summary>
    public float Horizontal;

    /// <summary>
    /// 创建的InputAction
    /// </summary>
    private MyInputAction myInputAction;
    private Rigidbody rigidbody;

    private void Awake()
    {
        myInputAction = new MyInputAction();
        //启用InputAction
        myInputAction.Enable();
        rigidbody = GetComponent<Rigidbody>();

        //给InputAction中的Jump添加监听,分为3个阶段Started->Performed->Canceld
        //myInputAction.GamePlay.Jump.performed += OnJump;
    }

    public void OnJump(InputAction.CallbackContext context)
    {
        //Started->Performed->Canceld
        //context.ReadValueAsButton()获取按键是按下(true),还是抬起(false)
        Debug.Log($"Jump!:{context.ReadValueAsButton()}");
        rigidbody.AddForce(Vector3.up * 5f, ForceMode.Impulse);
    }

    private void OnDestroy()
    {
        //禁用InputAction
        myInputAction.Disable();
    }

    void Update()
    {
        //获取InputAction中Movement的值
        Movement = myInputAction.GamePlay.Movement.ReadValue<Vector2>();
        //获取InputAction中Horizontal的值
        Horizontal = myInputAction.GamePlay.Horizontal.ReadValue<float>();
        rigidbody.AddForce(new Vector3(Movement.x, 0, Movement.y) * MoveSpeed * Time.deltaTime, ForceMode.Impulse);

        //if (myInputAction.GamePlay.Jump.IsPressed())
        //    Debug.Log("Press");
    }
}

3.多设备支持与手柄震动实现

注意创建InputAction的Action时需要选择Action Type为Pass Through,否则多设备连接使用时存在问题。

代码示例---多设备管理器

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

/// <summary>
/// 输入设备数据
/// </summary>
[System.Serializable]
public class InputSystemMultiData
{
    public int Index;               //0
    public InputDevice Device;      //输入设备
    public Action OnJump;           //jump事件
    public Vector2 MoveMentData;    //移动值

    public InputSystemMultiData(int index, InputDevice device)
    {
        Index = index;
        Device = device;
    }
}

/// <summary>
/// 多人手柄
/// </summary>
public class InputSystemMultiManager : MonoBehaviour
{
    /// <summary>
    /// 单例
    /// </summary>
    public static InputSystemMultiManager Instance;

    /// <summary>
    /// 存储已接入的输入设备
    /// </summary>
    public List<InputSystemMultiData> InputSystem_MultiDatas = new List<InputSystemMultiData>();

    /// <summary>
    /// 创建的InputAction
    /// </summary>
    private MyInputAction myInputAction;

    private void Awake()
    {
        Instance = this;

        myInputAction = new MyInputAction();

        //将InputAction中的Movement和Jump添加监听
        myInputAction.GamePlay.Movement.performed += OnMovement;
        myInputAction.GamePlay.Jump.performed += OnJump;
        myInputAction.Enable();
    }

    /// <summary>
    /// 通过index获取设备数据
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public InputSystemMultiData GetDataByIndex(int index)
    {
        //查找存储设备中满足条件的设备数据
        var data = InputSystem_MultiDatas.Find(a => a.Index == index);

        return data;
    }

    /// <summary>
    /// 获取设备Index
    /// </summary>
    /// <param name="device">原设备</param>
    /// <returns></returns>
    public int GetIndex(InputDevice device)
    {
        //查找设备是否已存储
        var data = InputSystem_MultiDatas.Find(a =>a.Device.deviceId == device.deviceId);

        if(data != null) 
            return data.Index;

        //新建设备并存储
        InputSystemMultiData multiData = new InputSystemMultiData(InputSystem_MultiDatas.Count, device);
        InputSystem_MultiDatas.Add(multiData);
        return multiData.Index;
    }

    /// <summary>
    /// 跳跃的监听
    /// </summary>
    /// <param name="context"></param>
    private void OnJump(InputAction.CallbackContext context)
    {
        //获取输入设备
        InputDevice device = context.control.device;
        //获取设备id
        int index = GetIndex(device);
        //执行设备(自定义)中的跳跃方法
        InputSystem_MultiDatas[index].OnJump?.Invoke();
    }

    /// <summary>
    /// 移动的监听
    /// </summary>
    /// <param name="context"></param>
    private void OnMovement(InputAction.CallbackContext context)
    {
        //获取输入设备
        InputDevice device = context.control.device;
        //获取设备id
        int index = GetIndex(device);
        //给设备(自定义)中的移动数据赋值
        InputSystem_MultiDatas[index].MoveMentData = context.ReadValue<Vector2>();
    }

    private void OnDestroy()
    {
        myInputAction.Disable();
    }
}

使用示例

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Rendering.LookDev;
using UnityEngine;
using UnityEngine.InputSystem;

public class InputSystemMultiBall : MonoBehaviour
{
    public int Index = -1;

    private InputSystemMultiData Data = null;

    private Rigidbody rigidbody;

    private void Awake()
    {
        rigidbody = GetComponent<Rigidbody>();
        Data = null;
    }

    private void Update()
    {
        if(Data == null)
        {
            //获取设备数据
            Data = InputSystemMultiManager.Instance.GetDataByIndex(Index);

            if (Data != null)
            {
                //添加跳跃方法
                Data.OnJump += OnBallJump;
            }
            else
                return;
        }
        //移动
        rigidbody.AddForce(new Vector3(Data.MoveMentData.x, 0, Data.MoveMentData.y) * 5 * Time.deltaTime, ForceMode.Impulse);
    }

    /// <summary>
    /// 跳跃
    /// </summary>
    private void OnBallJump()
    {
        rigidbody.AddForce(Vector3.up * 5f, ForceMode.Impulse);
        //开启协程-让手柄震动
        StartCoroutine(StartShockCoroutine());
    }

    /// <summary>
    /// 手柄震动
    /// </summary>
    /// <returns></returns>
    private IEnumerator StartShockCoroutine()
    {
        //判断是否为手柄输入设备
        if (Data.Device is Gamepad == false)
            yield break;

        Gamepad gamepad = Data.Device as Gamepad;
        //设置手柄马达转速(低频,高频)
        gamepad.SetMotorSpeeds(0.3f, 0.9f);
        //持续时间
        yield return new WaitForSeconds(1);
        //时间到设置手柄马达停止
        gamepad.SetMotorSpeeds(0, 0);
    }
}

4.修改绑定按键并保存

代码

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class InputSystemRebindBall : MonoBehaviour
{
    /// <summary>
    /// 跳跃的Action
    /// </summary>
    public InputActionReference JumpAction;
    /// <summary>
    /// 显示文本
    /// </summary>
    public Text RebindText;
    /// <summary>
    /// 玩家输入
    /// </summary>
    private PlayerInput playerInput;
    private Rigidbody rigidbody;
    public Button rebindBtn;

    private void Awake()
    {
        rigidbody = GetComponent<Rigidbody>();
        playerInput = GetComponent<PlayerInput>();
    }

    void Start()
    {
        //读取保存的按键输入数据
        string json =  PlayerPrefs.GetString("InputActions", null);

        //加载保存的按键输入数据并应用
        if (!string.IsNullOrEmpty(json))
            playerInput.actions.LoadBindingOverridesFromJson(json);

        //显示当前绑定的按键名称,InputControlPath.HumanReadableStringOptions.OmitDevice表示去除设备名称
        RebindText.text = InputControlPath.ToHumanReadableString(JumpAction.action.bindings[0].effectivePath,InputControlPath.HumanReadableStringOptions.OmitDevice);

        rebindBtn.onClick.AddListener(RebindKey);
    }

    /// <summary>
    /// 跳跃,使用PlayerInput添加event进行绑定
    /// </summary>
    public void OnJump()
    {
        rigidbody.AddForce(Vector3.up * 5f, ForceMode.Impulse);
    }

    /// <summary>
    /// 修改绑定的按钮
    /// </summary>
    public void RebindKey()
    {
        //先切换到其他行为方案
        playerInput.SwitchCurrentActionMap("UI");

        RebindText.text = "请输入新键...";

        //PerformInteractiveRebinding进行改键
        //WithControlsExcluding剔除鼠标操作
        //OnComplete改建完成执行
        //Start开始改键
        JumpAction.action.PerformInteractiveRebinding().WithControlsExcluding("Mouse").OnComplete(operation =>
        {
            Debug.Log("Change Key");
            //显示改键后按键名称
            RebindText.text = InputControlPath.ToHumanReadableString(JumpAction.action.bindings[0].effectivePath, InputControlPath.HumanReadableStringOptions.OmitDevice);
            //将operation释放
            operation.Dispose();
            //切换为原行为方案
            playerInput.SwitchCurrentActionMap("GamePlay");

            //保存改键信息
            string json = playerInput.actions.SaveBindingOverridesAsJson();
            PlayerPrefs.SetString("InputActions", json );

        }).Start();
    }
}

更多推荐

【Flutter】Flutter 使用 RxDart 实现异步编程

文章目录一、前言二、版本信息三、RxDart简介四、RxDart的基本使用1.Stream类2.扩展方法3.Subjects五、RxDart的实战应用1.实例一:使用RxDart实现事件缓冲2.实例二:使用RxDart实现事件合并六、总结一、前言欢迎来到这篇关于RxDart的入门文章。在这篇文章中,我们将一起探索RxD

Redis理解

文章目录针对小林Coding图解Redis做的自己的理解:数据类型篇Redis常用数据类型和应用场景StringListHashSetZsetBitMapHyperLogLogGEOStream持久化篇AOF持久化是怎么实现的AOF日志三种写回策略AOF重写机制RDB快照是怎么实现的RDB快照执行快照时,数据能被修改吗

腾讯云AI超级底座新升级:训练效率提升幅度达到3倍

大模型推动AI进入新纪元,对计算、存储、网络、数据检索及调度容错等方面提出了更高要求。在9月7日举行的2023腾讯全球数字生态大会“AI超级底座专场”上,腾讯云介绍异构计算全新产品矩阵“AI超级底座”及其新能力。腾讯云副总裁王亚晨在开场致辞中表示,AI大模型就像是一场F1比赛,腾讯云专门设计了星脉高性能算力网络“赛道”

特斯拉Dojo超算:AI训练平台的自动驾驶与通用人工智能之关键

特斯拉公开Dojo超算架构细节,AI训练算力平台成为其自动驾驶与通用人工智能布局的关键一环在近日举行的HotChips34会议上,特斯拉披露了其自主研发的AI超算Dojo的详细信息。Dojo是一个可定制的超级计算机,从芯片到系统全部由特斯拉自主设计,主要目标是高效运行各种机器学习训练算法。Dojo将为特斯拉的自动驾驶提

2023 Google开发者大会:你了解机器学习的新动向吗?

目录0年度科技盛会1生成式机器学习2无障碍游戏体验3跨平台机器学习总结0年度科技盛会2023Google开发者大会在上海浦东举办,为开发者和科技爱好者们带来新技术、新产品、新动向可能很多同学对Google开发者大会还不熟悉,Google开发者大会是Google展示最新产品和平台的年度盛会,为开发者提供丰富的学习资源、实

【力扣周赛】第 363 场周赛(完全平方数和质因数分解)

文章目录竞赛链接Q1:100031.计算K置位下标对应元素的和竞赛时代码写法2——手写二进制中1的数量Q2:100040.让所有学生保持开心的分组方法数(排序后枚举分界)竞赛时代码Q3:100033.最大合金数(二分答案)竞赛时代码Q4:8041.完全子集的最大元素和竞赛时代码——质因数分解+哈希表解法2——定义cor

深度学习编译器关键组件

1高层中间代码为了克服传统编译器中采用的IR限制DL模型中复杂计算的表达的局限性,现有的DL编译器利用高层IR(称为图IR)进行高效的代码优化设计。1.1图表示基于DAG的IR:基于DAG的IR是编译器构建计算图的最传统方法之一,它将节点和边组织为有向无环图(DAG)。在DL编译器中,DAG的节点表示原子DL运算符(卷

git使用详解

目录一,什么是git?二,如何安装git三,git的基本操作1.创建git本地仓库2.配置本地仓库3.认识工作区,暂存区,版本库。4.基本操作-添加文件5.基本操作-查看文件6.基本操作-修改文件7.版本回退8.撤销修改四.分支管理1.创建分支2.删除分支3.合并冲突4.分支管理策略5.bug分支6.强制删除分支五,远

网络爬虫-----初识爬虫

目录1.什么是爬虫?1.1初识网络爬虫1.1.1百度新闻案例说明1.1.2网站排名(访问权重pv)2.爬虫的领域(为什么学习爬虫?)2.1数据的来源2.2爬虫等于黑客吗?2.3大数据和爬虫又有啥关系?2.4爬虫的领域,前景3.总结什么是爬虫?爬虫能抓取拿些数据?1.什么是爬虫?本节课程的内容是介绍什么是爬虫?爬虫有什么

【内网穿透】Python一行代码实现文件共享,并实现公网访问

目录1.前言2.本地文件服务器搭建2.1.python的安装和设置2.2.cpolar的安装和注册3.本地文件服务器的发布3.1.Cpolar云端设置3.2.Cpolar本地设置4.公网访问测试5.结语1.前言数据共享作为和连接作为互联网的基础应用,不仅在商业和办公场景有广泛的应用,对于个人用户也有很强的实用意义。也正

前端--HTML

文章目录HTML结构快速生成代码框架HTML常见标签表格标签编写简历信息填写简历信息Emmet快捷键HTML特殊字符一、HTML结构1.认识HTML标签HTML代码是由"标签"构成的.形如:<body>hello</body>标签名(body)放到<>中大部分标签成对出现.<body>为开始标签,</body>为结束标

热文推荐