Repository: godot
Issue: Godot 4: An fallable CharacterBody2D.is_on_floor() returns different values when a tile is placed on top of CharacterBody2D
Labels: bug,topic:physics,needs testing

### Godot version

4.1.2.stable.flathub [399c9dc39]

### System information

Godot v4.1.2.stable (399c9dc39) - Freedesktop SDK 23.08 (Flatpak runtime) - Wayland - Vulkan (Compatibility) - Mesa Intel(R) Xe Graphics (TGL GT2) () - 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz (8 Threads)

### Issue description

In my scenario I use a CharacterBody2D with two is_on_floor() APIs, called before and after move_and_slide() API, to detect whether an item is falling in the air. I rely on this logic to implement an item, which can be broken on falling and hitting ground. Simplified code logic can be described like code below.

``` GDScript
func _physics_process(_delta: float) -> void:
    $Item_Is_On_Floor_Detector1.velocity.y += PhysicsServer2D.AREA_PARAM_GRAVITY

    var is_on_floor_before = is_on_floor()
    move_and_slide()
    var is_on_floor_after = is_on_floor()
    if not is_on_floor_before and is_on_floor_after and _is_speed_change_big_enough():
        _set_gold_broken() 
```

The code used to work fine in Godot 3 (it was KinematicBody2D but logic is similar). When migrating to Godot 4 , I notice the code path to _set_gold_broken() is triggerred unxpectedly by a certain pattern of tile placement like below. The effect is an item placed in the wall is broken from beginning of the game, because the reported result is the item appears to be in the air (on_the_floor() == false) but hit floor after moving.

![image](https://github.com/godotengine/godot/assets/183941/946ea6f6-2b36-4849-a4d2-56e35dbb6d44)

With this layout above, **is_on_floor_before == false and is_on_floor_after == true**

Meanwhile, a layout like below (just removing the tile on top of gold) produces a result making more sense:
![image](https://github.com/godotengine/godot/assets/183941/31afa064-9ea6-4359-98f6-cff5dba49111)

With the layout above, **is_on_floor_before == true and is_on_floor_after == true**.

The same behavior is identified on both Linux and macOS.



### Steps to reproduce

1. Clone test project, https://github.com/fuzhouch/godot-3to4-comparison to local, say, ./godot-3to4-comparison
2. Launch Godot 4.1.2 and load project for Godot 4, godot-3to4-comparison/godot4.
3. Load scene, [demo_tilemap_on_floor_detection_bad.tscn](https://github.com/fuzhouch/godot-3to4-comparison/blob/main/godot4/demo_tilemap_on_floor_detection_bad.tscn)
4. Pay attention to console output. It should print the following lines every 2 seconds.

```
[before] Item_Is_On_Floor_Detector1.is_on_floor()?false
[after] Item_Is_On_Floor_Detector1.is_on_floor()?true
[before] Item_Is_On_Floor_Detector1.is_on_floor_only()?false
[after] Item_Is_On_Floor_Detector1.is_on_floor_only()?true
```

As a comparison, we can load and run scene, [demo_tilemap_on_floor_detection_good.tscn](https://github.com/fuzhouch/godot-3to4-comparison/blob/main/godot4/demo_tilemap_on_floor_detection_good.tscn). The output becomes:

```
[before] Item_Is_On_Floor_Detector1.is_on_floor()?true
[after] Item_Is_On_Floor_Detector1.is_on_floor()?true
[before] Item_Is_On_Floor_Detector1.is_on_floor_only()?true
[after] Item_Is_On_Floor_Detector1.is_on_floor_only()?true
```

The two scenes are sharing the same GDScript file, the only difference is the tilemap.


## Additional information

I created a test project with Godot 3. It can be executed via the same repository but different project folder, godot3. Run scene [Demo_Tilemap_OnFloor_Detection.tscn](https://github.com/fuzhouch/godot-3to4-comparison/blob/main/godot3/Demo_Tilemap_OnFloor_Detection.tscn).

(The output does not have is_on_floor_only(), as the API does not exist in Godot 3.)

The output of Godot 3 is different with Godot 4, and does not look correct either. It just happenedly work in my code because **is_on_floor_before == true**, which unmatch my code logic.

```
[before] Item_Is_On_Floor_Detector1.is_on_floor()?True
[after] Item_Is_On_Floor_Detector1.is_on_floor()?False
```

### Minimal reproduction project

* Repositoy: https://github.com/fuzhouch/godot-3to4-comparison
* Godot 4 project (for reproduce): [godot4](https://github.com/fuzhouch/godot-3to4-comparison/tree/main/godot4) folder.
* Godot 3 project (for comparison): [godot3](https://github.com/fuzhouch/godot-3to4-comparison/tree/main/godot3) folder.