KinematicBody has inconsistent collisions
New user here. Before I report this as a bug, I wanted to double-check if I'm not doing anything wrong.
I am using a KinematicBody as a "Character controller", and need to check the collision with the floor to determine the floor "type" (water, wood, etc.) and adjust the character's animation/sounds accordingly.
I want to avoid additional ray casts, since I'm already colliding with the floor using the kinematic body anyway - all the information I need should already be in the collision info! Also, whichever method I decide on will be used on dozens of kinematic bodies at the same time, so it needs to be as fast as possible. Reusing existing collision data seems like a good plan.
The problem is that I can't get consistent collisions. Sometimes it gets reported, sometimes it doesn't. I also get very different results between using move_and_slide() and move_and_slide_with_snap() - which is odd to me, since the only difference I expected between those two methods would be in the movement.
I made a very minimal sample project that demonstrates the issue.
The ball should always match the floor color, unless it's in the air, when it should be blue.
I've attached the project (it's tiny).
Here is also the test code in the kinematic body, in case you don't want to download the project:
extends KinematicBody export var speed = 10.0 export var jumpSpeed = 20.0 export var gravity = Vector3(0.0, -2.0, 0.0) export var groundSnap = Vector3.DOWN * 0.1 var vel = Vector3() onready var material = get_node("MeshInstance").get_surface_material(0) func _process(delta): var dir = Vector3.ZERO if Input.is_action_pressed( "left" ): dir.x = -speed elif Input.is_action_pressed( "right" ): dir.x = speed if Input.is_action_pressed( "up" ): dir.z = -speed elif Input.is_action_pressed( "down" ): dir.z = speed if is_on_floor(): vel= Vector3( dir.x, 0, dir.z ) if Input.is_action_just_pressed( "jump" ): vel.y = jumpSpeed else: vel.y += gravity.y vel.x = dir.x vel.z = dir.z if is_on_ceiling(): vel.y = 0 func _physics_process(delta): #This doesn't work - object color stays blur most of the time, #implying no collisions happened var col = move_and_slide_with_snap( vel, groundSnap, Vector3.UP ) #This reports collisions better (ball is never blue when touching surfaces), #but doesn't jump (is_on_floor() doesn't work) # var col = move_and_slide( vel ) if col: var count = get_slide_count() if count > 0: for n in range(count): var hit = get_slide_collision(n) var otherMesh = hit.collider.get_node("MeshInstance") var otherMaterial = otherMesh.get_surface_material(0) material.albedo_color = otherMaterial.albedo_color else: material.albedo_color = Color.blue