Need help fixing align to spherical surface script

Discussion in 'Scripting' started by Vitaly-Abilevich, Sep 13, 2017.

1. Vitaly-Abilevich

Joined:
Nov 6, 2013
Posts:
55
Good day community!

I got this script attached to the player:

Code (CSharp):
1. using UnityEngine;
2.
3. public class SurfaceAlignment : MonoBehaviour {
4.
5.     bool allowAlign = true;
6.     float alignSpeed = 10f;
7.
8.     void Start () {
9.
10.     }
11.
12.     void FixedUpdate () {
13.         foreach (GameObject go in GameObject.FindGameObjectsWithTag("Planet"))
14.         {
16.
17.             float xDist = go.transform.position[0] - transform.position[0];
18.             float yDist = go.transform.position[1] - transform.position[1];
19.             float zDist = go.transform.position[2] - transform.position[2];
20.
21.             float distSquared = Mathf.Pow(xDist, 2) + Mathf.Pow(yDist, 2) + Mathf.Pow(zDist, 2);
22.
23.             float dist = Mathf.Sqrt(distSquared);
24.
25.             if (allowAlign)
26.             {
28.                 {
29.                     Vector3 targetPoint = go.transform.position - transform.position;
30.                     Quaternion targetRotation = Quaternion.LookRotation(targetPoint);
31.                     transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * alignSpeed);
32.                 }
33.                 else
34.                 {
35.                     Vector3 targetPoint = new Vector3(0f, 0f, 0f);
36.                     Quaternion targetRotation = Quaternion.LookRotation(targetPoint, Vector3.up);
37.                     transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * alignSpeed);
38.                 }
39.             }
40.         }
41.     }
42. }
What this code does is that when the player aproaches a sphere with the tag "Planet" in a range, it's mesh is aligned to the vector from the center of the sphere to the player position, but problem here is that instead of landing on feet, the player lands on his belly, this means that instead of being aligned over the Y axis, the playes is aligned over the Z Axis. I just do not have enough brain to fix this.

2. Dave-Carlile

Joined:
Sep 16, 2012
Posts:
958
Not an answer to your question, but distance can be calculated like this:

Code (csharp):
1. float distance = (go.transform.position - transform.position).magnitude;
or

Code (csharp):
1. float distance = Vector3.Distance(go.transform.position, transform.position);
That will simplify your code quite a bit.

As far as the orientation being off, how is your model aligned in its local space? You may just need to add 90 degrees or something, or use a different Up vector when calling LookRotation?

Vitaly-Abilevich likes this.
3. Vitaly-Abilevich

Joined:
Nov 6, 2013
Posts:
55
Thank you, I will consider this, I am using a Primitive Cube created inside Unity

4. BlackPete

Joined:
Nov 16, 2016
Posts:
822
Couple options here:

1) Use a state machine. If the player falls, switch the camera's reference point to something else (or even just null) where it can lazily drift around with a mournful "awwww" audio clip.

2) Use the ground surface as the camera's reference point. You have both the surface position + normal. Offset up along the normal to use as the camera's look-at position.

3) Use a variation of the above and blend together the reference points to set the camera's final reference point.

4) Look at the Cinemachine tool which can handle this stuff for you (I haven't personally used it yet, so I can't quite tell you how to use it).

Vitaly-Abilevich likes this.
5. Vitaly-Abilevich

Joined:
Nov 6, 2013
Posts:
55
Thank you, but to be honest I don't understand this

6. Dave-Carlile

Joined:
Sep 16, 2012
Posts:
958
So... how do you know if the player has landed on his feet or his belly?

Vitaly-Abilevich likes this.
7. Vitaly-Abilevich

Joined:
Nov 6, 2013
Posts:
55
Because of the Local Axis, Z Axis should be Front-Back, Y Axis should be Up-Down and X Axis should be Left-Right, Z positive gets alignes to the vector so it lands with the belly, it should be aligned over Y negative (Down) Axis

8. unit_nick

Joined:
Jul 15, 2017
Posts:
23
Are you sure the atmosthereRadius is large enough that he can stand? Maybe the distance is always greater causing him to face the center?

9. Vitaly-Abilevich

Joined:
Nov 6, 2013
Posts:
55
Yes, I can see the rotation between the outer space orbit and inside atmosphere.

Also I have solved the issue, kind of, instead of adding this script to the player, I created an Empty Transform, then I parented the camera to the transform and added a rotation script to the camera, made some adjustments to the rotation script, then I just copied the location of the player over the Empty Transform and then copied the rotation of the Empty Transform to the player and it works, problem is that I can not rotate the player over it's Y Axis, I still have to solve that and I have figured out what the problem is but I do not know what is causing it, I currently have this thing:

Code (CSharp):
1. Vector3 targetPoint = go.transform.position - transform.position;
2. transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * alignSpeed);
What I did is to override it with:

Code (CSharp):
1. Vector3 v = go.transform.position - transform.position;
2. Quaternion q = Quaternion.FromToRotation(-transform.up, v);
3. transform.rotation = q * transform.rotation;
And it works almost perfect, problem is that the transition between the 2 rotation is instant, there is no smooth transition, so I changed the last line and in result it looks like:

Code (CSharp):
1. Vector3 v = go.transform.position - transform.position;
2. Quaternion q = Quaternion.FromToRotation(-transform.up, v);
3. transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * alignSpeed);
But Quaternion.Lerp() and Quaternion.Slerp() causes a weird issue, instead of aligning to the surface based on the position over the planet, it sit still over a constant direction, this means that the vector always points to somewhere and never changes, no matter the position of the player over the planet.