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

Godot4中IsOnFloor()始终返回false 角色无法跳跃求助

Godot4中CharacterBody2D的IsOnFloor()返回false无法跳跃的解决方案

一、代码逻辑问题(核心原因)

你的代码存在几处关键错误,导致IsOnFloor()无法正确工作:

  1. 错误使用_Process处理物理逻辑
    CharacterBody2D的物理相关逻辑(重力、移动、地面检测)必须放在_PhysicsProcess(double delta)中,而非_Process。因为Godot的物理引擎按固定帧率更新,_Process是渲染帧驱动,两者不同步会导致碰撞检测状态异常。

  2. 速度计算逻辑错误

    • 每次循环都将velocity重置为Vector2.Zero,导致重力无法持续累加,角色垂直方向的运动状态完全被重置。
    • 最后执行velocity = velocity.Normalized() * speed会覆盖之前所有的速度计算(包括重力和跳跃力),让垂直速度失效,IsOnFloor()自然无法检测到地面接触。
  3. 错误使用MoveAndCollide
    CharacterBody2D的IsOnFloor()状态是由MoveAndSlide()或MoveAndSlideWithSnap()更新的,MoveAndCollide()不会更新这些内置状态,必须改用MoveAndSlide()来处理移动。

二、碰撞配置检查

如果修正代码后问题仍存在,检查以下碰撞设置:

  • 角色的CollisionShape2D:确保角色节点下添加了CollisionShape2D,Shape(如CapsuleShape2D)的大小和位置贴合精灵,没有偏移或过小。
  • 碰撞图层与掩码:在CharacterBody2D的Inspector面板中,检查Collision -> Layer和Mask,确保角色的Mask包含瓦片地图所在的碰撞图层,瓦片地图的Layer也在角色的Mask范围内。
  • 瓦片地图的碰撞设置:打开TileSet编辑器,确认使用的瓦片已添加正确的碰撞形状(Tile Collision Shape),且碰撞图层未被关闭。

三、修正后的代码

using Godot;
using System;

public partial class Player1 : CharacterBody2D
{
    private float gravity = 2000f; // 增大重力值,符合物理逻辑
    private int maxSpeed = 500;
    private float maxFallSpeed = 1200f;
    public int speed = 200;
    public int jumpForce = 600;
    public Vector2 screenSize;
    private bool jumpCheck = false;
    private float jumpTimer= 0f;
    private float maxJumpTime = 0.5f;
    
    public override void _Ready()
    {
        screenSize = GetViewportRect().Size;
    }
    
    // 改用_PhysicsProcess处理物理逻辑
    public override void _PhysicsProcess(double delta)
    {
        // 基于当前velocity更新,而非重置为Zero
        Vector2 velocity = Velocity;

        // 应用重力
        if (!IsOnFloor())
        {
            velocity.Y += gravity * (float)delta;
            // 限制最大下落速度
            velocity.Y = Mathf.Min(velocity.Y, maxFallSpeed);
        }
        else
        {
            // 落地时重置跳跃状态
            jumpCheck = false;
            jumpTimer = 0f;
        }

        // 输出地面检测状态
        GD.Print(IsOnFloor() ? "isonfloor = true" : "isonfloor = false");

        // 水平移动
        if (Input.IsActionPressed("left"))
        {
            GD.Print("left");
            velocity.X = -speed;
        }
        else if (Input.IsActionPressed("right"))
        {
            GD.Print("right");
            velocity.X = speed;
        }
        else
        {
            // 无输入时水平减速
            velocity.X = Mathf.MoveToward(velocity.X, 0, speed * 3 * (float)delta);
        }

        // 向下移动
        if (Input.IsActionPressed("down"))
        {
            GD.Print("down");
            velocity.Y += speed * 2;
        }

        // 跳跃逻辑
        if (Input.IsActionPressed("jump"))
        {
            GD.Print("jump");
            if (IsOnFloor() && !jumpCheck)
            {
                GD.Print("hello");
                jumpCheck = true;
                jumpTimer = 0f;
                velocity.Y = -jumpForce;
            }
            else if (jumpCheck && jumpTimer < maxJumpTime)
            {
                GD.Print("jump2");
                jumpTimer += (float)delta;
                velocity.Y = -jumpForce;
            }
        }
        // 松开跳跃键时立即结束跳跃
        else if (jumpCheck)
        {
            GD.Print("jump3");
            jumpCheck = false;
        }

        // 限制水平最大速度
        velocity.X = Mathf.Clamp(velocity.X, -maxSpeed, maxSpeed);

        // 更新Velocity并使用MoveAndSlide处理移动
        Velocity = velocity;
        MoveAndSlide();
    }
}

关键修改说明

  • 将物理逻辑移至_PhysicsProcess,确保和物理引擎同步。
  • 不再重置velocity为Zero,而是基于Velocity(CharacterBody2D的内置速度属性)更新,保留之前的运动状态。
  • 改用MoveAndSlide()处理移动,自动更新IsOnFloor()等状态。
  • 调整重力、跳跃力数值,使其更符合2D平台游戏的物理感受。
  • 添加了水平减速和最大速度限制,优化移动手感。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:40:21