How to fix the is_on_floor()?

Godot Version

4.4.1

Question

Could any body solve that why isn’t the is_on_floor() not working, but the collider still collide with other stuff?

The collider mask of the Player and the tile map layer are the same.

extends CharacterBody2D

const START_SPEED = 175.0   # 初始飞行速度
const MAX_SPEED = 275.0     # 飞行最高速度
const JUMP_VELOCITY = -300.0

const ACCELERATION = 800.0  # 转向/启动的灵敏度
const FRICTION = 300.0      # 停下的阻力
const BOOST_RATE = 75.0     # 飞行时每秒增加的速度值

var is_flying = false 
var current_fly_speed = START_SPEED 

@onready var animated_sprite: AnimatedSprite2D = $PlayerAnimated

# --- 新增:穿梭功能处理 ---
func _input(event: InputEvent) -> void:
	# 监听 E 键 (需在输入映射配置 interact)
	if event.is_action_pressed("interact"):
		teleport_logic()

func teleport_logic():
	# 遍历所有穿梭石
	for point in get_tree().get_nodes_in_group("teleport_points"):
		# 如果玩家正站在这个石头里
		if point.player_in_range:
			var target_pos = point.get_destination_pos()
			
			# 如果目的地就是自己,说明没设置出口,就不传送
			if target_pos == global_position:
				print("这个传送门没有设置出口!")
				return
				
			# 执行瞬间移动
			global_position = target_pos
			
			# 穿梭后的细节:清空速度,保持飞行状态
			velocity = Vector2.ZERO 
			is_flying = true
			
			# 播放一个小音效或特效(如果有的话)
			print("已穿梭至目标石头")
			break

# --- 原有:物理移动逻辑 ---
func _physics_process(delta: float) -> void:
	floor_snap_length = 5.0
	if is_on_floor():
		print("已落地")
	else:
		# print("在空中")
		pass
	# 1. 落地重置
	if is_on_floor():
		is_flying = false
		current_fly_speed = START_SPEED 

	# 2. 触发飞行
	if Input.is_action_just_pressed("move_up"):
		if is_on_floor():
			velocity.y = JUMP_VELOCITY
		elif not is_flying:
			is_flying = true
			current_fly_speed = START_SPEED 

	# 3. 移动分支
	var direction_x := Input.get_axis("move_left", "move_right")
	
	if is_flying:
		# --- 【飞行模式:动态加速】 ---
		var fly_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
		
		if fly_dir != Vector2.ZERO:
			current_fly_speed = move_toward(current_fly_speed, MAX_SPEED, BOOST_RATE * delta)
			velocity = velocity.move_toward(fly_dir * current_fly_speed, ACCELERATION * delta)
		else:
			current_fly_speed = move_toward(current_fly_speed, START_SPEED, BOOST_RATE * delta)
			velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
		
		animated_sprite.play("Jump")
		
		if Input.is_action_just_pressed("ui_accept"): # 按空格取消
			is_flying = false
			
	else:
		# --- 【普通模式】 ---
		if not is_on_floor():
			velocity += get_gravity() * delta

		if direction_x:
			velocity.x = move_toward(velocity.x, direction_x * START_SPEED, ACCELERATION * delta)
		else:
			velocity.x = move_toward(velocity.x, 0, (FRICTION * 2) * delta)

		if is_on_floor():
			if abs(velocity.x) < 0.1:
				animated_sprite.play("Idle")
			else:
				animated_sprite.play("Run")
		else:
			animated_sprite.play("Jump")

	# 4. 角色翻转
	if velocity.x > 0.1:
		animated_sprite.flip_h = false
	elif velocity.x < -0.1:
		animated_sprite.flip_h = true

	move_and_slide()

The physics collision Mask of the Player needs to match the physics collision Layer of the TileMapLayer. Masks detect layers.

1 Like

It don’t work, the collision mask of the player is the same as the Tilemap Layer.

So you painted it onto the tiles you want to collide in the Tileset?

i did paint it on to that.

I believe this is your problem. is_on_floor() is only true if the player is colliding with something on the down vector AND it is moving towards that vector. So the fix is to always have gravity affect the player. That should solve your collision problem.

i’m pretty sure that fix nothing else of let me not jump

You can fix the Jump problem by just giving your jump more velocity to break the downward force.

Alternately, I recommend you simplify your code then to a generic CharacterBody2D and slowly add in each piece of your code. Check that each change works, and when it stops working as intended, you’ll know where to look for the problem.

thank you that works.:grinning_face_with_smiling_eyes:

1 Like