# Walking up a ramp: Walking sideways works better than walking straight

I’ve been looking into a weird issue in my game. The really quick summary is that my player seems to be able to walk up a ramp more easily when aiming a bit sideways than when walking directly up the ramp.

Here’s a quick GIF showing the basic problem. What’s not really shown is that this ramp is steep enough (30 degrees) that if I aim straight at the ramp and try to walk forward, I don’t go up the ramp. The player could get up a 25’ ramp, but 30’ is too steep for the amount of force I’m giving the player. However, if I start aiming a little off to the side of the ramp, still walking “forward” relative to the camera, the player starts to move. The player moves both to the side, but importantly he also moves up the ramp. By aiming left and right repeatedly, I can go all the way up the ramp.

Some details:

• The player is a capsule collider.
• The player’s rigidbody has rotation constrained, on all axes. The player is only ever rotated by a MouseLook script that changes its local rotation.
• The player’s and the ramp’s colliders have the same PhysicMaterial, which has both Static and Dynamic coefficient’s of friction of 0.6. My first thought was that this the result of lower dynamic friction than static friction, such that once the player starts sliding left/right, their friction is reduced, and they can now go up the ramp more easily. But with identical static and dynamic coefficients, I assume that can’t be the issue.
• I’m moving the player with AddForce, in an extremely simple way: _rigidbody.AddForce(transform.forward * 50 * _rigidbody.mass);
• This isn’t only restricted to ramps. I have a related issue where the player is on flat ground, but is being pushed in one direction. He can’t move into that force if he goes straight into it. But if he aims left and right a little, he can get through and make forward progress.

So I’m not sure what would cause this behavior. It seems like the most forward force would be generated by facing directly at the ramp, and that aiming off-center would mean less force. But aiming off-center actually causes the player to go up.

Anyone have any thought on whether this seems “normal”, or what could be going on?

I spent a little more time simplifying this to make sure it wasn’t related to something else I was doing. I created a new sample project (in case this is a bug) isolating the behavior. The result of my findings is that even with identical Static and Dynamic friction values, it’s easier to move forward if I’m already sliding left/right than it is to more forward from a dead stop.

In my new simple test case, I have a “character”, which is just a flat box (2x1x2) with a Rigidbody, and no rotation constraints. Gravity is enabled, and this “character” has been placed on a large plane with some boundary walls. A “Pusher” script on the “character” exerts constant -Z force on the rigidbody, pushing it towards the wall.

The character controller allows it to move around. The simplified movement allows the character to move in one of four directions: Forwards, Backwards, Left, or Right. When running the scene, the character quickly ends up against the wall. Trying to walk Forward (away from the wall) doesn’t work, as the movement force isn’t great enough to overcome the -Z force being applied by the “Pusher” script. So the player just stays there held against the wall.

However, here’s the issue: If I move left or right first, so that the character has some inertia, THEN I try to move forward, I can move forward for a while. Here’s a demonstration.

The character and the ground have the same PhysicMaterial, with .6 for both dynamic and static friction. And yet, the character can make forward progress only if they’re already moving left/right a bit.

Does anyone understand why this is the case? Or is this a bug?

I’m a “bit” high so I might be thinking about this in a wrong way, but did you try projecting the vector you’re applying on the plane the player is standing on?

Probably not the answer but might shed some light on the problem.

I have a few prototypes with some-what simillar but still different rigidbody first person scripts and I’ve never noticed this behaviour, but I don’t really have ramps like that, some slope-age but more like bumpy hills

Also, is the player transform your taking the forward vector from is rotated on the X(might be confusing it with Z) or only the Y?

The “ramp” approach in the first post ended up being an slightly overly complicated example, which I’ve boiled down and simplified in my second post. In the second post, the whole system is just a horizontal plane, and a player that can only move forward, left, or right, but nothing in between. So in that sense, no projection of the force is needed (nor is any being done).

The sample project I made for this is really simple and small. I’ve attached it to this issue. With the scene running, you just press A or D to move left and right. Then release the key, and press W to move forward. The thing to note is how pressing W doesn’t move the player forward if the player is completely still initially. It only works if the player is drifting left or right.

I image this doesn’t come up much because it’s probably rare for a player to be pushed in one direction with nearly the same force as they are able to exert in the other direction. If the two force values aren’t fairly close to each other, this behavior doesn’t occur.

Is it on 2018?
If so maybe test it with an older version, I found some wierdness with it and i told myself im gonna stick to 2017.4 for a few more releases(I also hanged on 5.6 until 2017.4)

I asked about this on a pure physics forum, as I wanted to understand it better, and the consensus is that the behavior is correct. It’s not initially intuitive to me, but as I understand it the general idea is fairly simple: Dynamic friction is only exerted in the direction opposite the direction of motion, and the force has a fixed magnitude based on the mass of the object and the materials involved. So in that sense, there is a “friction budget”, or a maximum magnitude of force that can be applied due to the friction. It’s just the direction of the force that can change based on the current velocity of the object.

So, when the object is sliding East very quickly, and I try to push it North, friction is mostly only the object West to slow it down. Since since force is capped, the south-pushing friction that gets generated by my northward push is very small. It’s like aiming a unit vector 91 degrees to the west. The “west” component of that unit vector is very high, while it’s “south” component is very small. So in that sense, friction won’t be doing much to slow down my north motion if the eastward motion is high.

This still feels a bit weird to me, but it’s been confirmed by some physics folks at PhysicsForums.com, and by the unity team. (By “confirmed” I mean that the general idea has been confirmed. My poor attempt at trying to explain it is probably fully of errors.)

So, in short, this is working as intended, and it’s apparent just the way friction works in real life.

1 Like

Ok, but if we accept that everything works just as intended (and as it does in the real world), then we’d still have that bug to deal with.

The player is not intended to be able to walk up that ramp, right?

Here’s an idea:
Every frame you trace downwards so you know what you’re standing on (maybe more complicated when you’re actually standing on multiple things, or maybe you could do just a sphere-cast and take the first object you collide with).
If the ground normal is too high you would “eliminate” any acceleration into the forbidden direction.
So you calculate the velocity component you have towards the “ramp up” direction and subtract that from your current velocity. Which would essentially remove all velocity that could potentially push the player up the ramp, while still allowing perfectly normal movement into any orthogonal directions and down the ramp.

Have you tried the kinematic character controller from the asset store? I wonder if it has the same problem, but I doubt it.
If if have some time later today I’ll do a quick test.

I’m already doing exactly what you’ve mentioned. And this problem goes beyond just ramps: It works any time a constant force is pushing the player in one direction. If the force is very close, but slightly less, than the force the player can apply, then we’ll end up in this situation where walking directly against the force will cause no forward progress, but walking a little sideways into the direction of force will result in some forward progress.

As for how to deal with the problem in general, I’m not sure yet, other than to generally try to avoid it. For ramps in particular, making the ramp just a little steeper would avoid the issue, as eventually the steepness would just be too great to overcome.

I haven’t tried the kinematic controller. I’ve looked into it a bit, as it seems to overcome a few issues I have. I’m considering it as a possible future purchase if I keep running into weird issues my dynamic rigidbody controller.