# Character move on slope problem

Discussion in 'Physics' started by ZeuX, Mar 16, 2015.

1. ### ZeuX

Joined:
Oct 11, 2013
Posts:
13
Hi,Guys,
I have some question about high speed character physics problem,
I use changing velocity to make my character move,
(because addforce will stuck when walking on slope)
if it comes to end of up-slope or to down-slope in a little bit high speed,
it will fly off ground,
how can I keep my character always on ground,
I had think if I can not using rigidbody things,
but the game will have some moving platforms,
so, just use raycast behind character to make character position to hitpoint,
should not work.(because it will not move with platform)
so it must have rigidbody physics,
and if I use strongly gravity, when character sleeping, it will slowly skip down the slope,
that's not expected result,
I had draw a explain image here

2. ### McC1oud

Joined:
Mar 14, 2015
Posts:
96

9:17 if the url doesn't hold timestamp.

This might be related to your issue.

By the sounds of it, he uses some kind of trigger at the top to keep the character grounded.

ZeuX likes this.
3. ### sleekdigital

Joined:
May 31, 2012
Posts:
133
Another approach is to go ahead and use a higher gravity setting but turn the gravity on and off as needed (rigidbody.useGravity). If the player is grounded and has a velocity near 0, that means he is standing still on the ground. In that case, you can turn gravity off. That way he won't slide down slopes. If the player jumps or moves, turn the gravity back on.

ohilt06 and ZeuX like this.
4. ### mangax

Joined:
Jul 17, 2013
Posts:
334
even if he switched on higher gravity, the character will still jump off at high speeds.
what i can think of now is manage the character position in Y axis Manually when grounded!.

if you are using raycast to check if character is grounded, try re-position character height using hitpoint as ground position + character height / 2f.

let physics manages its position in XZ only... i dunno if this will result in any jittery... but disabling physics from Y axis alone should not cause so much issues.

ZeuX likes this.
5. ### ZeuX

Joined:
Oct 11, 2013
Posts:
13
thanks guys,
though this is not solve yet,
but I will try some logic
thanks a lot

6. ### delinx32

Joined:
Apr 20, 2012
Posts:
417
I agree with mangax. When the character starts, standing on flat groud, get the Y offset from the ground. Always make the Character's Y = groundY+offsetY, unless he's jumping or something.

ZeuX likes this.
7. ### ZeuX

Joined:
Oct 11, 2013
Posts:
13
OK,
So this is what I think,
If use raycast it will overlap ground when the slope is not flat,
and because the rigidbody physics, it will push character away a bit,
even worse it will still pushing if call this everyframe,
so I calculate the sphere hit point then cal back to the target we wanna it go,
just using spherecast,
but I dont actually try this yet, just think this might be work,
collider should be sphere or capsule
when character is not jump or not fall when nothing below it,
call this once,and move rigidbody to target,
then set velocity y to zero,and must be isGrounded,

the another problem is
there might be other cheaper way to calculate this thing,
because it use sqr, I think it will a little bit heavy,
hope someone can provide better method

the reason I don't use hitpoint normal to cal back
is because, the normal may be not precise,
maybe it's just a sphere thing like built-in sphere model
I don't know Unity's spherecast accuracy is enough or not
so this method might be more precise, but need be more cheaper

8. ### mangax

Joined:
Jul 17, 2013
Posts:
334
if you are planning to manage rigidbody height manually as we suggested..
whats so wrong (if) you placed collider at more height than simply placing it touching ground?
you don't need your sphere to drag it self on ground.. you can relay on raycast + repositioning in Y axis to place character in correct height.

look at image, with small offset for collider from ground... this way you can keep collider away from slops interaction! of course not all surfaces will be able to walk on.. sharp slopes will collide with player and make it hard for player to climb, which does not break common games logic..

make mesh model legs to reach ground (so it doesn't appear as if he is flying), while keep collider at small offset from ground.

lilwolf4evr, Razputin and ZeuX like this.
9. ### a-t-hellboy

Joined:
Dec 6, 2013
Posts:
180
Hey there,
Did you find proper way to solve this problem ? (Just not ramp or stairs, any kind of height like hills on terrain)

Last edited: Nov 24, 2018
10. ### mangax

Joined:
Jul 17, 2013
Posts:
334
my old solution i proposed here still works like a champ.. i use it personally..

11. ### kmart94

Joined:
Sep 27, 2017
Posts:
11
Project your velocity onto the ground using Vector3.ProjectOnPlane(velocityVector, groundNormalVector)
This should solve your issue giving your character a constant speed up or down any slope without any lifting.

12. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214
I'm having an odd problem when the character controller walks up slopes: it only works correctly if the slope (in this case, a ramp) is oriented along the global x-axis; but if it's rotated 90 degrees so it's along the z-axis, movement up the ramp is generally very slow and there are no footstep sounds (I added footsteps to the controller). This makes no sense to me, so I'm hoping someone can suggest a possible cause. I suppose I can just re-orient all ramps and staircases (which use an invisible ramp) so they face the right way, but that creates some problems.

13. ### mangax

Joined:
Jul 17, 2013
Posts:
334
apparently there is something wrong with your scripts.

but if your using (as an example) "vector3.right" to move a character, it will always effect along global x-axis, you need to use current object right direction, which is "transform.right"

Last edited: Sep 22, 2019
14. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214
I'm using transform.right for sidestrafing and the default Unity code for the rest (the main part of the latter is: Vector3 v = (m_Animator.deltaPosition * m_MoveSpeedMultiplier) / Time.deltaTime; )

15. ### mangax

Joined:
Jul 17, 2013
Posts:
334
it's hard to tell what's wrong without the full script that controls the character.. are you rotating the character as well (the transform) to orient it toward the Z direction in world??

16. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214
I'm rotating the character based on mouse input; the code for that is:
Code (CSharp):
1. xRotation = Quaternion.AngleAxis(-_mouseAdjusted.y, targetOrientation * Vector3.right);
This does use Vector3.right (which another person thought might cause the problem), but in this case it needs to use that value to get the correct motion (I changed it to the character's transform.right but that doesn't solve the problem on ramps, it just messes up the process of swiveling the camera while looking around).

17. ### mangax

Joined:
Jul 17, 2013
Posts:
334
@HonoraryBob ahh i hate looking at quaternion scripts.. makes my head spin.. the vector3.right feels off..

but i generally i do not recommend the approach you are using.. it's unnecessarily complicate things..
it seems you explicitly control the movement relative to character transform orientation/direction .. or world direction.. in other words.. the character move into a direction depending on it's orientation or where it is facing in the world..

what i would do, is controlling the character movement without respect to it's orientation.. Simply use the position of the character , then add/subtract depending on the input direction.. you just update the position where the character should go.. simple and effective..

for rotation.. you apply it for only "aesthetics and looks".. so depending where the character is currently heading, you update rotation so it is facing the direction currently moving towards.. so even if your character started flipping or rotating around.. it won't effect the movement script.

the approach you currently using is useful for controlling space ships/ships/cars.. where your ship rotation effects where your current thrust will apply forward speed.. but for characters its totally not needed.

18. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214

But the code doesn't control the speed of the character while walking up a slope (which is where the problem lies) - that's controlled by Unity's rigidbody physics because the code just pushes the character at the same speed and then the character is slowed down by the rigidbody moving up a gradient. The problem is that the speed oddly depends on which direction the ramp is facing, which doesn't make any sense. But it's clearly due to the physics system, not my controller code because the latter doesn't vary the speed. So that leaves the question of why the direction would make any difference - i.e. if a staircase is facing north the player shouldn't move more slowly than if the staircase is facing east, but that's what happens.

19. ### mangax

Joined:
Jul 17, 2013
Posts:
334
i guarantee to you that there is nothing wrong with unity's physics engine.
you need to check how you setup your scene objects and your scripts.. if you are dragging your character on ground.. apply my solution that i proposed for the other guys earlier.

20. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214

What could be wrong about the setup? The ramp is just a scaled quad tilted 54 degrees in the X axis; so I have no idea why rotating it around the Y axis would make any difference : the slope is still the same, the quad is still the same, and if it works while facing one direction then it should work when facing any other direction. My script just does what the default Unity third person controller does, since it was adapted from that. Again, if it works on ramps that are rotated in one direction then it should work for all directions.

21. ### mangax

Joined:
Jul 17, 2013
Posts:
334
can you send me a sample project of the issue?? send it as a private message.

22. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214
I traced the problem to the following line in Unity's default ThirdPerson controller script:
move = Vector3.ProjectOnPlane(move, m_GroundNormal);

This uses the ground normal, which would apparently explain why it cancels movement on an incline in certain directions, hence it throws the animator into the idle clip, which slows player to a crawl sometimes and also interrupts my footstep code since that code has to check whether the idle animation is beginning (otherwise an extra footstep plays after player has stopped moving as the animator transitions into the idle animation).

23. ### mangax

Joined:
Jul 17, 2013
Posts:
334
i don't like using animator speed.. it has some draw backs if you are not managing it 100%..

animations for me is no more than a "representation" everything is controlled on rigidbody velocity.. so your issue has nothing to do with physics.. your animations is what controlling the speed and causing issues.

Last edited: Sep 26, 2019
24. ### HonoraryBob

Joined:
May 26, 2011
Posts:
1,214
I said it was caused by the ProjectOnPlane() function (not physics), which takes the slope into account and there's clearly something going wrong with that. That code was just the default Unity code in the built-in controller. m_GroundNormal is just hitInfo.normal (the normal of the collider hit by the downward raycast that checks what's underneath the player). So ProjectOnPlane() clearly isn't working when the ramp is rotated toward certain directions.

25. ### B1QQ

Joined:
Aug 16, 2018
Posts:
10

Had the same issue. this vid helped me a lot
I gave up on using Rigidbody

haolly and ayhanavci like this.
26. ### PacoBarba

Joined:
Apr 10, 2015
Posts:
4

A video with the solution to this problem, I hope it is helpful.