Problem:
If the player is wallrunning, im checking the collision every physics tick, such that if no collision is detected, the wallrun is ended.
Ive tried detecting the collision end via area3ds on_body_exited(), area3ds has_overlapping_bodies() and raycast3ds is_colliding().
Somehow, even if the raycast or area3d is still colliding with the wall all collision check methods immediately return false (right after the first check that starts the wallrun).
Hypothesis:
Ive checked my code multiple times and everything seems, like it should work, to me.
Even a de-synchronisation between the colliding objects tick rate and _physics_process() wouldn’t make sense to me, as the collision check should continue to be true instead of getting set to false.
Meaning this is likely caused by the collision itself not working properly. But i really don’t know.
Additional Info:
Im trying to implement wallrunning similar to Titanfall2. To do that i have multiple movement states to switch between, one of which is the wallrun state. Im using two physics objects (ive tried both raycasts or area3ds) on either side of the player character to continuously check, whether the player is in contact with a wall or not. Im checking this via raycastnode.is_colliding() for raycasts and area3dnode.has_overlapping_bodies() for area3ds.
Unfotunately, force_raycast_update() did not help. as for your other suggestions, i already tried them before.
thank you for your suggestions either way.
I managed to work around the issue of the wallrun ending early by using the characterbody3d inherent is_on_wall() function, however this is doesnt fix the issue of the collisions not working properly, as i need the normal vector of the surface that is raycasted to calculate the players velocity and am thus required to use raycasts (or shapecasts) to have access to the get_collision_normal() function .
Although is_on_wall() works really well, it neither fixes the underlying issue, nor is it sufficient for what i need.
Im thinking i might be able to store the object that was last collided with as a variable and then pull the normal vector from the surface of the object somehow, that way even if the collision is detected only a few frames out of the standard 60 fps for _physics_process(), i could still get a usable normal vector for flat surfaces.
However even if this worked, it would only work with completely flat surfaces…
:C
thank you once again for your suggestion, unfortunately this didn’t help either.
although the wallrun occasionally starts as intended, it only works in one direction, the wallrun often times is cancelled either immediately or roughly a second after it starts, and if it does succeed the velocity applied often turns into a vector(0, 2, 0) that just turns the player into an elevator (ill figure out the vector math after fixing the collision check).
ive done some more debugging: neither the cause for stopping the wallrun prematurely is indeed the collision check returning false.
in short: raycast3ds is_colliding() and area3ds has_body_overlapping() collision checks only work on a few frames, leading to the wallrun ending instantly and the wallrun only starting some of the time.
is_on_wall() on the other hand, while being more reliable, still only works sometimes and often returns false even while the player is fixed to the wall.
I tried to switch from jolt to the default physics engine and it seems at least is_on_wall() now works properly.
Raycast3d and area3d checks still dont work even with the default physics engine maybe im using raycast wrong?
ill try to remake this from the beginning, but this time with a guide.
sooo… im feeling kinda stupid. although is_on_wall() still doesnt work with jolt engine, raycast now does.
i just forgot to rotate the raycasts with the camera (im not rotating the characterbody3d which is the raycasts parent node and thus changes the raycasts position).
the collision checks now work, however when wallrun starts, the velocity is changed to a vector3(0, 3, 0) turning the player into an elevator just as with is_on_wall() + default physics engine before.
Additionally, the raycast/area3d collision stopping, does not stop the wallrun.
At least the initial raycast and area3d work without any problems now.
ill try to figure out whats happening with the velocity and wallrun cancel condition then post a comprehensive explanation.
(fixed) neither area3d nor raycast3d output consistent true return values when checking their collision via has_overlapping_bodies() in the case of area3ds or is_colliding() for raycast3ds.
This was an issue caused by the area and raycast not overlapping with anything in the first place, as i forgot to rotate them with the camera.
(circumvented) the characterbody3d method is_on_wall() and the corresponding CharacterBody3d.get_wall_normal() do not work properly with the jolt physics engine
fixing to the default physics engine fixes the issue (but the bug is not fixed, only circumvented)
(ongoing issue) an arising issue after getting area3d and raycast3d to work: using the normal of the colliding wall to calculate a vector that the characterbody3ds velocity is lerped to, ends up turning the playercharacter into an elevator by fixing the velocity at a fixed upward vector and somehow disabling any checks that see if the wall is disconnected and disable the wallrun state.
from my research, the third bug seems to pertain the characterbody3ds move_and_slide() function, so i will try to switch the character controller to use rigidbody3d instead to circumvent the issue.
the second issue seems to be a bug caused by the jolt physics engine and subsequently difficult to fix but I’m not really sure of this.
For the time being, unless someone else adds some good suggestions, i wont update this post and just leave everything as it is, as i have fixed the initial issue that the post was originally about. have a great day and good luck with your projects.