I know this is a popular problem, but haven’t found a real solution for my open world CharacterController, and tried a few prototypes by myself, i thought it will be time to ask to our great community and to help others that might have the same problem!
How could you give the ability to the CharacterController to slide down slopes with a relative good performance?
Mostly avoiding the “stick to wall” effect.
*Would something like this make sense? (pseudo-pseudo logic) Check the ground slope on FixedUpdate and somehow add a remanent of the position of the player minus the normal of the ground to push the player in that direction?
I see lots of unity games that are obviously using a custom character controller that has friction on walls and slide on slopes, shouldn’t Unity build a better character controller that does this? What do you guys think?
I did a post just yesterday about tilting a plane to where something is.
I bring this up, as the code to calculate the normals according to where you are are about the same.
When you are doing movement with your controller, you will need to get the hit where your character is sitting. Say he is on an angle of 45 degrees. The hit only gives you back a normal and a point. using the normal and Vector3.up (or Transform.up) you can get the angle of rest for your controller. If this angle is above your slope you need to slide down, then you can do your slide.
Figuring the direction of that slide is the easy part using the code that I posted in the link.
Get a cross between the normal and Vector3.up. This gives you the cross direction (or right) of the direction that you should be going. Getting the cross direction of that right and the normal will give you the direction you need to slide in.
First, let me thank you for your time on pointing me into the right direction, am quite there i think.
I got to get the slide direction as you pointed perfectly, now actually sliding the player in a smooth/natural manner is the new problem, thinking about not letting the player jump, or move(not aloot) while sliding so i can avoid flickering movement?
This is what i got right now, is it there a better way?
public Vector3 slidingDirection;
public bool sliding;
void Update(){
....
moveDirection.y += (gravity * Time.deltaTime) * 3f;
moveDirection += slidingDirection;
_characterController.Move(moveDirection * Time.deltaTime);
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (angle > 40f)
{
sliding = true;
Vector3 normal = hit.normal;
Vector3 c = Vector3.Cross(Vector3.up, normal);
Vector3 u = Vector3.Cross(c, normal);
slidingDirection = u * 4f;
}
else
{
sliding = false;
slidingDirection = Vector3.zero;
}
}
sliding is a form of moving… so you need to do this wher eyou move. up in your Update.
Do a SphereCast from your collider down, and see if he is standing on a slope, if so, add the sliding to his movement. He should never be able to slide slower than he can move, You could give more movement to steeper inclines.
So… get the keys and get that movement * speed, get the sliding if he has some * sliding speed, and add the two together. limit it to the slide speed so that he cant rush the slide. That way he can control how he slides, but he will still slide.
NOTE… I am saying that this is not supposed to happen in OnControllerColliderHit… only in the update.
Trying on ControllerHit feels weird , i need another option to find that point where the charactercontroller is actually standing, was trying a 360 raycast with no luck, let me see what can i get with the spherecast.
Notice that OnControllerColliderHit generates 80 bytes of garbage for each call, which can become a huge problem with many character controllers walking around