使用Unity新输入系统 New Input System 实现人物移动跳跃(unity 2022.3)
一、配置
-
设置Edit -> Project Setting -> Player -> Other Setting 修改其中两个部分内容。
- 修改API等级为
.NET Framework - Active Input Handling 选择新版输入系统
![3338a132-02fd-4510-ab3d-55deda5af766]()
- 修改API等级为
-
安装 Input System
Window -> Package Manager -> 搜索并安装
二、设置
1、给场景中的Player添加 `Player Input` 组件, 点击Create Actions,unity会自动生成一个配置表,已经有一些默认操作(免得自己动手添加了!)。可以根据自己需求修改按键。2、由于使用代码方式,可以删除`Player Input` 组件。点击之前生成的配置表,勾选Generate C# Class 选项,点击Apply。系统会自动生成一个同名称脚本。如图所示

三、具体使用
1、实现人物移动与翻转
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rb;
public PlayerInputControl inputControl;
public Vector2 inputDirection;
[Header("基本参数")]
public float speed;
private void Awake()
{
inputControl = new PlayerInputControl();
rb = GetComponent<Rigidbody2D>();
}
private void OnEnable()
{
inputControl.Enable();
}
private void OnDisable()
{
inputControl.Disable();
}
private void Update()
{
inputDirection = inputControl.GamePlay.Move.ReadValue<Vector2>();
}
private void FixedUpdate()
{
Move();
}
public void Move()
{
//人物移动
rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime, rb.velocity.y);
//由于手柄操作inputDirection的值不一定只有-1和1,所以需要处理
int faceDir = (int) transform.localScale.x;
if (inputDirection.x > 0)
faceDir = 1;
if (inputDirection.x < 0)
faceDir = -1;
//人物翻转
transform.localScale = new Vector3(faceDir,1,1);
}
2、实现人物按左shift键强制走路
通过调整速度变量,当按键被按下时,人物速度减少一半,实现走路状态切换。松开时回到原速度。Input System配置表中新加跳跃WalkButton的Action,类型为Button。如下图绑定按键

代码如下:
public class PlayerController : MonoBehaviour
{
....
[Header("基本参数")]
public float speed;
public float runSpeed;
public float walkSpeed;
...
private void Awake()
{
...
#region 强制走路
runSpeed = speed;
walkSpeed = runSpeed/2;
//持续按下时走路形态,取消时跑步
inputControl.GamePlay.WalkButton.performed += ctx =>
{
if (physicsCheck.isGround)
speed = walkSpeed;
};
inputControl.GamePlay.WalkButton.canceled += ctx =>
{
if (physicsCheck.isGround)
speed = runSpeed;
};
#endregion
}
...
}
3、实现人物跳跃
Input System配置表中新加跳跃Jump的Action,类型为Button
绑定键盘按钮以及手柄按钮


PlayerController新加代码
public float jumpForce;
private void Awake()
{
.....
//跳跃按钮事件注册
inputControl.GamePlay.Jump.started += JumpOnstarted;
}
private void JumpOnstarted(InputAction.CallbackContext obj)
{
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
3.1 解决无限向上跳跃问题
使用isGround变量,碰撞体检测人物是否在地面,只有当人物在地面时才能实现跳跃。新加脚本 PhysicsCheck 专门用来物理检测。代码如下:using UnityEngine;
public class PhysicsCheck : MonoBehaviour
{
[Header("检测参数")]
public float checkRadius;
public Vector2 bottomOffset;
public LayerMask groundLayer;
[Header("状态")]
public bool isGround;
void Update()
{
Check();
}
public void Check()
{
//检测地面
isGround = Physics2D.OverlapCircle((Vector2)transform.position + bottomOffset, checkRadius,groundLayer);
}
//绘制检测范围
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere((Vector2)transform.position + bottomOffset, checkRadius);
}
}
//PlayerController 脚本补充如下
private PhysicsCheck physicsCheck;
private void Awake()
{
....
physicsCheck = GetComponent<PhysicsCheck>();
}
private void JumpOnstarted(InputAction.CallbackContext obj)
{
if (physicsCheck.isGround)
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
3.2 解决人物卡在墙上问题
在文件夹中新建物理材质 `Physics Material 2D`,将该材质的摩擦力Friction设置为0,再将该材质赋予人物做挂碰撞体的Material中,再次运行发现墙面变光滑!四、完整代码
1、PlayerController 人物控制脚本using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rb;
private PhysicsCheck physicsCheck;
public PlayerInputControl inputControl;
public Vector2 inputDirection;
[Header("基本参数")]
public float speed;
public float runSpeed;
public float walkSpeed;
public float jumpForce;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
inputControl = new PlayerInputControl();
physicsCheck = GetComponent<PhysicsCheck>();
//跳跃按钮事件注册
inputControl.GamePlay.Jump.started += JumpOnstarted;
#region 强制走路
runSpeed = speed;
walkSpeed = runSpeed/2;
//持续按下时走路形态,取消时跑步
inputControl.GamePlay.WalkButton.performed += ctx =>
{
if (physicsCheck.isGround)
speed = walkSpeed;
};
inputControl.GamePlay.WalkButton.canceled += ctx =>
{
if (physicsCheck.isGround)
speed = runSpeed;
};
#endregion
}
private void OnEnable()
{
inputControl.Enable();
}
private void OnDisable()
{
inputControl.Disable();
}
private void Update()
{
inputDirection = inputControl.GamePlay.Move.ReadValue<Vector2>();
}
private void FixedUpdate()
{
Move();
}
public void Move()
{
//人物移动
rb.velocity = new Vector2(inputDirection.x * speed * Time.deltaTime, rb.velocity.y);
//由于手柄操作inputDirection的值不一定只有-1和1,所以需要处理
int faceDir = (int) transform.localScale.x;
if (inputDirection.x > 0)
faceDir = 1;
if (inputDirection.x < 0)
faceDir = -1;
//人物翻转
transform.localScale = new Vector3(faceDir,1,1);
}
private void JumpOnstarted(InputAction.CallbackContext obj)
{
if (physicsCheck.isGround)
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
2、PhysicsCheck物理检测脚本
using UnityEngine;
public class PhysicsCheck : MonoBehaviour
{
[Header("检测参数")]
public float checkRadius;
public Vector2 bottomOffset;
public LayerMask groundLayer;
[Header("状态")]
public bool isGround;
void Update()
{
Check();
}
public void Check()
{
//检测地面
isGround = Physics2D.OverlapCircle((Vector2)transform.position + bottomOffset, checkRadius,groundLayer);
}
//绘制检测范围
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere((Vector2)transform.position + bottomOffset, checkRadius);
}
}

浙公网安备 33010602011771号