Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Rotating bilboard only on one local axis

Discussion in 'Scripting' started by Wojzax, Jun 2, 2020.

  1. Wojzax

    Wojzax

    Joined:
    Jul 22, 2014
    Posts:
    34
    So I'm making a table that has four billoard legs. Each one of this legs should be detachable and have it's own box collider. That's why I make the billboard planes child of the "physical" legs.

    Now I need to make the LegPlanes billboard objects look at the camera, but rotate only on one axis.
    I did something like this:
    Code (CSharp):
    1. void RotateToCamera()
    2.     {
    3. //rotating leg billboard with leg parent
    4.          Plane.transform.rotation=transform.rotation;
    5. //taking it's local rotation in this state
    6.         float xRot=Plane.transform.localEulerAngles.x;
    7.         float yRot=Plane.transform.localEulerAngles.y;
    8.         float zRot=Plane.transform.localEulerAngles.z;
    9.  
    10. //now rotating billboard with the camera
    11.  Plane.transform.forward=Camera.main.transform.forward;
    12.  
    13. //setting new local rotation on all axises. if object can rotate in certain axis
    14. //(AxisCanRot variable) it's getting local value from leg parent, if can't rotate
    15. // on certain axis it takes local rotation affected by camera position    
    16. float quatX; float quatY; float quatZ;
    17.         if(xAxisCanRot){quatX=xRot;}else{quatX=Plane.transform.localEulerAngles.x}
    18.         if(yAxisCanRot){quatY=yRot;}else{quatY=Plane.transform.localEulerAngles.y}
    19.         if(zAxisCanRot){quatZ=zRot;}else{quatZ=Plane.transform.localEulerAngles.z}
    20.  
    21. //now I put them all together as a new local rotation
    22. Plane.transform.localRotation=Quaternion.Euler(quatX,quatY,quatZ);
    23.     }
    In this code im having xAxisCanRot and yAxisCanRot true, and zAxisCanRot false, so legs will only rotate around local z axis.

    It all seems to work, Im rotating camera around chair and it works as intended, but when I knock over the chair and legs are upside-down or sideways there are some weird bugs.
    The legs rool no longer follows the camera, but kinda other way round.



    Is there a way to do this right? Maybe it's because legs are child to another parent, but I detached them and still they are acting the same
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    Don't futz with Euler angles. They are terrible.

    So the fundamental algorithm should be this:
    1. convert camera's position into coordinates local to "chair0Leg0", using transform.InverseTransformPoint. From this point on, chair0Leg0 is the space in which all of our logic will operate.
    2. "flatten" this converted position by setting its Y to 0
    3. Set chair0Leg0Plane.localRotation to Quaternion.LookRotation(flattenedCamera)

    That should pretty much be it. Let me know if any of these steps needs further clarification.
     
    Last edited: Jun 2, 2020
    Wojzax likes this.
  3. Wojzax

    Wojzax

    Joined:
    Jul 22, 2014
    Posts:
    34
    That really kinda work, I put
    Code (CSharp):
    1. Vector3 newCamPos=transform.InverseTransformPoint(Camera.main.transform.position);
    2.         newCamPos.z=0;
    3.         Plane.transform.localRotation=Quaternion.LookRotation(newCamPos)*Quaternion.Euler(0,90,90);
    at the end I have to add this Quaternion because my legs were shifted (the texture exactly)

    I get something promising, only weird thing is that every half of rotation the plane is upside down, like immedietly:



    this shift occurs almost exactly when legs are in certain rotation even if i dont change camera, just rotate table by itself it still happens
     
    Last edited: Jun 2, 2020
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    Can you log your newCamPos and see where the "flip" point is? I assume it's going to be when it crosses 0 on either X or Z. If so, you could workaround the issue by adding a 80 rotation if the X or Z is in that state. I'm not sure what the actual mathematical issue would be.
     
    Wojzax likes this.
  5. Wojzax

    Wojzax

    Joined:
    Jul 22, 2014
    Posts:
    34
    That was the case, thanks :) If newCamPos.x was more than 0, I change this additional Vector x to 180 and all works :)