Jolt Physics causing insane CharacterBody3D and RigidBody3d launch upon collision

Godot Version

4.6.1

Question

After finishing my FPS movement, I decided to add a basic RigidBody3D, however with Jolt Physics, this happens when CharacterBody3D collides with RigidBody3D, I'm not sure how to prevent this behaviour, also Godot Physics has the same problem but less frequent. How do I fix this?

At least for me, I don’t understand the issue by just looking the video.

What’s the issue?
What do you expect to happen?
What did happen?
What exactly trigger the issue? (steps to replicate the issue)

Any additional info would help people to help you.


Here’s a longer video

The issue is the CharacterBody3D if moving too fast off the RigidBody3D gets launched off by the RigidBody3D and the RigidBody3D gets launched off by the CharacterBody3D

I expect the physics to collide normally, can’t push because there’s no programmed logic for that but can collide

What happened is that the CharacterBody3D if moving too fast off the RigidBody3D gets launched off by the RigidBody3D and the RigidBody3D gets launched off by the CharacterBody3D

What triggers the issue:
Set the physics engine into Jolt Physics (yes, It’s not the default for me somehow.)
Setup a basic Gridmap
Setup a basic RigidBody3D
Setup CharacterBody3D with this script

extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
const acceleration = 0.3
const sens = 0.003

@onready var camera = $Camera3D

func \_ready() → void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func \_unhandled_input(event: InputEvent) → void:
if event is InputEventMouseMotion:
rotate_y(-event.relative.x \* sens)
camera.rotate_x(-event.relative.y \* sens)
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-90), deg_to_rad(90))

func \_physics_process(delta: float) → void:


if not is_on_floor():
	velocity += get_gravity() * delta

if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	velocity.y = JUMP_VELOCITY

var input_dir := Input.get_vector("move_left", "move_right", "move_up", "move_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if is_on_floor():
	if direction:
		velocity = velocity.move_toward( Vector3(direction.x * SPEED, velocity.y, direction.z * SPEED), acceleration ) 
	else:
		velocity = velocity.move_toward( Vector3(0, velocity.y, 0), acceleration )
# $Camera3D/Label.text = str(ground_ray.get_collider(0))

move_and_slide()

Move the CharacterBody3D on top of the RigidBody3D

1 Like

I did a quick test using your code and it did moving too fast when jump on top of the rigidbody. I’m not sure myself but it might be logic in the code which repeatedly increase the velocity value through acceleration.

I’ll try more later.

Your CharacterBody3D believes the rigid body is a moving platform, as the rigidbody moves and rotates it will move and displace your character, using collision layers you can set the rigid body to a layer different from the character body’s moving platform layers.

2 Likes

I don’t think this explains all of the issue in of itself. I think the RigidBody is being pushed by the CharacterBody, causing the moving platform code to go into a feedback loop. This might not be easily fixed with changing collision layers.

If this can’t be fixed with changing collision layers to the CharacterBody, then adding a StaticBody to the player’s feet to interact with the Rigidbodies may be needed. Since StaticBodies don’t get affected by physics at all, this should fix the issue. Though, I admit it sounds janky.

I set my CharacterBody3D into the 2nd collision layer, kept the RigidBody3D in the first layer, this solved the problem

1 Like

That was not the solution, but i found a mitigation

Moving Platform > Upward Velocity = Do Nothing MITIGATES the problem, not ELIMINATES (Mitigation: The player doesn’t get launched anymore)
(Criteria for elimination: The RigidBody3D shouldn’t get launched anymore)

Floor > Snap Length = 0.0 MITIGATES this even further, still doesn’t eliminate because an edge case : hitting the edge of the rigidbody in a certain way will make it launch

Setting the collision layers of the Character body will do nothing, did you set the “moving platform layers”?

I’ve been having the same problem in the game I’m trying to make and removing the rigidbody3D layer from the “Flor Layers” in the “Moving Platform” section of the CharacterBody3D settings does solve the issue of the character being launched, but it doesn’t solve the problem of the rigidbody3D being launched.
Meaning, when the character steps off from the top of the box, the box still gets launched, but not the character - which is an improvement but not a complete solution.

I noticed that setting the character’s “Safe Margin” to a ‘big’ number like 0.1m does fix the box being launched (and so you don’t even need to remove the layer from the moving platforms layers because if the box isn’t launched, the feedback loop doesn’t happen and so the character is also not launched).
However, my game is in 3rd person, and setting the safe margin so high makes the character’s feet look like they are hovering 10 cm above the ground (because they are doing exactly that, I guess). Then I tried reducing the character’s capsule height by double the value of the safe margin, so the capsule starts 10cm above the origin of the character. It seemed to work perfectly at first, I could get on the boxes and walk off them and nothing weird happened, and the feet looked like they were touching the floor/platforms. However, I later noticed that if I just jumped without moving horizontally, the player landed on the ground with the feet digging into the ground. So for some reason, if the character is not moving horizontally when it lands on the ground, the safe margin is ignored and so the feet dig 10cm into the ground, so not a good solution after all…

Try acceleration * delta

the acceleration value might be too high for the time scale.

Yeah it did, even if the CharacterBody3D’s capsule shape still moves the cube when going of it at least it’s in an expected way, thanks mate!

They are right that you want to use delta with acceleration on move_toward, they are wrong about your acceleration being too high.

Currently your SPEED represents 5 meters per second and your acceleration represents 0.3 meters per frame, so low-framerate players will accelerate slower than high-framerate players. An acceleration of ~5 times the speed will reach max speed in ~1/5th of a second, if you are testing at 60FPS multiplying 0.3 by 60 gets you about the same number, try acceleration * delta with an acceleration of 20 meters per second.

1 Like

The newtonian formulas for velocity

v = u + a t

and of course, small change in velocity for a small change in time, constant acceleration…

dv = du + a dt

thats the formula for Euler integration.

v = acceleration * delta

is the incremental change in velocity, what precisely does “velocity” in this context happen to be ?

If you have two acelerations per frame,

v = a1 *delta

and then

v += a2 *delta