Characterbody3d falling through floor under specific circumstances related to falling.

Godot Version

v4.4.1.stable.official [49a5bc7b6]

Question

I recently was having a couple of friends test a control scheme for a game I’m working on and one of them said the jumps felt floatty, so I upped the gravity and started to notice a couple of problems with falling through the floor under the conditions listed below…

  1. Only when the character is moving backwards, towards the camera and is landing from a backwards jump. I have yet to replicate this with a fall, but it may still be possible.
  2. At gravity 9.8, we have no negative effects.
  3. At gravity ~19.6, the character will sink part way into the ground on landing and stick for a moment before raising back up to ground level and continuing to move. If they land into a hillside, they may or may not phase through the terrain.
  4. At gravity ~29.4, the character will phase through the floor without fail.
  5. This happens regardless of whether I increase gravity directly or use a script to increase gravity only on the decent.

For the record I am using the Terrain3D plugin and a characterbody3D for the actual character. I have had it previously mentioned that this may somehow be related to the camera. If that is the case, the camera3D is attached to a Node3D centered on the character. The Node3d is at position 0, 0, 0 and rotation -15, 0, 0. The camera itself is at position 0, 75, 0 and rotation -90, -180, 0. The Node3D also includes a script for a lag in motion, smoothing, and a “look ahead” that pans in the direction the character is traveling. Script included here.

extends Node3D

@export var follow_target: Node3D
@export var follow_speed: float = 5.0
@export var look_ahead_distance: float = 60.0
@export var camera_height: float = 6.0
@export var camera_distance: float = 10.0
@export var camera_angle_deg: float = 45.0
var effective_speed := 1.0
var current_look_ahead := Vector3.ZERO
var look_ahead_velocity := Vector3.ZERO
var position_offset: Vector3 = Vector3(0, 10, 0)
var rotation_lag_speed := 3.0
var position_lag_speed := 10.0

func _physics_process(delta: float) → void:
if not follow_target:
return

# update speed for smoothing ---
if follow_target and "move_speed" in follow_target:
	var move_speed = follow_target.move_speed
	effective_speed = move_speed + ((move_speed + 1.0) / 2.0)

# get target velocity 
var velocity := Vector3.ZERO
if follow_target.has_method("get_velocity"):
	velocity = follow_target.call("get_velocity")
else:
	velocity = follow_target.global_transform.basis.z * -1.0

var speed := velocity.length()
var direction := Vector3.ZERO
if speed > 0.01:
	direction = velocity.normalized()

# smooth look-ahead
var desired_look_ahead = direction * look_ahead_distance * clamp(speed / effective_speed, 0.0, 1.0)
look_ahead_velocity = look_ahead_velocity.lerp(desired_look_ahead - current_look_ahead, delta * 5.0)
current_look_ahead += look_ahead_velocity * delta

# final target camera position
var target_position = follow_target.global_transform.origin + position_offset + current_look_ahead
global_transform.origin = global_transform.origin.lerp(target_position, delta * position_lag_speed)

# smooth yaw rotation
var forward = -follow_target.global_transform.basis.z
var target_yaw = atan2(forward.x, forward.z)
var current_yaw = rotation.y
var smoothed_yaw = lerp_angle(current_yaw, target_yaw, delta * rotation_lag_speed)
rotation.y = smoothed_yaw

This is due to a peculiarity of physics processing by the engine. Increase the thickness of the ground and the character will stop falling through. But, most likely, he will continue to sink. You can try to change the physics engine, but noticeable changes are unlikely.

It’s best to go back to this option.

Then I will take your advise. Just to be clear, is this an issue with Jolt? Bullet? Godot? All of the above? I’m very new at all this and just want to make sure I understand what’s going on.

This option is the closest. Very briefly — the game physics engine is deterministic and does not always have time to process collisions if objects move quickly. Example — a bullet flies through glass. In one frame it is in front of the glass, in the next — behind it. The glass remains intact, which is impossible in reality. That’s why in such a case you need to use a beam, not a physical body.

Therefore, the realization of real physics in the game engine is not a very good idea. Falsification is more useful — our way is deception.

1 Like