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

平台游戏L型地形角色跳跃异常问题求助

问题描述

我正在开发一款2D平台游戏,角色处于L型地形(下方和侧边各有一个方块)时无法正常跳跃,表现得像是与上方方块发生了碰撞。操控角色向平台移动并尝试跳跃时,动作卡顿,角色几乎立刻落回地面。

无法跳跃场景示意图:
L型地形跳跃卡顿场景

角色移动核心代码如下:

void Update()
{
    //Movimiento
    if (!isCrouching)
    {
        rb.velocity = new Vector2(Input.GetAxisRaw("Horizontal") * spd, rb.velocity.y);
        anim.SetFloat("speed", Mathf.Abs(rb.velocity.x));
        rb.drag = 0;
    } else
    {
        if (Input.GetAxisRaw("Horizontal") != 0)
        {
            rb.drag = crouchFriction;
        }
        else
        {
            rb.drag = 0;
            rb.velocity = new Vector2(0, rb.velocity.y);
        }
    }

    //Flip
    Flip();

    //GroundCheck
    GroundCheck();

    //Saltar
    if (Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.W))
    {
        if (!isCrouching)
        {
            jumpBuffCount = jumpBuffTime;
        }
    } else
    {
        jumpBuffCount -= Time.deltaTime;
    }

    if (jumpBuffCount > 0)
    { 
        if (coyoteTimeCount > 0)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpBuffCount = 0;
        }
    }

    if ((Input.GetKeyUp(KeyCode.UpArrow) || Input.GetKeyUp(KeyCode.W)) && isGrounded)
    {
        coyoteTimeCount = 0;
    }

    if (!isGrounded)
    {
        if (transform.parent == null || transform.parent != null && !transform.parent.CompareTag("FallingPlatform"))
        {
            if (rb.velocity.y > 0.1f)
            {
                anim.SetBool("isJumping", true);
                anim.SetBool("isFalling", false);
            }
            else
            {
                anim.SetBool("isJumping", false);
                anim.SetBool("isFalling", true);
            }
        }
    } else
    {
        anim.SetBool("isJumping", false);
        anim.SetBool("isFalling", false);
    }

    //Agacharse
    Crouch();

    anim.SetBool("isCrouching", isCrouching);
}

private void GroundCheck()
{
    Collider2D hit = Physics2D.OverlapBox(new Vector2(transform.position.x, transform.position.y - 0.5f), new Vector2(0.96f, 0.06f), 0, colision);
    isGrounded = hit;

    if (isGrounded)
    {
        coyoteTimeCount = coyoteTime;
    }
    else
    {
        coyoteTimeCount -= Time.deltaTime;
    }
}

已尝试的操作:

  • 给角色和Tilemap添加无摩擦的Physics Material 2D
  • 调整groundcheck范围使其小于碰撞体,避免检测到墙壁
  • 测试其他场景,问题仅在L型地形出现

解决方案

1. 修复跳跃时的卡墙冲突

当前跳跃逻辑直接设置垂直速度,但角色贴着L型侧边方块时,水平碰撞会导致Rigidbody2D的水平速度被强制清零,甚至产生向上的碰撞反馈抵消跳跃力。修改跳跃逻辑,在跳跃瞬间给侧面碰撞一个微小的推开力:

if (jumpBuffCount > 0 && coyoteTimeCount > 0)
{
    float horizontalInput = Input.GetAxisRaw("Horizontal");
    // 检测角色侧面是否有碰撞
    Collider2D sideHit = Physics2D.OverlapBox(
        new Vector2(transform.position.x + (horizontalInput * 0.5f), transform.position.y),
        new Vector2(0.06f, 0.96f),
        0,
        colision
    );
    if (sideHit != null)
    {
        // 给反向小力,避免卡墙
        rb.AddForce(new Vector2(-horizontalInput * 5f, 0), ForceMode2D.Impulse);
    }
    rb.velocity = new Vector2(rb.velocity.x, jumpForce);
    jumpBuffCount = 0;
}

2. 优化GroundCheck的检测精度

当前GroundCheck的OverlapBox宽度接近角色碰撞体,在L型地形可能同时检测到地面和侧边墙壁,导致isGrounded误判。修改为只检测角色正下方区域:

private void GroundCheck()
{
    // 缩小检测宽度,只覆盖角色中心下方
    Collider2D hit = Physics2D.OverlapBox(
        new Vector2(transform.position.x, transform.position.y - 0.5f),
        new Vector2(0.6f, 0.06f),
        0,
        colision
    );
    // 额外判断:确保碰撞体在角色下方
    isGrounded = hit != null && hit.bounds.max.y < transform.position.y;

    if (isGrounded)
    {
        coyoteTimeCount = coyoteTime;
    }
    else
    {
        coyoteTimeCount -= Time.deltaTime;
    }
}

3. 调整角色碰撞体参数

如果角色使用BoxCollider2D,尝试:

  • 将碰撞体宽度缩小10%,减少和侧边方块的重叠概率
  • 把碰撞体y轴锚点稍微向上偏移,避免底部碰撞体过度贴合地形边缘

4. 优化Rigidbody2D碰撞设置

在Rigidbody2D组件中:

  • 将Collision Detection设置为Continuous,减少高速移动时的碰撞穿透
  • 勾选Use Full Kinematic Contacts,提升碰撞检测的准确性

5. 调试碰撞状态

添加调试代码,查看跳跃瞬间的碰撞详情:

void Update()
{
    // ... 原有代码 ...

    // 按F1查看碰撞信息
    if (Input.GetKeyDown(KeyCode.F1))
    {
        Debug.Log("Is Grounded: " + isGrounded);
        Collider2D[] hits = Physics2D.OverlapBoxAll(transform.position, GetComponent<BoxCollider2D>().size, 0, colision);
        foreach (var hit in hits)
        {
            Debug.Log("碰撞对象: " + hit.gameObject.name + " | 位置: " + hit.transform.position);
        }
    }
}

通过调试信息确认是否真的和上方方块发生碰撞,或者有其他碰撞体干扰。


内容的提问来源于stack exchange,提问作者Marcos T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 09:22:16