我们可以看到unity官方文档中有两个组件,但这里我只学了一个用于输入的游戏对象组件 |输入系统 |1.1.1https://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输入方式,一个借鉴了别人的,介绍了剩下三个,加油诸君,我们共同学习进步。