Godot4中IsOnFloor()始终返回false 角色无法跳跃求助
Godot4中CharacterBody2D的IsOnFloor()返回false无法跳跃的解决方案
一、代码逻辑问题(核心原因)
你的代码存在几处关键错误,导致IsOnFloor()无法正确工作:
错误使用_Process处理物理逻辑
CharacterBody2D的物理相关逻辑(重力、移动、地面检测)必须放在_PhysicsProcess(double delta)中,而非_Process。因为Godot的物理引擎按固定帧率更新,_Process是渲染帧驱动,两者不同步会导致碰撞检测状态异常。速度计算逻辑错误
- 每次循环都将
velocity重置为Vector2.Zero,导致重力无法持续累加,角色垂直方向的运动状态完全被重置。 - 最后执行
velocity = velocity.Normalized() * speed会覆盖之前所有的速度计算(包括重力和跳跃力),让垂直速度失效,IsOnFloor()自然无法检测到地面接触。
- 每次循环都将
错误使用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
相关产品推荐
相关产品推荐

