使用Unity新输入系统 New Input System 实现人物移动跳跃(unity 2022.3)

一、配置

  1. 设置Edit -> Project Setting -> Player -> Other Setting 修改其中两个部分内容。

    • 修改API等级为 .NET Framework
    • Active Input Handling 选择新版输入系统
      3338a132-02fd-4510-ab3d-55deda5af766
  2. 安装 Input System
    Window -> Package Manager -> 搜索并安装

二、设置

1、给场景中的Player添加 `Player Input` 组件, 点击Create Actions,unity会自动生成一个配置表,已经有一些默认操作(免得自己动手添加了!)。可以根据自己需求修改按键。
2、由于使用代码方式,可以删除`Player Input` 组件。点击之前生成的配置表,勾选Generate C# Class 选项,点击Apply。系统会自动生成一个同名称脚本。如图所示

2d104d23-6ed7-49e1-b530-85d2da972162

三、具体使用

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。如下图绑定按键

d318042c-aaa8-48a4-8726-807f81af562d
代码如下:

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

98f06a23-ecf6-4ca0-a62b-d20e0e27111a

绑定键盘按钮以及手柄按钮
842432c0-22bf-44b1-bed9-9bf71ec86651

34882754-e316-4651-86bb-192f76ea58d9

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);
    }
}

posted on 2025-08-06 19:40  juaa  阅读(270)  评论(0)    收藏  举报