- Home /
How can I rotate a player proportionally over a mesh?
I’m making 3PS/FPS where they player controls a tank that needs to stay level with whatever surface they are on. Most surfaces are going to be 3d like a sphere or like the inside of a cube (so not like a terrain).
Below is a function I use in the player controller script to ensure that the player is always level with the surface they are on.
void LevelTankOnMove()
{
float rotationAngle;
Vector3 rotationDirection;
Vector3 center = transform.position + transform.TransformVector(0, down, 0);
if (Physics.Raycast(center, -transform.up, out hitInfo))
{
Quaternion.FromToRotation(transform.up, hitInfo.normal).ToAngleAxis
(out rotationAngle, out rotationDirection);
transform.RotateAround(center, rotationDirection, rotationAngle);
}
}
It works great if the player is on a spherical collider. However, if the player is on a more conventional mesh, they rotate instantly when crossing over the seam between surfaces of the mesh (when the center of the tank crosses the seam).
What I’d like to do is have the tank rotate over the seam in proportion to the amount of the tank that’s over the seam (I'll post pictures in the comments).
Conceptually, I’d project the shape of the player’s collider onto the surface they are on and get a scan of lines, vertices, and other features beneath them that I could use to orient the player. I can do this with raycasts, but I have a feeling that there is an easier way of doing it. Unfortunately, I’m still pretty new to Unity, so I don’t know what part of the API might address this problem, or even what to google (which I have done plenty of).
Any ideas?
Answer by Kishotta · May 19, 2018 at 05:43 PM
One possible solution would be to cast several rays "down" (probably best to do one in the center and in a ring near the edge of the base) and record their hit normals. Then rotate the tank to align with the average normal. This way, if 3/4 rays hit a flat surface (normal is "up"), and 1/4 hits a 45 degree angle, the tanks rotation will be 11 degrees (you'll probably want to use more than 4 rays though).
I was hoping to find some way of using a navmesh to solve this problem as casting rays down would have caused problems when the tank moved over the edge of a cube i.e. the rays would never collide with anything. I fixed this by inserting a check for this situation which thenhas rays cast out from the center.