2
\$\begingroup\$

I know there are already some threads about this, but my problem isn't exactly with the algorithm itself. I was able to use RayCast and get the ground normal, using it to store the rotation necessary to align to the ground in a quaternion using:

slopeRotation = Quaternion.FromToRotation (transform.up, hit.normal);

Where hit.normal is the normal of the ground. After this, I check whether the player is moving (the user is moving the joystick axis) or standing still. If it's standing still, I align it with the ground using:

transform.rotation = Quaternion.Slerp(transform.rotation,slopeRotation * transform.rotation,10*Time.deltaTime);

When the player is moving, I rotate using:

transform.rotation = Quaternion.Slerp (transform.rotation,slopeRotation *camRotation*movementRotation , 10 * Time.deltaTime);

Where camRotation is simply the rotation of the MainCamera(a third person one) on the Y axis and movementRotation is the rotation of the joystick axis, also on the Y axis, calculated using:

movementRotation = Quaternion.LookRotation (new Vector3(Input.GetAxis ("Horizontal"), 0, Input.GetAxis ("Vertical")));
camRotation = Quaternion.Euler (0, cam.transform.rotation.eulerAngles.y, 0);

Although the code above makes sense in my head, it doesn't work as expected, as seen in the picture below: enter image description here

As you can see, it works fine when you're standing still, which means that the ground normal and the slopeRotation are correctly calculated. When the player moves though, the combination of all the quaternions seems to cause some kind of problem that makes the player slightly deviate from the correct rotation. It might be worth noting that camRotation and moveRotation also work completely fine on their own, so the player moves correctly according to both the rotation of the camera and of the joystick, both on the floor and on ramps.

\$\endgroup\$
3
\$\begingroup\$

Nevermind guys. I just realized a really silly mistake behind all of this. The thing is, when I use:

slopeRotation = Quaternion.FromToRotation(transform.up, hit.normal);

to get the rotation necessary to align to the ground, once the Player aligns itself to the ground, slopeRotation will become Quaternion.identity, since transform.up's direction will be the same ashit.normal. It work's fine if the Player is standing still.
However, if I try to move on a ramp, the Player will correctly rotate according to the camera and to the joystick input, but since slopeRotation == Quaternion.identity, the Player will always try to revert back to it's initial rotation.
Thus, when the player is moving, I create another Quaternion, called slopeRotationMoving = Quaternion.FromToRotation(Vector3.up). So, because slopeRotationMoving is relative to Vector3.up which is always pointing up (as opposed to transform.up, which will eventually align with the surface), it will never revert back to Quaternion.identity. Now, when the player is moving, I use:

transform.rotation = Quaternion.Slerp (transform.rotation,slopeRotationMoving *camRotation*movementRotation , 10 * Time.deltaTime);

And it works perfectly. So, as a reminder, always remember to use transform.up, transform.forward,Vector3.up,Vector3.forward, etc. according to your needs, since they're very different.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.