godotengine / godotengine/godot

CharacterBody3D with skeleton and root motion animations gets stuck against other physics objects

Open
#90,402 2 comments 1 reaction 0 assignees View on GitHub
discussion needs testing topic:3d topic:physics
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

- Reproducible in v4.3.dev.custom_build [0c6b5efab]

### System information

Godot v4.3.dev (0c6b5efab) - Windows 10.0.22631 - Vulkan (Forward+)

### Issue description

When running against another physics object with CharacterBody3D with a skeleton and root motion animations the body gets stuck against other physics objects. Using a capsule as the main physics collider.

Looking into this a bit more it seems there are three places in move_and_slide() that can cause the horizontal velocities set to zero.
```

@@ -178,11 +178,11 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
if (motion_vertical_velocity.dot(up_direction) > 0 || ceiling_vertical_velocity.length_squared() > motion_vertical_velocity.length_squared()) {
velocity = ceiling_vertical_velocity + velocity.slide(up_direction);
}
}
}
-
+ // HERE (the velocity vector is cleared a bit lower, but the < 0.01 seems a bit arbitrary)
if (collision_state.floor && floor_stop_on_slope && (velocity.normalized() + up_direction).length() < 0.01) {
Transform3D gt = get_global_transform();
if (result.travel.length() <= margin + CMP_EPSILON) {
gt.origin -= result.travel;
}
@@ -250,10 +250,11 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
if (vel_dir_facing_up) {
Vector3 slide_motion = velocity.slide(result.collisions[0].normal);
// Keeps the vertical motion from velocity and add the horizontal motion of the projection.
velocity = up_direction * up_direction.dot(velocity) + slide_motion.slide(up_direction);
} else {
+ // HERE (this cancels out the movement sometimes, perhaps a rotation issue)
velocity = velocity.slide(forward);
}

// Allow only lateral motion along previous floor when already on floor.
// Fixes slowing down when moving in diagonal against an inclined wall.
@@ -291,10 +292,11 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
if (p_was_on_floor && (wall_min_slide_angle > 0.0) && result_state.wall) {
Vector3 horizontal_normal = wall_normal.slide(up_direction).normalized();
real_t motion_angle = Math::abs(Math::acos(-horizontal_normal.dot(motion_slide_up.normalized())));
if (motion_angle < wall_min_slide_angle) {
motion = up_direction * motion.dot(up_direction);
+ // HERE (this cancels the movement sometimes, perhaps a rotation issue)
velocity = up_direction * velocity.dot(up_direction);

apply_default_sliding = false;
}
}

```

Removing these velocity assignments on those lines will fix the getting stuck. But the character will slip and slide.

### Steps to reproduce

Run the test project and walk against the cylinder wall for some time.

### Minimal reproduction project (MRP)

[stuck.zip](https://github.com/godotengine/godot/files/14910288/stuck.zip)

https://github.com/godotengine/godot/assets/91064515/b66fef75-3144-4d61-822f-4b89d1a1cc9c

Contributor guide

Open the contributing guide

Research direction

Start with CharacterBody3D::_move_and_slide_grounded() and the three velocity assignments highlighted in the issue. Run the stuck.zip reproduction and walk the character against the cylinder wall. Done means root-motion CharacterBody3D instances no longer get stuck against physics objects while retaining appropriate slope and sliding behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.