Unity 2D平台游戏跳跃与冲刺动作冲突问题求助
2D平台游戏跳跃与冲刺同时触发的冲突问题
问题现象
单独执行跳跃(Z键)或冲刺(C键)均正常,但同时触发时角色会被斜向抛向空中:
- 跳跃机制:按下Z键给RigidBody2D施加
Vector2(0, 175)的力 - 冲刺机制:按下C键通过协程给RigidBody2D设置
Vector3(±3, 0)的速度
已尝试的无效方案:
- 执行动作前设置
playerRb.velocity = Vector2.zero - 用
return语句控制流程
原因分析
- 输入执行时机冲突:
Update中同时检测Z和C的GetKeyDown,两键同时按下时,跳跃的AddForce和冲刺的velocity赋值会在同一帧执行。AddForce会给Y轴添加力,而冲刺的velocity只覆盖X轴,Y轴保留了跳跃的力,最终形成斜向运动。 - 状态拦截不及时:
Dash协程中isDashing = true是在协程启动后才生效,但同一帧的跳跃检测已经完成,协程的代码不会在调用StartCoroutine的当前帧立即执行。
解决办法
核心思路
优先锁定动作互斥,统一运动控制逻辑,避免力与速度混合导致的状态残留。
具体方案
- 增加动作互斥判断:在跳跃输入检测中加入
canDash判断,确保冲刺启动时无法触发跳跃(canDash在冲刺协程启动时会立即设为false)。 - 统一速度控制:将跳跃从
AddForce改为直接设置Y轴速度,避免力与速度混合的冲突;冲刺时先清空当前速度,再设置冲刺速度。
修改后的代码示例
using System.Collections; using System.Collections.Generic; using UnityEngine; public class playerScript : MonoBehaviour { private Animator playerAnimator; private Rigidbody2D playerRb; private float h, v; public Transform groundCheck; public bool attackingState; public float speed; public float jumpVelocity; // 改为velocity更符合统一控制逻辑 public bool leftDirection; public int idAnimation; public bool Grounded; // dash system variables public bool canDash = true; private bool isDashing; private float dashPower = 3f; private float dashingTime = 0.2f; private float dashCoolDown = 0.8f; void Start() { canDash = true; playerRb = GetComponent<Rigidbody2D>(); playerAnimator = GetComponent<Animator>(); } void Update() { h = Input.GetAxisRaw("Horizontal"); v = Input.GetAxisRaw("Vertical"); if (isDashing) { return; } if (h > 0 && leftDirection == true && attackingState == false && canDash == true) { flip(); } else if(h < 0 && leftDirection == false && attackingState == false && canDash == true) { flip(); } if(v < 0) { idAnimation = 2; if(Grounded == true || canDash == false) { h = 0; } }else if(h != 0) { idAnimation = 1; }else { idAnimation = 0; } if (Input.GetKeyDown(KeyCode.X) && v >= 0 && attackingState == false) { playerAnimator.SetTrigger("atack"); } // 增加canDash判断,防止冲刺时触发跳跃 if (Input.GetKeyDown(KeyCode.Z) && v >= 0 && Grounded == true && canDash) { // 改用设置Y轴速度替代AddForce,统一运动逻辑 playerRb.velocity = new Vector2(playerRb.velocity.x, jumpVelocity); } if (Input.GetKeyDown(KeyCode.C) && canDash == true) { StartCoroutine(Dash()); } if(attackingState == true && Grounded == true) { h = 0; } playerAnimator.SetBool("Grounded", Grounded); playerAnimator.SetInteger("idAnimation", idAnimation); playerAnimator.SetFloat("speedY", playerRb.velocity.y); } void FixedUpdate() { if (isDashing) { return; } Grounded = Physics2D.OverlapCircle(groundCheck.position, 0.02f); playerRb.velocity = new Vector2 (h * speed, playerRb.velocity.y); } void flip() { leftDirection = !leftDirection; float x = transform.localScale.x; x *= -1; transform.localScale = new Vector3(x, transform.localScale.y, transform.localScale.z); } public void atk(int atk) { switch(atk) { case 0: attackingState = false; break; case 1: attackingState = true; break; } } IEnumerator Dash() { canDash = false; isDashing = true; float originalGravity = playerRb.gravityScale; playerRb.gravityScale = 0f; // 清空当前速度,避免残留跳跃的Y轴速度 playerRb.velocity = Vector2.zero; playerAnimator.SetTrigger("dash"); playerRb.velocity = new Vector2(transform.localScale.x * dashPower, 0f); yield return new WaitForSeconds(dashingTime); playerRb.gravityScale = originalGravity; isDashing = false; yield return new WaitForSeconds(dashCoolDown); canDash = true; } }
关键修改点
- 跳跃输入检测增加
canDash判断,实现动作互斥 - 将跳跃的
AddForce改为设置Y轴速度,统一用velocity控制角色运动 - 冲刺协程中先清空当前速度,消除之前运动状态的残留影响
内容的提问来源于stack exchange,提问作者cartesian_plan
相关产品推荐
相关产品推荐

