3D collision manipulates velocity

Godot Version



I use a CharacterBody3D with following controlls code:

if Input.is_action_just_pressed("move_ahead") and not(moving_ahead):
			velocity += global_transform.basis * foreward * speed
			moving_ahead = true

and calling “move_and_slide()” within “_physics_process” method. The movement works as expected but when the CharacterBody3D collides with other 3D objects (namely StaticBody3D), velocity is set to some value in negative collision normal direction - or something like that - resulting in permanent movement in that direction.

You can clone and try it on your own from here:

Thank you for reading :slight_smile:

I would really appreciate an explanation of this behaviour and what are the mistakes i made.


I further tested this effect. With Area3D nodes and attached CollisionShape3D there is no collision, while using RigidBody3D or CharacterBody3D with attached CollisionShape3D causes the exact same behaviour: “Undenieable repellance” as described above.

Help is still really appreciated.

As far as I can tell this is normal, move_and_slide calculates a new velocity for the body after the collision, because the velocity you set would result in the two bodies going inside each other.

Normally this is not an issue because usually the controls are checked every frame, so after collision, if the player is pressing forward for example then the velocity will be set to the forward velocity and the body will not just keep the “bounce” velocity.

I guess the solution could be to set the velocity every frame in _physics_process, something like:

if moving_ahead:
	velocity = global_transform.basis * foreward * speed
1 Like

Thank you for your reply @Monday. I understand that my control mechanics are very basic, maybe too basic indeed. The flaw with your solution is that releasing the “move_foreward” button while being in contact with a wall would cause the same behaviour but you might be right with

… usually the controls are checked every frame

and therefore my controlls are simply, too simple. I conclude that even for a basic movement it seems necessary that there is more advanced code maintaining the velocity vector.