One-Way collision blocking 3-ways.
Using CharacterBody2D, and tilemap one-way collision, collisions are being blocked from the sides adjacent to the one-way.
Steps to reproduce the behavior:
- Create a one-way collision on a tilemap, and a characterbody2d with a collision box.
- Attempt to pass through the one-way collision from every side.
Expected behavior In Godot default, one-way collision only blocks the one direction. In Rapier2D, one way seems block 3 directions. The intended, plus the two adjacent directions.
Environment:
- OS: Win11
- Version: 0.8.10
- Godot Version: 1.3
- Type: SIMD 2D
Example project: Arrow keys for movement, spacebar for jump. phystest.zip
I'm still having this trouble on 0.8.10, the one-way is blocking on the left and right of the tiles as well as the top. This does not happen with GodotPhysics.
Here is using GodotPhysics and one-way:
https://github.com/user-attachments/assets/f147ea6c-4318-46d3-a567-b3cd7bc4caac
Here is Rapier2D:
https://github.com/user-attachments/assets/9af68c1c-b39f-49fa-b830-6c9d70a98c04
And Rapier2D with a single collider built using TilemapCollisionGenerator:
https://github.com/user-attachments/assets/162f4ee2-551f-4f39-8398-19a1f46e071a
Ok, thanks for the sample provided. Sorry for taking long time to look into this. I am able to reproduce this issue easiest when i fall and press left and it doesn't go through.
The One-Way is done in src/rapier_wrapper/physics_hooks.rs, in the function update_as_oneway_platform. I'll take a look if changing the line:
let contact_is_ok = local_normal.dot(allowed_local_normal) < 0.00001;
Will help at all.
No, I was wrong, that is actually for rigidbodies, for characterbodies, its in:
src/spaces/rapier_space_body_helper.rs
In:
should_skip_collision_one_dir
My next guess is its possible the error is from epsilon, since in 2d the units are 100x bigger than 3d. I'll try decrease epsilon for the one_dir check
No, I was wrong, that is actually for rigidbodies, for characterbodies, its in:
src/spaces/rapier_space_body_helper.rsIn:
should_skip_collision_one_dirMy next guess is its possible the error is from epsilon, since in 2d the units are 100x bigger than 3d. I'll try decrease epsilon for the one_dir check
Any luck with this? I'll switch back to GodotPhysics if not as one-ways need to work properly for platformer games, an RPG or a game with no one-ways you could probably just ignore it for now.
EDIT: I can't switch back to GodotPhysics cause they did a terrible job with shapecasting.
No luck yet, but fixed other bugs, will take a look also at this soon though.
Taking another look at this, though this is a difficult issue. The character controller movement is handled inside src/spaces/rapier_space_body_helper.rs in test_body_motion. There are 3 phases to this:
- recover motion. Expand the body colliders by the margin (grow) and check if now it collides with a collider, if yes, "recover" / "push" out of this collider
- Cast motion. Try to to find what is the possible motion (how far it can move, it's a shapecast, when you try to find the safe point (max you can move without collision ))
- Rest Info: Apply the motion and fill the collision information
My first guess is that step 2 might be having issues.
Step 1
Iterates 4 times, for each collision checks should_skip_collision_one_dir, margin and uses inside shapes_contact.
General
- shapes_contact: Finds contacts between 2 shapes. Function from Rapier.
- should_skip_collision_one_dir: Callback that checks if 2 shapes should skip collision or not. Function from Godot-Rapier.
After my fixes in linked PR
https://github.com/user-attachments/assets/9b316671-d69a-408c-b11d-163fce3ca4ed