Godot Version
v4.3.stable.mono.official [77dcf97d8]
Question
I wrote the physics of interaction of CharacterBody3D with RigidBody3D, and when CharacterBody walks on objects (or, more precisely, descends from them) - the objects fly into the air. When a Character interacts with an Object, right before move_and_slide() the _push_away_rigid_bodies() function is called (Which I have included below)
func _push_away_rigid_bodies():
for i in get_slide_collision_count():
var c := get_slide_collision(i)
if c.get_collider() is RigidBody3D:
var push_dir = -c.get_normal()
# How much velocity the object needs to increase to match player velocity in the push direction
var velocity_diff_in_push_dir = self.velocity.dot(push_dir) - c.get_collider().linear_velocity.dot(push_dir)
# Only count velocity towards push dir, away from character
velocity_diff_in_push_dir = max(0, velocity_diff_in_push_dir)
# Objects with more mass than us should be harder to push. But doesn't really make sense to push faster than we are going
const MY_APPROX_MASS_KG = 80.0
var ratio = MY_APPROX_MASS_KG / c.get_collider().mass
var mass_ratio = min(1., MY_APPROX_MASS_KG / c.get_collider().mass)
# Optional add: Don't push object at all if it's 4x heavier or more
if mass_ratio < 0.25:
continue
# Don't push object from above/below
push_dir.y = 0
# 5.0 is a magic number, adjust to your needs
var push_force = mass_ratio * 0.7
c.get_collider().apply_impulse(push_dir * velocity_diff_in_push_dir * push_force, c.get_position() - c.get_collider().global_position)