8.InputAction类
8.1 知识点
InputAction是什么?
- 顾名思义,InputAction是InputSystem帮助我们封装的输入动作类。
- 它的主要作用是不需要我们通过写代码的形式来处理输入,而是直接在Inspector窗口编辑想要处理的输入类型。当输入触发时,我们只需要把精力花在输入触发后的逻辑处理上。
- 我们在想要用于处理输入动作的类中,申明对应的InputAction类型的成员变量(注意:需要引用命名空间UnityEngine.InputSystem)。
比如创建移动和开火两个输入动作
把脚本挂载到空对象上,可以在inspector窗口编辑InputAction
InputAction的缺点是不会显示变量名。可以添加一个头特性进行区分。
[Header("move Binding")]
public InputAction move;
[Header("axis 1D Axis")]
public InputAction axis;
InputAction参数相关
点击齿轮
Actions 输入动作设置 设置检测哪些输入
Action Type:动作类型
- Value:值类型,主要用于状态连续更改的输入,例如鼠标的移动,手柄的遥感。如果有多个设备绑定这个Action,只会发送其中一个设备(最受控制的)的输入。比如多个手柄只会检测主手柄的输入。
- Button:按钮类型,用于每次按下时触发的Action
- Pass Through:直通类型,和Value一样,区别在于如果有多个设备绑定这个Action,会发送所有设备的输入。比如多个手柄都会响应他的输入组。
Control Type:控制类型
- 在这里选择对应的类型,之后在选择对应设备按键相关属性时。会根据你选择内容的不同,筛选对应内容。这上面显示的内容就是各设备属性的返回值类型。当你选择他们后,非选择的类型将不会在之后的按键设置中出现、很多内容我们基本用不到。相当于是在这里筛选输入设备。
- Any 任何值
- Analog 模拟值,浮点数
- Axis 一维轴浮点数,例如:摇杆输入返回值
- Bone 骨骼
- Digital 数字
- Double 浮点
- Dpad 4向按钮,例如:摇杆上的D-pad
- Eyes VR相关数值
- Integer 整数
- Quaternion 四元数
- Stick 摇杆相关
- Touch 触屏相关
- Vector2 2维向量
- Vector3 3维向量
- 比如控制类型选择了Vector2,那么在点击加号添加绑定,点击选择号设备后,只能选择返回Vector2变量类型的输入设备,比如手柄摇杆,鼠标位置等,因为进行了筛选。假如选择了按钮类型,那么只能选择按钮返回值的输入设备,比如鼠标左键,手柄按键等。
Interactions 相互作用设置 用于特殊输入,比如长按、多次点击等等 当满足条件时才会触发这个行为(设置长按时间、点击次数等等)
3个事件
- 之后通过代码添加监听事件
- 开始started:比如鼠标点击 一点击就触发了时间
- 触发performed:比如长按 长按1秒后就触发该事件
- 结束canceled:比如长按 但是只长按了0.5秒就松开了 结束该事件
相互作用设置参数
- Hold 长按
- 适用于需要输入设备保持一段时间的操作。当按钮按下会触发started,若在松开按钮前,按住时间大于等于Hold Time则会触发performed(时间一到就触发),否则触发canceled。
- 比如设置长按一秒 才会触发performed事件
- Tap 点击
- 和Hold相反,需要在一段时间内按下松开来触发。当按钮按下会触发started,若在Max Tap Duriation时间内(小于)松开按钮,触发performed,否则触发canceled。
- 其实就是按下抬起
- 比如要在0.2秒内按下抬起 才算做一次点击 执行performed事件
- 和Hold相反,需要在一段时间内按下松开来触发。当按钮按下会触发started,若在Max Tap Duriation时间内(小于)松开按钮,触发performed,否则触发canceled。
- SlowTap 缓慢点击
- 类似Hold,但是它在按住时间大于等于Max Tap Duriation的时候,并不会立刻触发performed,而是会在松开的时候才触发performed
- 比如当前按下时间要大于0.6秒后,松开鼠标,才会触发performed事件
- MultiTap 多次点击
- 用作于多次点击,例如双击或者三连击。Tap Count为点击次数,Max Tap Spacing为每次点击之间的间隔(默认值为 2 * Max Tap Duration)。Max Tap Duration为每次点击的持续时间,即按下和松开按钮的这段时间。当每次点击时间小于Max Tap Duration,且点击间隔时间小于Max Tap Spacing,点击Tap Count次,触发performed。
- 比如 双击时间要小于0.75秒才算双击 0.2秒内点击松开才算点击
- Press 按下
- 可以实现类似按钮的操作
- Trigger Behavior 触发行为
- Press Only:按下的时候触发started和performed。不触发canceled
- Release Only:按下的时候触发started,松开的时候触发performed
- Press And Release:按下的时候触发started和performed,松开的时候会再次触发started和performed。不触发canceled
- Press Point:在Input System中,每个按钮都有对应的浮点值,例如普通的按钮,将会在0(未按下)和1(按下)之间。因此我们可以利用这个值(Press Point)来进行区分,当大于等于这个值则认为按钮按下了。
Processors 值处理加工设置 对得到的值进行处理加工 就是输入设备的值传过来后进行二次处理
- Clamp 将输入值钳制到[min..max]范围。
- Invert 反转控件中的值(即,将值乘以-1)。
- Invert Vector 2 反转控件中的值(即,将值乘以-1)。如果invertX为真,则反转矢量的x轴;如果invertY为真,则反转矢量的y轴。
- Invert Vector 3 反转控件中的值(即,将值乘以-1)。如果反转x为真,则反转矢量的x轴;如果反转y为真,则反转y轴;如果反转z为真,则反转z轴。
- Normalize 如果最小值>=零,则将[min..max]范围内的输入值规格化为无符号规格化形式[0..1],如果最小值<零,则将输入值规格化为有符号规格化形式[-1..1]。
- Normalize Vector 2 将输入向量规格化为单位长度(1)。
- Normalize Vector 3 将输入向量规格化为单位长度(1)
- Scale 将所有输入值乘以系数。
- Scale Vector 2 将所有输入值沿x轴乘以x,沿y轴乘以y。
- Scale Vector 3 将所有输入值沿x轴乘以x,沿y轴乘以y,沿z轴乘以z。
- 死区:死区可以理解为最小最大范围的扩大取值。比如摇杆在0-0.125的时候都认为是0,0.925以上都认为是1。可以解决轻微摇动会产生输入和最大摇动都没拉满的问题。
- Axis Deadzone axis死区处理器缩放控件的值,使绝对值小于最小值的任何值为0,绝对值大于最大值的任何值为1或-1。许多控件没有精确的静止点(也就是说,当控件位于中心时,它们并不总是精确报告0)。在死区处理器上使用最小值可避免此类控件的无意输入。此外,当轴一直移动时,某些控件不一致地报告其最大值。在死区处理器上使用最大值可确保在这种情况下始终获得最大值。
- Stick Deadzone 摇杆死区处理器缩放Vector2控件(如摇杆)的值,以便任何幅值小于最小值的输入向量都将得到(0,0),而任何幅值大于最大值的输入向量都将规格化为长度1。许多控件没有精确的静止点(也就是说,当控件位于中心时,它们并不总是精确地报告0,0)。在死区处理器上使用最小值可避免此类控件的无意输入。此外,当轴一直移动时,某些控件不一致地报告其最大值。在死区处理器上使用最大值可确保在这种情况下始终获得最大值。
点击+号
比如添加了鼠标左键点击事件,并开启了代码,点击会进入逻辑
点击一下后
可以关联添加多个被监听的点击设备,比如下面按下1也会执行
Add Binding 添加新的输入绑定(单按键输入)比如鼠标左右键按下
Add Positive\Negative Binding Or Add 1D Axis Composite 添加1D轴组合(类似Input中的水平竖直热键,返回-1~1之间的一个值)
条下的参数
- Negative:负面按键,例如 0~-1
- Positive:正向按键,例如 0~1
双击1DAxis的参数
- Composite Type:复合类型 一般不修改
- MinValue:最小值
- MaxValue:最大值
- Which Side Wins:哪一方获胜(当同时按下时如何处理 比如同时按下前进后退ws时 看ws谁获胜 可能打平)
- Neither:双方没有优先权,返回MinValue和MaxValue的中间值
- Positive:正面优先,返回maxValue
- Negative:负面优先,返回minValue
双击下面的条可以选择监听的按键 比如下面 按S代表-1 W代表1
代码开启1D轴后 可以在Update中实时打印选择按下的值
axis.Enable();
void Update()
{
print(axis.ReadValue<float>());
}
如下图 因为选择了Neither 0代表不按或者ws一起按 -1代表s 1代表w
Add Up\Down\Left\Right Composite Or Add 2D Vector Composite 添加2D向量组合(类似将Input中的水平竖直热键组合在一起,得到的Vector中的x,y分别表示两个轴)
条下的参数
- Up:上 ( 0 , 1 )
- Down:下 ( 0 , -1 )
- Left:左 ( -1 , 0 )
- Right:右 ( 1 , 0 )
点击2DVector的参数
- Composite Type:复合类型
- Mode:处理模式
- Analog:模拟值,浮点值
- Digital Normalized:单位化向量
- Digital:未单位化的向量
双击点击下方条选择监听的按键 比如键盘的上下左右键
代码开启2D轴后 可以在Update中实时打印选择按下的值
vector2D.Enable();
void Update()
{
print(vector2D.ReadValue<Vector2>());
}
Add Up\Down\Left\Right\Forward\Backward Composite 添加3D向量组合
- 3D和2D类似 无非是多了一维的参数 要关联多两个键
Add Button With One Modifier Composite 添加带有一个复合修改器的按钮(可以理解为双组合键, 比如Ctrl+C、Ctrl+V)
条下参数
- Modifier:复合输入内容
- Button:输入内容
- 举例:复制按键Ctrl+C
- Ctrl为Modifier
- C为Button
btnOne.Enable();
btnOne.performed += (context) =>
{
print("组合键触发");
};
Add Button With Two Modifier Composite 添加带有两个复合修改器的按钮(可以理解为三组合键,比如Ctrl+K+U)
- 和单组合键类似
条下参数
- Modifier:复合输入内容
- Button:输入内容
- 举例:复制按键Ctrl+K+U
- Ctrl为Modifier1
- K为Modifier2
- U为Button
创建一种输入后
比如值创建一个单键输入 会出现一个条 双击选择输入设备
Path:从哪个控件接受输入
- Usages:常用用法
- GamePad:游戏手柄
- Joystick:操纵杆
- Keyboard:键盘
- Mouse:鼠标
- Pen:笔
- Pointer:指针
- Sensor:传感器
- TouchScreen:触屏
- Tracked Device:履带装置
- XR Controller:XR 控制器
- XR HMD:XR 头戴显示器
- Other:其它
InputAction的使用
启用输入检测
- move.Enable();
操作监听相关
开始操作
move.started += StartedTestFun;
private void StartedTestFun(InputAction.CallbackContext context)
{
print("开始事件调用");
}
真正触发
move.performed += (context) =>
{
print("触发事件调用");
};
结束操作
move.canceled += (context) =>
{
print("结束事件调用");
};
关键参数 CallbackContext
//真正触发
move.performed += (context) =>
{
print("触发事件调用");
//当前状态
//没有启用 Disabled
//等待 Waiting
//开始 Started
//触发 Performed
//结束 Canceled
//context.phase
print("当前状态"+context.phase);
//动作行为信息
print("动作行为信息" + context.action.name);
//控件(设备)信息
print("控件(设备)信息" + context.control.name);
//获取值
//context.ReadValue<float>
//持续时间
print("持续时间"+context.duration);
//开始时间
print("开始时间"+context.startTime);
};
特殊输入设置
注意Interactions
- 可以点击上方Move条的齿轮 设置的为整个Move的所有关联设备 要长按五秒才能触发performed事件
- 也可以点击下方条 专门只为右键设置长按五秒才能触发performed事件
点击按钮或手动找到InputSystem默认值的设置
可以点击创建InputSystem默认值的设置文件按钮,会创建出设置文件,可以修改设置文件的值
Input System Package设置
UpdateMode:更新模式
Process Events In Dynamic Update:在动态更新中处理事件
Process Events In Fixed Update:在固定更新中处理事件
Process Events Manually:手动处理事件
Background Behavior:后台行为
Reset And Disable Non Background Devices:重置和禁用非后台设备
Reset And Disable All Devices:重置和禁用所有设备
Ignore Focus:忽略焦点
Filter Noise on .current:过滤当前设备的噪音
Compensate Orientation:定向补偿
Default Deadzone Min:默认死区最小值
Default Deadzone Max:默认死区最大值
Default Button Press Point:默认按钮按下点
Button Release Threshold:按钮释放阈值
Default Tap TIme:默认点击时间
Default Slow Tap Time:默认慢速点击时间
Default Hold Time:默认保持时间
Tap Radius:点击半径
MultTap Delay TIme:多次点击延迟时间
Supported Devices:支持的设备
- 如果希望输入系统支持其可以识别的所有输入设备,请将支持的设备保留为空。
- 但是,如果您只对某一组设备感兴趣,那么在此处添加它们将缩小编辑器中显示的范围,并避免从与项目无关的设备获取输入。
- 在此处添加设备时,任何未被分类为受支持的设备都将显示在输入调试器的“不受支持的设备”下
Motion Usage:动作使用
Description:描述
Play Mode Input Behavior:播放模式输入行为
Pointers And Keyboards Respect Game View Focus:指针和键盘遵守游戏视图焦点
All Devices Respect Game View Focus:所有设备都遵守游戏视图焦点
All Device Input Always Goes To Game View:所有设备输入始终进入游戏视图
8.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Lesson08_InputAction类 : MonoBehaviour
{
[Header("move Binding")]
public InputAction move;
[Header("axis 1D Axis")]
public InputAction axis;
[Header("2D Vector")]
public InputAction vector2D;
[Header("3D Vector")]
public InputAction vector3D;
[Header("Button With One")]
public InputAction btnOne;
void Start()
{
#region 知识点一 InputAction是什么?
//顾名思义,InputAction是InputSystem帮助我们封装的输入动作类
//它的主要作用,是不需要我们通过写代码的形式来处理输入
//而是直接在Inspector窗口编辑想要处理的输入类型
//当输入触发时,我们只需要把精力花在输入触发后的逻辑处理上
//我们在想要用于处理输入动作的类中
//申明对应的InputAction类型的成员变量(注意:需要引用命名空间UnityEngine.InputSystem)
#endregion
#region 知识点二 InputAction参数相关
#endregion
#region 知识点三 InputAction的使用
//1.启用输入检测
move.Enable();
//2.操作监听相关
//开始操作
move.started += StartedTestFun;
//真正触发
move.performed += (context) =>
{
print("触发事件调用");
//当前状态
//没有启用 Disabled
//等待 Waiting
//开始 Started
//触发 Performed
//结束 Canceled
//context.phase
print("当前状态"+context.phase);
//动作行为信息
print("动作行为信息" + context.action.name);
//控件(设备)信息
print("控件(设备)信息" + context.control.name);
//获取值
//context.ReadValue<float>
//持续时间
print("持续时间"+context.duration);
//开始时间
print("开始时间"+context.startTime);
};
//结束操作
move.canceled += (context) =>
{
print("结束事件调用");
};
//3.关键参数 CallbackContext
//当前状态
//动作行为信息
//控件信息
//获取值
//持续时间
//开始时间
axis.Enable();
vector2D.Enable();
vector3D.Enable();
btnOne.Enable();
btnOne.performed += (context) =>
{
print("组合键触发");
};
#endregion
#region 知识点四 特殊输入设置
//1.Input System 基础设置(一些默认值设置)
//2.设置特殊输入规则
#endregion
}
#region 知识点三 InputAction的使用
private void StartedTestFun(InputAction.CallbackContext context)
{
print("开始事件调用");
}
#endregion
void Update()
{
//print(axis.ReadValue<float>());
//print(vector2D.ReadValue<Vector2>());
//print(vector3D.ReadValue<Vector3>());
}
}
8.3 练习题
使用InputAction类,为一个3D对象制作通过鼠标键盘控制其移动、跳跃、开火的逻辑(移动跳跃 利用物理系统刚体加力)
创建一个平面和一个球体 球体改颜色 添加刚体
创建脚本挂载到小球上。创建移动、跳跃、开火InputAction。添加分组特性。
[Header("移动控制")]
public InputAction move;
[Header("跳跃控制")]
public InputAction jump;
[Header("开火控制")]
public InputAction fire;
创建刚体变量 Start中得到小球的刚体
private Rigidbody body; // 刚体组件,用于实现物体的运动
void Start()
{
body = this.GetComponent<Rigidbody>(); // 获取当前游戏对象的刚体组件
}
给移动控制关联wasd和上下左右, 启用移动控制输入,创建存储移动方向的变量 Start中启用移动控制输入,Update中读取移动输入的值,将读取的y和z进行转换后给球体添加力
private Vector3 dir; // 存储移动方向的向量
move.Enable(); // 启用移动控制输入
void Update()
{
dir = move.ReadValue<Vector2>(); // 读取移动输入的值,即鼠标或键盘的输入
dir.z = dir.y; // 将移动向量的y值赋给z值,因为我们只需要在水平方向上移动
dir.y = 0; // 将移动向量的y值设为0,保证物体不会上下移动
body.AddForce(dir); // 通过刚体组件给物体施加力,实现移动
}
给跳跃添加空格按键监听,启用跳跃控制输入,Start中给跳跃事件的触发事件添加监听,让物体施加向上的力(利用物理系统刚体加力)
jump.Enable(); // 启用跳跃控制输入
jump.performed += (context) =>
{
// 跳跃逻辑,给物体施加向上的力(利用物理系统刚体加力)
body.AddForce(Vector3.up * 200);
};
点击发子弹要做成鼠标当前位置的获取和射线检测
创建子弹预制体,添加子弹脚本让子弹一直往前飞,两秒后销毁
public class Bullet : MonoBehaviour
{
void Start()
{
Destroy(this.gameObject, 2);
}
void Update()
{
this.transform.Translate(Vector3.forward * 20 * Time.deltaTime);
}
}
给开火事件添加左按键,启用开火控制输入,声明一个公共游戏对象bullet,用于存储子弹的预制体,外部关联。Start中给开火事件的触发事件添加监听,把鼠标位置转成射线得到方向向量,生成子弹设置初始旋转
// 声明一个公共游戏对象bullet,用于存储子弹的预制体
public GameObject bullet;
fire.Enable(); // 启用开火控制输入
fire.performed += (context) =>
{
// 开火逻辑,通过鼠标位置的射线检测确定子弹飞出去的方向
RaycastHit info;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue()), out info))
{
// 得到子弹飞出去的向量
Vector3 point = info.point;
//让y轴和小球y相等 否则可能会在地下发射
point.y = this.transform.position.y;
//得到子弹向量
Vector3 dir = point - this.transform.position;
// 创建子弹实例并飞出去
Instantiate(bullet, this.transform.position, Quaternion.LookRotation(dir));
}
};
8.4 练习题代码
Lesson08_练习题
using Player;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Lesson08_练习题 : MonoBehaviour
{
//使用InputAction类
//为一个3D对象制作通过鼠标键盘控制其
//移动、跳跃、开火的逻辑(移动跳跃 利用物理系统刚体加力)
// 声明一个公共游戏对象bullet,用于存储子弹的预制体
public GameObject bullet;
[Header("移动控制")]
public InputAction move;
[Header("跳跃控制")]
public InputAction jump;
[Header("开火控制")]
public InputAction fire;
private Rigidbody body; // 刚体组件,用于实现物体的运动
private Vector3 dir; // 存储移动方向的向量
void Start()
{
body = this.GetComponent<Rigidbody>(); // 获取当前游戏对象的刚体组件
move.Enable(); // 启用移动控制输入
jump.Enable(); // 启用跳跃控制输入
fire.Enable(); // 启用开火控制输入
jump.performed += (context) =>
{
// 跳跃逻辑,给物体施加向上的力(利用物理系统刚体加力)
body.AddForce(Vector3.up * 200);
};
fire.performed += (context) =>
{
// 开火逻辑,通过鼠标位置的射线检测确定子弹飞出去的方向
RaycastHit info;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue()), out info))
{
// 得到子弹飞出去的向量
Vector3 point = info.point;
//让y轴和小球y相等 否则可能会在地下发射
point.y = this.transform.position.y;
//得到子弹向量
Vector3 dir = point - this.transform.position;
// 创建子弹实例并飞出去
Instantiate(bullet, this.transform.position, Quaternion.LookRotation(dir));
}
};
}
void Update()
{
dir = move.ReadValue<Vector2>(); // 读取移动输入的值,即鼠标或键盘的输入
dir.z = dir.y; // 将移动向量的y值赋给z值,因为我们只需要在水平方向上移动
dir.y = 0; // 将移动向量的y值设为0,保证物体不会上下移动
body.AddForce(dir); // 通过刚体组件给物体施加力,实现移动
}
}
Bullet
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
void Start()
{
Destroy(this.gameObject, 2);
}
void Update()
{
this.transform.Translate(Vector3.forward * 20 * Time.deltaTime);
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com