Godot Version
v4.6.3.stable.official [7d41c59c4]
Question
I have been trying to create something similar to Titanfall 2’s wall running system but I ran into an issue involving running along curved surfaces.
I keep the character stuck to the wall by applying a force based on the inverse of the wall normal. The wall normal is obtained by a raycast going from the player towards the wall (also using the inverse of the wall normal). The current wall normal value is naturally updated to whatever wall normal is picked up by this raycast. I can’t find anything about how this is done in Titanfall, but this is what I came up with. (If anyone has any knowledge on the topic, or have an idea about how this could be better implemented, please let me know)
This method works fine… as long as the player is moving fast enough into the wall run. If the player is moving a bit slower, the force applied to keep the player stuck to the wall ends up applying a force that is at least somewhat parallel to the orthogonal vector of the wall normal–or the surface of a given side of the cylinder/curved surface–whenever the normal is updated to the normal of the following side of the curved surface. This creates a sort of rubber banding effect where the player is prevented from going over the edge of current side by the “stick force”.
Here is a video which shows this issue: Watch issue | Streamable - Don’t mind the pink raycast, it’s for the initial latch to the wall.
(If it is is still unclear with the video I can make a better one, but here is also a diagram)
I thought this was all that was happening, but sometimes I feel like I am able to break past the force, get over the edge, and still not get pulled towards the new surface… so there might be a different issue playing into this behavior, but this is what I understand for now.
If anyone has any ideas of how to fix this issue, or has any alternatives for keeping a player to a curved surface while wall running, it would be greatly appreciated.
So far, I have tried making the raycast trail behind the player (based on the inverse of the move direction) but this was unreliable. I tried removing the part of the force that goes against the move direction, but I realized that that was… all of the force, apparently. The force towards the wall is either cancelled out or pushed against the move direction as well because of how move and slide works (I think?). I tried redirecting the velocity along the wall every normal change, but I couldn’t get the player to stick to the wall reliably. I tried interpolating the normal, but nothing seemed to come from that either. I have come to think that this is probably not how it is supposed to be done? I think maybe my last idea would be to use a spherecast or a body_test_motion instead of a raycast so there is more of a chance that the player is able to fully cross the edge before the new normal is applied (the normal is obtained sort of early since the ray comes from the center of the player instead of slightly in front.
Some other info (I’ll add to this as things come to mind):
- Player has a cylinder collider (outlandish! I know.)
- I’m not using the raycast3D nodes outside of debugging and demonstration, otherwise I am using the direct space state.
If you need me to show some of the code, let me know. I just, uh, need to do some… housecleaning beforehand.
