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

Unity中Rigidbody2D角色Y轴跳跃异常问题求助

Unity 2D角色跳跃异常问题排查记录

我把Rigidbody2D设置为dynamic模式,插值方式设为extrapolate,尝试了多版代码都没实现正常跳跃:

初始代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

public class player : MonoBehaviour
{
    Vector2 Moveing;
    public float Speed = 2f;
    private Rigidbody2D rb;

    void Start()
    {
        CurrentHealth = Maxhealth;
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            transform.eulerAngles = new Vector2(0, 180);
        }
        else if (Input.GetKeyUp(KeyCode.LeftArrow))
        {
            transform.eulerAngles = new Vector2(0, 0);
        }
        // 省略其他移动、动画逻辑代码
        else if (!Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) & IsHurt == true && attacking == false)
        {
            am.Play("hurt" + lv);
        }
        else if (Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && IsHurt == false && attacking == false)
        {
            Moveing = new Vector2(1, 0);
            am.Play("walk" + lv);
        }
        else if (Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && IsHurt == true)
        {
            Moveing = new Vector2(1, 0);
            am.Play("walkhurt" + lv);
        }
        else if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.UpArrow) && IsHurt == false && attacking == false)
        {
            Moveing = new Vector2(2, 0);
            am.Play("run" + lv);
        }
        else if (Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.UpArrow) && IsHurt == true)
        {
            Moveing = new Vector2(2, 0);
            am.Play("runhurt" + lv);
        }
        // 省略其他状态判断代码
        else if (!Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) & IsHurt == false && attacking == true)
        {
            Moveing = new Vector2(0, 0);
            am.Play("attack" + lv);
        }
        else
        {
            Moveing = new Vector2(0, 0);
            am.Play("idle" + lv);
        }
        if (Input.GetKeyDown(KeyCode.Space)) //jump
        {
            Moveing += new Vector2(0, Speed);
        }

        rb.MovePosition(new Vector2(transform.position.x, transform.position.y) + Speed * Time.deltaTime * Moveing.normalized);
    }
}

问题:角色无法正常跳跃,实际跳跃高度仅约0.03。

第二版代码:使用AddForce

修改跳跃逻辑为直接给刚体加力:

if (Input.GetKeyDown(KeyCode.Space)) //jump
{
    rb.AddForce(new Vector2(0,Speed));
}

问题:角色瞬间向上移动Speed数值的距离,随后缓慢下落,效果像瞬移,不符合正常跳跃体验。

第三版代码:拆分MovePosition

单独调用MovePosition处理跳跃:

if (Input.GetKeyDown(KeyCode.Space)) //jump
{
    rb.MovePosition(new Vector2(transform.position.x, transform.position.y) + Speed * Time.deltaTime * new Vector2(0,1).normalized);
} 

结果:和第一版代码一致,跳跃高度依旧极低。

第四版代码:不依赖Rigidbody的手动跳跃逻辑

新增地面检测和帧计数来模拟跳跃:

public class player : MonoBehaviour
{
    Vector2 Moveing;
    public float Speed = 2f;
    private Rigidbody2D rb;
    private bool IsGround;
    private int CurrentJumpFrame=0;

    void Start()
    {
        CurrentHealth = Maxhealth;
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            transform.eulerAngles = new Vector2(0, 180);
        }
        else if (Input.GetKeyUp(KeyCode.LeftArrow))
        {
            transform.eulerAngles = new Vector2(0, 0);
        }
        // 省略其他移动、动画逻辑代码
        else if (!Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) & IsHurt == true && attacking == false)
        {
            am.Play("hurt" + lv);
        }
        else if (Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && IsHurt == false && attacking == false)
        {
            Moveing = new Vector2(1, 0);
            am.Play("walk" + lv);
        }
        // 省略其他状态判断代码
        else
        {
            Moveing = new Vector2(0, 0);
            am.Play("idle" + lv);
        }
        if (Input.GetKeyDown(KeyCode.Space)&&IsGround==true) //jump
        {
            Moveing += new Vector2(0, Speed);
            CurrentJumpFrame = 1;
            transform.position = new Vector2(transform.position.x, transform.position.y + Speed / 18 / 60);
        }
        if (CurrentJumpFrame>0&&CurrentJumpFrame<=60&&IsGround==false)
        {
            transform.position = new Vector2(transform.position.x, transform.position.y + Speed / 18 / 60);
            CurrentJumpFrame++;
        }
        else if (IsGround == true)
        {
            CurrentJumpFrame = 0;
        }

        rb.MovePosition(new Vector2(transform.position.x, transform.position.y) + Speed * Time.deltaTime * Moveing.normalized);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.CompareTag("Grid"))
        {
            IsGround= true;
        }
    }
    void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Grid"))
        {
            IsGround= false;
        }
    }
}

结果:还是和第一版一样,跳跃高度几乎可以忽略。

额外尝试:移除Moveing.normalized

把第一版和第二版代码中的Moveing.normalized改为Moveing,跳跃问题依旧没解决,还新增了新问题:角色移动3~4个Tile后会卡在Tilemap碰撞体上,即使合并了Tilemap碰撞体也无法解决。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:38:12