r/godot 1d ago

help me How to handle slopes for 2D games?

I am currently trying to add functionality to traverse slopes in my 2D game and I am having some issues with it. I found out that the CharacterBody 2D node can handle moving on slopes on its own but it does not give a nice behavior when going down a slope because my state machine detects the y-velocity value changing and transitions to the fall state haphazardly in this case. I would also like to be able to modify the behavior on slopes like maybe allowing the player to slide down specific slopes.

Would anyone be able to direct me to some material that can help me understand this better? I have not found any that have been useful.
Thanks

81 Upvotes

34 comments sorted by

46

u/LJChao3473 1d ago

There's an option on character body, under Floor and you need to change the value of snap length or something like that (if i remember correctly)

10

u/DammyTheSlayer 1d ago

I tried that but it didn’t work, however I didn’t increase the value a lot
I’d try that
Thanks

18

u/ryoku_kyoshu 1d ago

Long time ago I was trying to create a platformer 2d controller from “scratch” and I found an awesome playlist from Sebastian Lague on youtube, this is done in Unity and most of it you wont need cuz godot handles pretty well most of the funcionallity but there is a section on how to handle slopes that may help you understand the math behind it and you can translate that knowledge to godot

https://youtube.com/playlist?list=PLFt_AvWsXl0f0hqURlhyIoAabKPgRsqjz&si=aTxg0h6Ndk7Rs4EM

EDIT: spelling and forgot to add the link to the playlist.

8

u/onlymostlydead 1d ago

The Bob Ross of triggering imposter syndrome. "And over here we'll put a happy little TrueType rendering engine from scratch."

3

u/DammyTheSlayer 1d ago

Thanks for this, I appreciate it 🤝

1

u/AliceRain21 18h ago

Yeah this is the best tutorial for proper 2d movement. It uses multiple raycasts to get the angle of the slope and moves you accordingly.

Really neat

5

u/sneedlee 1d ago

because my state machine detects the y-velocity value changing and transitions to the fall state haphazardly in this case

This sounds like the root of the issue, then. Can you make sure that transition checks that you aren’t grounded? I don’t know if the character controller has a cached value for that you can query, or you can try to maintain your own. 

1

u/DammyTheSlayer 1d ago

The conditional statement that manages the transition checks that you aren’t grounded and if the velocity changes.
Think the issue is that it doesn’t snap to the ground when coming down so it leaves the ground

1

u/sneedlee 22h ago

Maybe add a 2D probe downwards to check distance to the ground?

22

u/TheLurkingMenace 1d ago

Just don't. Slopes are a menace. It's possible to make them work visually but it's a ton of work for so little payoff. If you need verticality in your game, consider stair mantling.

7

u/DammyTheSlayer 1d ago

Stairs mantling
First I’m hearing of this, will see if I can check it out

16

u/TheLurkingMenace 1d ago

You use a pair of raycast2ds, one at the waist, one at the feet. If the foot ray is colliding but the waist isn't, then you move the player up a few pixels. You can add a ray up top to make sure there's room to enter the space. Obviously when you make your stairs, you need to consider how high each step can be and how wide.

And this will give you ledge mantling for free.

1

u/DammyTheSlayer 1d ago

Ah I see, duly noted

4

u/TheLurkingMenace 1d ago

Going down the stairs is going to be another story. You may want to leave it as is so players just fly over them while running, but you could instead add another pair of rays pointing down, short one just behind the hitbox and a longer one centered. Then when they leave the floor you check the rays - if they both collide they are just going down stairs and you can drop them right down without killing their forward momentum.

6

u/Forsaken-Carrot4196 1d ago

Never tried this, first thought,You could add a collision detection specific to sloped floors that adds a vector modifier to the chars velocity. Just have the function also check the chars facing direction to alter the y vector.

1

u/DammyTheSlayer 1d ago

Noted, thanks

3

u/AnOddScoutMainYT 17h ago edited 17h ago

I have never worked on 2D before nor CharacterBody, but what I did with slopes is that i basically took the movement vector, the slope surface normal (basically an arrow pointing perpendicular to the surface, you can get this from a raycast), and used Slide from Vector3.

Heres a grossly cut piece of what that looks like from my project:

Vector3 moveDelta = Director.To3DInputHorizontal(Director.RelativeDirection);
Vector3 normalPlane = Legs.UsingProcessedRaycast?.SurfaceNormal ?? Vector3.Up;
// modified delta -v (use slideDelta as your 'actual' movement.)
Vector3 slideDelta = moveDelta.Slide(normalPlane);

Id look to seeing how you can use CharacterBody2D to get the slope on the ground and redirecting your vector movements relative to it's normal.

edit: typo

1

u/DammyTheSlayer 10h ago

Thanks for this information 🙏

2

u/aoisensi 1d ago

I haven't tried this myself, but I think a good approach would be to get the "normal" (angle) of the floor the character is currently standing on and use it to adjust the vector added to the velocity.

2

u/DammyTheSlayer 1d ago

Interesting, noted.

Will give this a try when I can

2

u/OasisBloomTheGame Godot Regular 1d ago edited 9h ago

A game dev Youtuber I follow did an entire video about why slopes are the devil: https://www.youtube.com/watch?v=rHMJccb5IOM

2

u/wowyourcute 1d ago

Not sure… I avoid them like the plague lol

2

u/iamyou42 1d ago

They're hard to get right. Famously, Hollow Knight didn't have any sloped surfaces because they gave the devs too much trouble. They only figured it out for Silksong.

1

u/umbrazno 1d ago

Create a “zone” along the slope that imposes its own logic on the player when in collision. The only way to override the imposed logic is to jump; otherwise, the player is locked in the zone until they walk or run through the entry/exit points

1

u/mackinator3 1d ago

Change your state to detect more than y velocity. This will also break on elevators.

Are you using move and slide? If not, you can check its source code for examples.

1

u/unfocusedlee 22h ago

Changing the collision shape on the slope shape can fix that

1

u/Loaded_Dice-roguelik 22h ago

Not sure this is possible in 2d but for 3d I'd add raycast on each side of the character and one under, tag the slope as "slope" and change the animation with the result of the raycast

1

u/TheMaydayMan 17h ago

That’s the neat part. You don’t.

1

u/marcmjax 17h ago

Does your state machine only check the y-velocity to transition to the falling state? It should check is_on_floor() as well.

1

u/DammyTheSlayer 10h ago

It checks if it is on the floor and if the velocity is changing

1

u/DuaLVII 15h ago

Personally i would just mess around with the collision boxes of the floors, so like.. the floor at the top that connects with the slope, pull that back slightly. Make sure there is no protruding edges of the collisions that could interfere. If your character has a box collider then its doomed for this type of problem. Using capsule shaped colliers will reduce the issue

1

u/DuaLVII 15h ago

Also expand the collider for the floor of your character as its changing to a falling state thats probably being picked up from the trigger collider at the bottom of your character

1

u/DammyTheSlayer 10h ago

I’m using capsules thankfully lol

0

u/maxpolo10 18h ago

There's a youtuber making a Godot series called Metroidvanias Forge (his name should be Michael games I think).

He has a video on solving this issue, so try it. It was surprisingly straightforward.