Search Unity

  1. We've closed the job boards. If you're looking for work, or looking to hire check out Unity Connect. You can see more information here.
    Dismiss Notice
  2. We're running great holiday deals on subscriptions, swag and Asset Store packages! Take a peek at this blog for more information!
    Dismiss Notice
  3. Check out our Unite Austin 2017 YouTube playlist to catch up on what you missed. More videos coming soon.
    Dismiss Notice
  4. Unity 2017.2 is now released.
    Dismiss Notice
  5. The Unity Gear Store is here to help you look great at your next meetup, user group or conference. With all new Unity apparel, stickers and more!
    Dismiss Notice
  6. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice
  8. Unity 2017.3 beta is now available for download.
    Dismiss Notice

Need help fixing align to spherical surface script

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

  1. Vitaly-Abilevich

    Vitaly-Abilevich

    Joined:
    Nov 6, 2013
    Posts:
    54
    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.         {
    15.             float atmosthereRadius = go.GetComponent<Planet>().atmosphere;
    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.             {
    27.                 if (dist <= atmosthereRadius)
    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

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    937
    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

    Vitaly-Abilevich

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

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    609
    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

    Vitaly-Abilevich

    Joined:
    Nov 6, 2013
    Posts:
    54
    Thank you, but to be honest I don't understand this
     
  6. Dave-Carlile

    Dave-Carlile

    Joined:
    Sep 16, 2012
    Posts:
    937
    So... how do you know if the player has landed on his feet or his belly? :)
     
    Vitaly-Abilevich likes this.
  7. Vitaly-Abilevich

    Vitaly-Abilevich

    Joined:
    Nov 6, 2013
    Posts:
    54
    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

    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

    Vitaly-Abilevich

    Joined:
    Nov 6, 2013
    Posts:
    54
    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.