Unity Input System 官方案例学习笔记
01 前言
作者:hzb
开始时间:2023-12-9
最后更新时间:2023-12-11
资料来源:Unity Input System 官方案例
该文章将从Unity Input System的所给的官方案例中学习这个新的输入系统的使用,资料中所有中文由ChatGPT4提供翻译,同时部分补充即实例由GPT4提供,如有错误欢迎指出。
案例导入
- Package Manager
- Project Settings
02 案例: Simple Demo
这个示例展示了如何使用输入系统设置一个简单的角色控制器。由于有多种方式可以做到这一点,该示例展示了几种方法。每个演示都设置为一个单独的场景。所有场景中的基本功能都是相同的。你可以移动、四处看看,以及向场景中发射弹丸(彩色立方体)。在某些场景中,只支持游戏手柄,但更复杂的演示支持多种不同的输入同时使用。
(1) UsingState
案例分析
案例README
这个演示从最低级开始,展示了如何通过在MonoBehaviour.Update
函数中直接轮询输入状态来连接输入。为了简单起见,它只处理游戏手柄,但对于其他类型的输入设备(例如使用Mouse.current
和Keyboard.current
)也以类似方式工作。
这里演示的关键API是Gamepad.current
和InputControl.ReadValue
。
public class SimpleController_UsingState : MonoBehaviour
{
//...
public void Update()
{
var gamepad = Gamepad.current;
if (gamepad == null)
return;
var move = Gamepad.leftStick.ReadValue();
//...
}
}
在这个演示中,主要关注点是如何直接从游戏手柄(或其他输入设备)获取实时输入数据,并基于这些数据来更新游戏中的角色或对象状态。示例可能包括如何读取摇杆位置、按钮按下状态等,来实现角色的移动、跳跃或其他动作。
关键步骤
关键特点和步骤可能包括:
- 获取当前游戏手柄:
- 使用
Gamepad.current
来获取当前连接的游戏手柄。
- 使用
- 轮询按键状态:
- 检查特定按钮(如南方向按钮)在当前帧是否被按下或释放。
- 读取摇杆输入:
- 获取摇杆(如左摇杆
leftStick
)的当前位置,这通常返回一个Vector2
类型的值,表示摇杆的水平和垂直偏移。
- 获取摇杆(如左摇杆
- 应用输入到游戏逻辑:
- 根据获取到的输入值来控制角色的移动、转向或其他行为。
- 简单实现:
- 这种方法通常比较直接和简单,适合快速原型开发或小型项目。
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
的使用方法相似,但有几个关键的区别和优势:
- 输入设备的直接访问:新的输入系统允许直接访问特定的输入设备(如
Gamepad
)。这意味着您可以直接查询游戏手柄的状态,而不是通过一般的输入轴或按钮映射。 - 设备独立性:新的输入系统设计用来更好地处理多种输入设备,包括游戏手柄、键盘、鼠标等,每种设备都有其专有的类和方法。
- 更好的按键状态管理:新系统提供了更细致的按键状态查询,如
wasPressedThisFrame
、wasReleasedThisFrame
等,这使得管理按键状态(例如检测单次按下或释放)更为简便。
总的来说,UsingState
在设计上提供了更多的灵活性和控制力,特别是在处理多种输入设备和复杂的输入需求时。虽然其基本原理(即每帧检查输入状态)与旧的Input Manager
相似,但新系统提供了更多的功能和更好的设备管理。
案例补充
Gamepad
在 Unity 的新输入系统中使用 Gamepad
类时,通常会用到以下几种状态和功能:
- 按键状态:
wasPressedThisFrame
: 在当前帧中,该按键是否被首次按下。wasReleasedThisFrame
: 在当前帧中,该按键是否被释放。isPressed
: 该按键当前是否被持续按下。
- 摇杆和触摸板:
leftStick
,rightStick
: 分别代表左右摇杆的当前位置(返回Vector2
)。dpad
: 方向键的当前位置(也是Vector2
)。
- 触发器:
leftTrigger
,rightTrigger
: 游戏手柄上左右触发器的当前值(通常是0到1的浮点数)。
- 按钮:
- 如
buttonSouth
(通常是A或X键)、buttonNorth
(通常是Y或△键)、buttonEast
(通常是B或○键)、buttonWest
(通常是X或□键)。 startButton
,selectButton
: 分别代表开始和选择按钮。
- 如
- 震动功能:
SetMotorSpeeds(float lowFrequency, float highFrequency)
: 设置游戏手柄的震动强度。
- 设备状态:
Gamepad.current
: 获取当前连接的游戏手柄。Gamepad.all
: 获取所有连接的游戏手柄列表。
使用这些状态和功能,可以检测游戏手柄上的按键、摇杆、触发器的当前状态,以及设置震动等。这对于创建游戏中的角色控制、菜单导航、交互响应等功能非常有用。通过这些API,可以为玩家提供丰富而直观的游戏操作体验。
KeyBoard
在 Unity 的新输入系统中,针对键盘的常用状态和功能包括以下几个方面:
- 按键状态:
wasPressedThisFrame
: 在当前帧中,指定的键是否被首次按下。wasReleasedThisFrame
: 在当前帧中,指定的键是否被释放。isPressed
: 指定的键当前是否被持续按下。
- 特定按键的访问:
- 可以通过
Keyboard.current.<keyName>.ReadValue()
或Keyboard.current.<keyName>.isPressed
等方式访问特定键的状态,其中<keyName>
是键的名称,例如spaceKey
、enterKey
、leftShiftKey
等。
- 可以通过
- 所有按键的状态:
Keyboard.current.allKeys
: 获取一个包含所有按键的数组,可以用来遍历或查询特定键的状态。
- 键盘的整体状态:
Keyboard.current
: 获取当前连接的键盘。
- 文本输入:
onTextInput
: 事件,可以用来接收文本输入,特别是对于需要文本输入(如聊天或表单填写)的应用。
- 修饰键状态:
- 如
shiftKey
,ctrlKey
,altKey
,metaKey
(Windows上的Windows键,Mac上的Command键)等,用于检测这些修饰键是否被按下。
- 如
- 键盘布局:
Keyboard.current.keyboardLayout
: 获取当前键盘布局的名称。
通过这些API,可以精确地控制键盘输入,响应玩家的按键操作,实现角色控制、UI交互、文本输入等功能。这对于确保玩家能够通过键盘与游戏或应用程序有效交互非常重要。
键盘的每个键都有一个对应的名称,用于标识和访问该键的状态。以下是一些常用键的名称列表:
- 字母键:
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
- 数字键:
digit1Key
,digit2Key
,digit3Key
,digit4Key
,digit5Key
,digit6Key
,digit7Key
,digit8Key
,digit9Key
,digit0Key
- 功能键:
f1Key
,f2Key
,f3Key
,f4Key
,f5Key
,f6Key
,f7Key
,f8Key
,f9Key
,f10Key
,f11Key
,f12Key
- 修饰键:
leftShiftKey
,rightShiftKey
,leftCtrlKey
,rightCtrlKey
,leftAltKey
,rightAltKey
,leftMetaKey
,rightMetaKey
(Meta
键通常是 Windows 键或 Mac 上的 Command 键)
- 空格和回车键:
spaceKey
,enterKey
- 方向键:
upArrowKey
,downArrowKey
,leftArrowKey
,rightArrowKey
- 其他常用键:
escapeKey
,tabKey
,capsLockKey
,backspaceKey
,deleteKey
,homeKey
,endKey
,pageUpKey
,pageDownKey
,insertKey
- 数字小键盘键:
numpadEnterKey
,numpadDivideKey
,numpadMultiplyKey
,numpadPlusKey</