Unity Input System 官方案例学习笔记

Unity Input System 官方案例学习笔记

01 前言

作者:hzb

开始时间:2023-12-9

最后更新时间:2023-12-11

资料来源:Unity Input System 官方案例

该文章将从Unity Input System的所给的官方案例中学习这个新的输入系统的使用,资料中所有中文由ChatGPT4提供翻译,同时部分补充即实例由GPT4提供,如有错误欢迎指出。

案例导入

  • Package Manager

image-20231211111345627

  • Project Settings

image-20231211111535392

02 案例: Simple Demo

这个示例展示了如何使用输入系统设置一个简单的角色控制器。由于有多种方式可以做到这一点,该示例展示了几种方法。每个演示都设置为一个单独的场景。所有场景中的基本功能都是相同的。你可以移动、四处看看,以及向场景中发射弹丸(彩色立方体)。在某些场景中,只支持游戏手柄,但更复杂的演示支持多种不同的输入同时使用。

(1) UsingState

案例分析
案例README

这个演示从最低级开始,展示了如何通过在MonoBehaviour.Update函数中直接轮询输入状态来连接输入。为了简单起见,它只处理游戏手柄,但对于其他类型的输入设备(例如使用Mouse.currentKeyboard.current)也以类似方式工作。

这里演示的关键API是Gamepad.currentInputControl.ReadValue

public class SimpleController_UsingState : MonoBehaviour
{
    //...

    public void Update()
    {
        var gamepad = Gamepad.current;
        if (gamepad == null)
            return;

        var move = Gamepad.leftStick.ReadValue();
        //...
    }
}

在这个演示中,主要关注点是如何直接从游戏手柄(或其他输入设备)获取实时输入数据,并基于这些数据来更新游戏中的角色或对象状态。示例可能包括如何读取摇杆位置、按钮按下状态等,来实现角色的移动、跳跃或其他动作。

关键步骤

关键特点和步骤可能包括:

  1. 获取当前游戏手柄
    • 使用 Gamepad.current 来获取当前连接的游戏手柄。
  2. 轮询按键状态
    • 检查特定按钮(如南方向按钮)在当前帧是否被按下或释放。
  3. 读取摇杆输入
    • 获取摇杆(如左摇杆 leftStick)的当前位置,这通常返回一个 Vector2 类型的值,表示摇杆的水平和垂直偏移。
  4. 应用输入到游戏逻辑
    • 根据获取到的输入值来控制角色的移动、转向或其他行为。
  5. 简单实现
    • 这种方法通常比较直接和简单,适合快速原型开发或小型项目。

SimpleDemo_UsingState是一个很好的起点,用于理解如何在 Unity 的新输入系统中处理原始输入数据。它特别适合那些需要对输入进行低级处理的应用场景。

代码注释
using UnityEngine.InputSystem;
using UnityEngine;

// 直接使用游戏手柄设备的状态。
public class SimpleController_UsingState : MonoBehaviour
{
    // 定义移动速度和旋转速度。
    public float moveSpeed;
    public float rotateSpeed;
    // 弹丸的预制体。
    public GameObject projectile;

    // 用于存储旋转状态和射击状态的私有变量。
    private Vector2 m_Rotation;
    private bool m_Firing;
    private float m_FireCooldown;

    public void Update()
    {
        // 获取当前连接的游戏手柄。
        var gamepad = Gamepad.current;
        if (gamepad == null)
            return; // 如果没有手柄连接,则退出。

        // 读取左右摇杆的值。
        var leftStick = gamepad.leftStick.ReadValue();
        var rightStick = gamepad.rightStick.ReadValue();

        // 根据右摇杆控制视角旋转,根据左摇杆控制移动。
        Look(rightStick);
        Move(leftStick);

        // 检查南方向按钮(例如A或X键)的按下和释放状态,控制射击。
        if (gamepad.buttonSouth.wasPressedThisFrame)
        {
            m_Firing = true;
            m_FireCooldown = 0;
        }
        else if (gamepad.buttonSouth.wasReleasedThisFrame)
        {
            m_Firing = false;
        }

        // 如果处于射击状态且射击冷却时间已到,进行射击。
        if (m_Firing && m_FireCooldown < Time.time)
        {
            Fire();
            m_FireCooldown = Time.time + 0.1f; // 设置下次射击的冷却时间。
        }
    }

    // 根据输入方向进行移动。
    private void Move(Vector2 direction)
    {
        if (direction.sqrMagnitude < 0.01)
            return; // 如果方向向量几乎为零,则不移动。
        var scaledMoveSpeed = moveSpeed * Time.deltaTime;
        // 将方向向量转换为世界坐标系下的移动。
        var move = Quaternion.Euler(0, transform.eulerAngles.y, 0) * new Vector3(direction.x, 0, direction.y);
        transform.position += move * scaledMoveSpeed; // 应用移动。
    }

    // 根据输入旋转角色。
    private void Look(Vector2 rotate)
    {
        if (rotate.sqrMagnitude < 0.01)
            return; // 如果旋转向量几乎为零,则不旋转。
        var scaledRotateSpeed = rotateSpeed * Time.deltaTime;
        // 计算新的旋转值,并应用到对象上。
        m_Rotation.y += rotate.x * scaledRotateSpeed;
        m_Rotation.x = Mathf.Clamp(m_Rotation.x - rotate.y * scaledRotateSpeed, -89, 89);
        transform.localEulerAngles = m_Rotation;
    }

    // 发射弹丸。
    private void Fire()
    {
        // 创建一个新的弹丸实例并设置其位置和方向。
        var transform = this.transform;
        var newProjectile = Instantiate(projectile);
        newProjectile.transform.position = transform.position + transform.forward * 0.6f;
        newProjectile.transform.rotation = transform.rotation;
        // 设置弹丸大小和物理属性。
        const int size = 1;
        newProjectile.transform.localScale *= size;
        newProjectile.GetComponent<Rigidbody>().mass = Mathf.Pow(size, 3);
        // 给弹丸一个前向力,使其发射。
        newProjectile.GetComponent<Rigidbody>().AddForce(transform.forward * 20f, ForceMode.Impulse);
        // 随机改变弹丸的颜色。
        newProjectile.GetComponent<MeshRenderer>().material.color =
            new Color(Random.value, Random.value, Random.value, 1.0f);
    }
}
案例总结

这种方法即每帧检查当前是否有游戏手柄接入,并获取这个手柄上各个按键的状态。这与旧的Unity Input Manager的使用方法相似,但有几个关键的区别和优势:

  1. 输入设备的直接访问:新的输入系统允许直接访问特定的输入设备(如 Gamepad)。这意味着您可以直接查询游戏手柄的状态,而不是通过一般的输入轴或按钮映射。
  2. 设备独立性:新的输入系统设计用来更好地处理多种输入设备,包括游戏手柄、键盘、鼠标等,每种设备都有其专有的类和方法。
  3. 更好的按键状态管理:新系统提供了更细致的按键状态查询,如 wasPressedThisFramewasReleasedThisFrame 等,这使得管理按键状态(例如检测单次按下或释放)更为简便。

总的来说,UsingState在设计上提供了更多的灵活性和控制力,特别是在处理多种输入设备和复杂的输入需求时。虽然其基本原理(即每帧检查输入状态)与旧的Input Manager相似,但新系统提供了更多的功能和更好的设备管理。

案例补充
Gamepad

在 Unity 的新输入系统中使用 Gamepad 类时,通常会用到以下几种状态和功能:

  1. 按键状态
    • wasPressedThisFrame: 在当前帧中,该按键是否被首次按下。
    • wasReleasedThisFrame: 在当前帧中,该按键是否被释放。
    • isPressed: 该按键当前是否被持续按下。
  2. 摇杆和触摸板
    • leftStick, rightStick: 分别代表左右摇杆的当前位置(返回 Vector2)。
    • dpad: 方向键的当前位置(也是 Vector2)。
  3. 触发器
    • leftTrigger, rightTrigger: 游戏手柄上左右触发器的当前值(通常是0到1的浮点数)。
  4. 按钮
    • buttonSouth(通常是A或X键)、buttonNorth(通常是Y或△键)、buttonEast(通常是B或○键)、buttonWest(通常是X或□键)。
    • startButton, selectButton: 分别代表开始和选择按钮。
  5. 震动功能
    • SetMotorSpeeds(float lowFrequency, float highFrequency): 设置游戏手柄的震动强度。
  6. 设备状态
    • Gamepad.current: 获取当前连接的游戏手柄。
    • Gamepad.all: 获取所有连接的游戏手柄列表。

使用这些状态和功能,可以检测游戏手柄上的按键、摇杆、触发器的当前状态,以及设置震动等。这对于创建游戏中的角色控制、菜单导航、交互响应等功能非常有用。通过这些API,可以为玩家提供丰富而直观的游戏操作体验。

KeyBoard

在 Unity 的新输入系统中,针对键盘的常用状态和功能包括以下几个方面:

  1. 按键状态
    • wasPressedThisFrame: 在当前帧中,指定的键是否被首次按下。
    • wasReleasedThisFrame: 在当前帧中,指定的键是否被释放。
    • isPressed: 指定的键当前是否被持续按下。
  2. 特定按键的访问
    • 可以通过 Keyboard.current.<keyName>.ReadValue()Keyboard.current.<keyName>.isPressed 等方式访问特定键的状态,其中 <keyName> 是键的名称,例如 spaceKeyenterKeyleftShiftKey 等。
  3. 所有按键的状态
    • Keyboard.current.allKeys: 获取一个包含所有按键的数组,可以用来遍历或查询特定键的状态。
  4. 键盘的整体状态
    • Keyboard.current: 获取当前连接的键盘。
  5. 文本输入
    • onTextInput: 事件,可以用来接收文本输入,特别是对于需要文本输入(如聊天或表单填写)的应用。
  6. 修饰键状态
    • shiftKey, ctrlKey, altKey, metaKey(Windows上的Windows键,Mac上的Command键)等,用于检测这些修饰键是否被按下。
  7. 键盘布局
    • Keyboard.current.keyboardLayout: 获取当前键盘布局的名称。

通过这些API,可以精确地控制键盘输入,响应玩家的按键操作,实现角色控制、UI交互、文本输入等功能。这对于确保玩家能够通过键盘与游戏或应用程序有效交互非常重要。

键盘的每个键都有一个对应的名称,用于标识和访问该键的状态。以下是一些常用键的名称列表:

  1. 字母键:
    • aKey, bKey, cKey, dKey, eKey, fKey, gKey, hKey, iKey, jKey, kKey, lKey, mKey, nKey, oKey, pKey, qKey, rKey, sKey, tKey, uKey, vKey, wKey, xKey, yKey, zKey
  2. 数字键:
    • digit1Key, digit2Key, digit3Key, digit4Key, digit5Key, digit6Key, digit7Key, digit8Key, digit9Key, digit0Key
  3. 功能键:
    • f1Key, f2Key, f3Key, f4Key, f5Key, f6Key, f7Key, f8Key, f9Key, f10Key, f11Key, f12Key
  4. 修饰键:
    • leftShiftKey, rightShiftKey, leftCtrlKey, rightCtrlKey, leftAltKey, rightAltKey, leftMetaKey, rightMetaKeyMeta键通常是 Windows 键或 Mac 上的 Command 键)
  5. 空格和回车键:
    • spaceKey, enterKey
  6. 方向键:
    • upArrowKey, downArrowKey, leftArrowKey, rightArrowKey
  7. 其他常用键:
    • escapeKey, tabKey, capsLockKey, backspaceKey, deleteKey, homeKey, endKey, pageUpKey, pageDownKey, insertKey
  8. 数字小键盘键:
    • numpadEnterKey, numpadDivideKey, numpadMultiplyKey, numpadPlusKey</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值