You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2D平台游戏跳跃与冲刺动作冲突问题求助

2D平台游戏跳跃与冲刺同时触发的冲突问题

问题现象

单独执行跳跃(Z键)或冲刺(C键)均正常,但同时触发时角色会被斜向抛向空中:

  • 跳跃机制:按下Z键给RigidBody2D施加Vector2(0, 175)的力
  • 冲刺机制:按下C键通过协程给RigidBody2D设置Vector3(±3, 0)的速度

已尝试的无效方案:

  • 执行动作前设置playerRb.velocity = Vector2.zero
  • 用return语句控制流程

原因分析

  1. 输入执行时机冲突:Update中同时检测Z和C的GetKeyDown,两键同时按下时,跳跃的AddForce和冲刺的velocity赋值会在同一帧执行。AddForce会给Y轴添加力,而冲刺的velocity只覆盖X轴,Y轴保留了跳跃的力,最终形成斜向运动。
  2. 状态拦截不及时:Dash协程中isDashing = true是在协程启动后才生效,但同一帧的跳跃检测已经完成,协程的代码不会在调用StartCoroutine的当前帧立即执行。

解决办法

核心思路

优先锁定动作互斥,统一运动控制逻辑,避免力与速度混合导致的状态残留。

具体方案

  1. 增加动作互斥判断:在跳跃输入检测中加入canDash判断,确保冲刺启动时无法触发跳跃(canDash在冲刺协程启动时会立即设为false)。
  2. 统一速度控制:将跳跃从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:43:09