Unity中的new input system2D游戏中单个玩家的控制,两种较为简单的方法以及介绍另外三种方法及其应用场景

我们可以看到unity官方文档中有两个组件,但这里我只学了一个用于输入的游戏对象组件 |输入系统 |1.1.1icon-default.png?t=O83Ahttps://docs.unity.cn/Packages/com.unity.inputsystem@1.1/manual/Components.html#notification-behaviors

PlayerInput表示单个玩家,以及该玩家的关联输入操作.
PlayerInputManager处理允许多个并发用户的设置(例如,游戏中的玩家大厅和分屏游戏)。

 下面是我写的2d人物移动的代码,因为懒得删所以一起放上来了

using UnityEngine;
using UnityEngine.InputSystem;
using System.Collections;
public class PlayerController : MonoBehaviour
{
    private Animator _animator;
    [Header("跳跃施加力")]
    [SerializeField] private float jumpForce = 10f;
    [Header("移动速度")]
    [SerializeField] private float moveSpeed;
    [Header("质量")]
    [SerializeField] private float newMass = 1;
    private SpriteRenderer _renDerer;// 角色渲染器
    private Rigidbody2D _rb;// 角色刚体
    public PlayerInputControl inputControl;// 玩家输入控制
    public Vector2 inputDirection;// 玩家输入方向
    public PhysicsCheck physicsCheck;// 物理检测
    private Vector2 _velocity = Vector2.zero;// 移动速度
    [SerializeField] private float movementSmoothing = .05f;// 移动平滑度
    // 设定一个可修改的位置
    public Vector3 resetPosition;

    // 跳跃相关变量
    private bool isJumping = false;
    private float jumpCooldown = 0.1f; // 跳跃缓冲时间

    private void Awake()
    {
        InputSystem.EnableDevice(Keyboard.current);// 启用键盘输入
        inputControl = new PlayerInputControl();// 初始化输入控制
        _rb = GetComponent<Rigidbody2D>();// 获取角色刚体
        _renDerer = GetComponent<SpriteRenderer>();// 获取角色渲染器
        physicsCheck = GetComponent<PhysicsCheck>();// 获取物理检测
        _animator = GetComponent<Animator>();// 获取动画控制器
    }
    void OnEnable()
    {
        inputControl.Enable();// 启用输入控制
    }
    private void Start()
    {
        _rb.mass = newMass;// 设置角色质量
        _rb.gravityScale = 3f;  // 默认重力比例// 如果没有设置 resetPosition,默认设置为当前角色位置
        
            // 如果没有设置 resetPosition,默认设置为当前角色位置
            if (resetPosition == Vector3.zero)// 如果没有设置 resetPosition,默认设置为当前角色位置
            {
                resetPosition = transform.position;// 设置重置位置
            }
    }

    private void Update()
    {
        // 获取玩家的输入方向
        inputDirection = inputControl.Player.Move.ReadValue<Vector2>();

        // 检测角色是否在地面上并处理跳跃
        if (physicsCheck.isGrounded)
        {
            if (inputControl.Player.Jump.triggered && !isJumping)
            {
                Jump();
            }
        }
    // 处理左右移动动画
        HandleMovementAnimation();
    }

    private void FixedUpdate()
    {
        Move();
    }

    private void OnDisable()
    {
        inputControl.Disable();
    }

    public void Jump()
    {
        // 重置垂直速度,防止跳跃时漂浮
        _rb.velocity = new Vector2(_rb.velocity.x, 0f);

        // 给 Rigidbody2D 添加一次向上的力量,触发跳跃
        _rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);

        // 设置跳跃状态
        isJumping = true;
        
        // 临时调整重力,使跳跃更加有感觉
        _rb.gravityScale = 1.5f;

        // 延迟后恢复重力
        StartCoroutine(ResetGravity());
    }

    private IEnumerator ResetGravity()
    {
        // 控制跳跃后的重力逐渐恢复
        yield return new WaitForSeconds(0.1f);
        _rb.gravityScale = 3f;  // 恢复正常的重力
        isJumping = false; // 跳跃结束
    }

    public void Move()
    {
        Vector2 targetVelocity = new Vector2(inputDirection.x * moveSpeed, _rb.velocity.y);
        _rb.velocity = Vector2.SmoothDamp(_rb.velocity, targetVelocity, ref _velocity, movementSmoothing);

        if (inputDirection.x > 0)
        {
            _renDerer.flipX = false;
        }
        else if (inputDirection.x < 0)
        {
            _renDerer.flipX = true;
        }
    }

    private void HandleMovementAnimation()
    {
        if (inputDirection.x != 0 && physicsCheck.isGrounded)
        {
            _animator.SetBool("isRunning", true);
        }
        else if (physicsCheck.isGrounded)
        {
            _animator.SetBool("isRunning", false);
        }
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        // 如果碰撞对象是玩家
        if (collision.gameObject.CompareTag("yanjiang"))
        {
            // 将人物的位置重置到指定位置
            transform.position = resetPosition;
            Debug.Log("Character hit the lava! Resetting position...");
        }
    }
}

1.先从unity中的windows窗口找到Package Manager,

在unity注册表中输入input System

下载并安装

2.他让你重启完了之后点开

中的project settings,中文叫项目设置,找到player

中的other settings

中的Active Input Handling选择new input system或者both

ok,我们就可以使用unity的new input system了

2我们创建一个new input system

我们创建的时候就要把他命名为PlayerInputSystem,这是为了方便我们使用,然后我们在你里面添加

这个一般是选择用的输入方式,比如手柄,键盘等等但不限于这些名字,为了方便我是将其中的键盘改了名字,这就是里面的输入方式了,这边我们讲一下最简单的两种2d人物移动方法就是通过读取inputsystem中的数据来移动,和运用unity给予的事件回调来输入,先讲讲第一种,我们先要

将move中的所有输入变成值的形式,这是为了方便我们写他移动的代码

其中Mode这里改变值的形式,是否取整等等,如果你是手柄的话,你需要把Mode中的改成analog意思是他的值是模拟输入的 Analog 值,通常是一个包含水平(x)和垂直(y)分量的 Vector2,这两者的值在 -1 到 1 之间变化,但是我只用键盘所以我就改成了Digital Normalized,意思是取整形值,按A就是-1按D就是1.,就是类似按钮的意思。

其中Composite Type是关于多键的组合输入这里我们不管,我们选择2D Vector。

然后我们就要让unity为我们配置的组件生成代码

右边的Generate c# class勾一下apply一下,然后点击Edit asset

ok,这是第一个方法需要做的,现在我们开始写代码

[Header("移动速度")]
[SerializeField] private float moveSpeed=200f;
private Rigidbody2D _rb;// 角色刚体
public PlayerInputControl inputControl;// 玩家输入控制
public Vector2 inputDirection;// 玩家输入方向 
    void OnEnable()
    {
        inputControl.Enable();// 启用输入控制
    }
    void OnDisable()
    {
        inputControl.Disable();//关闭输入控制内存回收
    }
    private void Awake()
    {
        inputControl = new PlayerInputControl();// 初始化输入控制
        _rb = GetComponent<Rigidbody2D>();// 获取角色刚体
    }
    private void FixedUpdate()
    {
        Move();
    }//我喜欢放在FixedUpdate,因为对2d游戏来说这样性能好,而且手感也不差

    private void Update()
    {
        inputDirection = inputControl.Player.Move.ReadValue<Vector2>();//读取新输入系统的值,这里的Player和Move都是看着新输入系统的表来的
    }
    public void Move()
    {
        Vector2 targetVelocity = new Vector2(inputDirection.x * moveSpeed, _rb.velocity.y);//注意这里的y一定是_rb.velocity.y这样人物下降的时候才是正常的,而不是飘下来的
        _rb.velocity = Vector2.SmoothDamp(_rb.velocity, targetVelocity, ref _velocity,,movementSmoothing);//可以学一下SmoothDamp,对于视觉效果很不错

        if (inputDirection.x > 0)
        {
            _renDerer.flipX = false;
        }
        else if (inputDirection.x < 0)
        {
            _renDerer.flipX = true;
        }//改变方向也可以用scale但是可能后面特殊功能比如说你改了scale他就会出问题,所以我喜欢用flipX
    }
    


如果人物无法移动尝试删除OnDisable函数

3.okok我们讲第二种方法

这种方法不吃代码,但是需要你给人物加入一个playerinput组件选择player input,我们还是在playercontroller中写好代码,我们可以在unity中这个是四种方法,但是我们选择Invoke UnityEvents,想了解其他两个的可以去看第4和第5.

这个是事件回调的方法,你将move函数放在playercontroller中可以通过他来调用我们用它写个跳跃吧

然后我们就可以调用PlayerController中的Jump()函数,注意如果改了函数名或者什么的他是有可能要让你重新绑定的,其余的我给你们发一个b站大佬的教学02-接收InputAction的Unity事件_哔哩哔哩_bilibili

4.unity中还可以用Send Messages

这种方法不常用,因为他性能损耗有点严重,特别是对象特别多的情况

SendMessage 的基本用法

SendMessage 允许你向目标对象发送一个指定的方法名称(字符串)并执行对应的方法。这个方法通常用于当你不确定目标对象的方法名时,或者你不想直接调用某个方法时。所以我们可以去看b站中教学这个方法的一些内容,在特定情况下这个真的很有用,特别是父对象向子对象传递信息,我们就可以不引用各种傻不拉几的变量,而是用传递信息,对写代码特别方便,就是有个问题,在重复调用的情况下对性能可能有影响

它存在性能和类型安全上的问题,因此在性能要求较高或需要更强类型安全的情况下,通常推荐使用其他方法,如直接调用方法、事件或委托等。

5使用委托也就是Invoke C Sharp Events

也就是所谓的观察者模式中的一个实现

  • 定义事件:通过委托定义事件。事件本质上是一个委托。
  • 触发事件:使用 ?.Invoke() 来触发事件,确保事件不为空,避免空引用异常。
  • 订阅事件:通过 += 运算符将处理方法订阅到事件。
  • 取消订阅事件:使用 -= 运算符取消订阅,避免多次调用相同事件处理程序。

6.BroadCast Messages

BroadcastMessage 是一种用于向目标对象及其所有子对象发送消息的机制。它会遍历目标对象的所有子物体,并在它们上面调用指定的方法。BroadcastMessage 是 Unity 提供的一种便捷的方式,可以让你在层级结构中的多个对象之间传播消息。

  • BroadcastMessage 是 Unity 中一个非常方便的消息广播机制,可以让你向一个对象及其所有子物体发送消息并执行特定方法。
  • 它通过遍历层级结构中的子对象并调用指定的方法,适用于需要广泛通知多个对象的场景。
  • 尽管非常方便,但它也有性能和类型安全方面的缺点,因此在复杂或性能要求较高的项目中,可以考虑使用其他更高效和类型安全的消息传递机制,如事件和委托。

7.总结 

我们讲了一个new input system输入方式,一个借鉴了别人的,介绍了剩下三个,加油诸君,我们共同学习进步。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值