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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Quaternion Question

Discussion in 'Scripting' started by GreedyCorporationGames, Jul 15, 2018.

  1. GreedyCorporationGames

    GreedyCorporationGames

    Joined:
    Apr 20, 2017
    Posts:
    24
    Hello

    I'm trying to match the rotation of one object to another while offsetting the y axis rotation by a dynamic value.

    The y axis works perfectly but the x axis rotation is reversed and an unwanted z axis rotation is added. I was able set the z axis back to zero before applying it to the object but I can't fix the x axis.

    Code (CSharp):
    1. float portalOffset = Quaternion.Angle(portal.rotation, otherPortal.rotation);
    2. Quaternion yOffSet = Quaternion.Euler(0, portalOffset, 0);
    3. Quaternion newRotation = playerCamera.rotation * yOffSet;
    4. newRotation.eulerAngles = new Vector3(newRotation.eulerAngles.x, newRotation.eulerAngles.y, 0);
    5. transform.rotation = newRotation;
    Any feedback would be appreciated
    Thanks
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    OK... you're mixing quats and eulers in a way that just over complicates an issue.

    So before I even bother getting into some long diatribe about 3d rotations... how about instead... you describe what you need to have occur.

    NOTE - when I say describe what you need, don't do so in a way you think should work. So not in the context of quats or y-axis rotations or anything.

    What are you doing actually?

    Like I get the suggestion that you're doing something with 'portals' here, like in the game 'Portal' from Valve?

    Is it that you're trying to rotate the player when they walk through the portal so that they are oriented appropriately on the exit of the portal?

    Are you trying to rotate the camera to render the portal appropriately on either end?

    I think I helped someone out a while back with a portal demo... I should have that project laying around somewhere. I'll see if I can dig it up if you give me more information.
     
  3. GreedyCorporationGames

    GreedyCorporationGames

    Joined:
    Apr 20, 2017
    Posts:
    24
    Yes. I used this for most of the code.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    This hilariously looks similar to the one I helped some guy out with a while back... just the 'before' I modified it (all the way down to checking overlap in Update instead of OnTriggerEnter). They must of used this same tutorial.

    Anyways, they too were having camera rotational issues. I forked their project and basically rewrote the thing and pushed it back to them... here it is:
    https://github.com/lordofduct/PortalsDemo

    This was the original thread here:
    https://forum.unity.com/threads/portals.522231


    [edit]
    Yep, found the github project for the original from Brackey's:
    https://github.com/Brackeys/Portal-In-Unity

    I guess the bugs I described in that other post about the rotations actually originate from this tutorial and not from that person I helped. Which makes sense, I had a feeling when I was messing with it before that that person was not the original creator of it either.
     
    Last edited: Jul 16, 2018
  5. GreedyCorporationGames

    GreedyCorporationGames

    Joined:
    Apr 20, 2017
    Posts:
    24
    Sorry didn't have much time to make my last post. Is there anyway you could show me the rotation code. I don't have github and I'm really bad with source control.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
  7. GreedyCorporationGames

    GreedyCorporationGames

    Joined:
    Apr 20, 2017
    Posts:
    24
    I rewrote my Rotate() method based on the script you provided but it doesn't account for the rotational difference between the two portals.
    Code (CSharp):
    1. Quaternion q = Quaternion.LookRotation(-otherPortal.forward, otherPortal.up);
    2. Quaternion dq = Quaternion.Inverse(portal.rotation) * q;
    3.  
    4. transform.rotation = dq * playerCamera.rotation;

    Is there a way to add the rotational difference using something like this?

    Code (CSharp):
    1. float portalOffset = Quaternion.Angle(portal.rotation, otherPortal.rotation);

    Here's my complete script for the portal camera.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. namespace P3
    5. {  
    6.  
    7.     public class Portal_Camera : MonoBehaviour
    8.     {
    9.  
    10.         public Transform playerCamera;
    11.         public Transform portal;
    12.         public Transform otherPortal;
    13.  
    14.         public string testButton;
    15.  
    16.         void OnEnable()
    17.         {
    18.             SetInitialReferences();
    19.         }
    20.        
    21.         void OnDisable()
    22.         {
    23.  
    24.         }
    25.  
    26.         void Start ()
    27.         {
    28.  
    29.         }
    30.  
    31.         void Update ()
    32.         {
    33.             Follow();
    34.             Rotate();
    35.         }
    36.        
    37.         void SetInitialReferences()
    38.         {
    39.             playerCamera = GameObject.FindGameObjectWithTag("MainCamera").transform;
    40.         }
    41.  
    42.         void Follow()
    43.         {
    44.             Vector3 playerOffsetFromPortal = otherPortal.InverseTransformPoint(playerCamera.position);
    45.  
    46.             transform.localPosition = playerOffsetFromPortal;
    47.         }
    48.  
    49.         void Rotate()
    50.         {
    51.             if (this.tag == "Portal Camera Lab")
    52.             {
    53.                 Quaternion q = Quaternion.LookRotation(-otherPortal.forward, otherPortal.up);
    54.                 Quaternion dq = Quaternion.Inverse(portal.rotation) * q;
    55.  
    56.                 transform.rotation = dq * playerCamera.rotation;
    57.                 //float portalOffset = Quaternion.Angle(portal.rotation, otherPortal.rotation);
    58.                 //Quaternion yOffSet = Quaternion.Euler(0, portalOffset, 0);
    59.                 //Quaternion newRotation = playerCamera.rotation * yOffSet;
    60.                 //newRotation.eulerAngles = new Vector3(newRotation.eulerAngles.x, newRotation.eulerAngles.y, 0);
    61.                 //transform.rotation = newRotation;
    62.             }
    63.             else
    64.                 transform.localRotation = playerCamera.rotation;
    65.         }
    66.     }
    67. }
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    First off in your script you have a bunch of useless stuff that can be ripped out.

    Furthermore you didn't update how the position is updated, so that's going to be all wrong.

    You should also use LateUpdate to get a smoother look.

    This is what I did to get it to work:
    Code (csharp):
    1.  
    2. public class Portal_Camera : MonoBehaviour
    3. {
    4.  
    5.     public Transform portal;
    6.     public Transform otherPortal;
    7.  
    8.     void LateUpdate()
    9.     {
    10.         Follow();
    11.         Rotate();
    12.     }
    13.  
    14.     void Follow()
    15.     {
    16.         var playerCamera = Camera.main.transform;
    17.         //Vector3 playerOffsetFromPortal = otherPortal.InverseTransformPoint(playerCamera.position);
    18.         //transform.localPosition = playerOffsetFromPortal;
    19.  
    20.         Quaternion q = Quaternion.LookRotation(-otherPortal.forward, otherPortal.up);
    21.         Quaternion dq = Quaternion.Inverse(portal.rotation) * q;
    22.  
    23.         //update pos
    24.         var dv = playerCamera.position - portal.position;
    25.         dv = dq * dv;
    26.         this.transform.position = otherPortal.position + dv;
    27.     }
    28.  
    29.     void Rotate()
    30.     {
    31.         var playerCamera = Camera.main.transform;
    32.         Quaternion q = Quaternion.LookRotation(-otherPortal.forward, otherPortal.up);
    33.         Quaternion dq = Quaternion.Inverse(portal.rotation) * q;
    34.  
    35.         transform.rotation = dq * playerCamera.rotation;
    36.     }
    37.  
    38. }
    39.  
    Of course Follow and Rotate should honestly be done all at once since they both are based off rotation and need to calculate that:
    Code (csharp):
    1.  
    2. public class Portal_Camera : MonoBehaviour
    3. {
    4.  
    5.     public Transform portal;
    6.     public Transform otherPortal;
    7.  
    8.     private void LateUpdate()
    9.     {
    10.         var cam = Camera.main; //get the main rendering camera... we're going to be positioning based off this
    11.  
    12.         var q = Quaternion.LookRotation(-otherPortal.forward, otherPortal.up);
    13.         var dq = Quaternion.Inverse(portal.rotation) * q;
    14.  
    15.         //update pos
    16.         var dv = cam.transform.position - portal.position;
    17.         dv = dq * dv;
    18.         this.transform.position = otherPortal.position + dv;
    19.  
    20.         //update rot
    21.         this.transform.rotation = dq * cam.transform.rotation;
    22.  
    23.         //make sure camera projection matches
    24.         this.GetComponent<Camera>().projectionMatrix = cam.projectionMatrix;
    25.     }
    26.  
    27. }
    28.  
    Note that in my code, what portal I associate a camera with is not the camera next to the portal, but rather the camera a portal should have projected on itself.

    So if you have a 'Portal A' that goes to 'Portal B'... the camera for 'Portal A' will be located over by 'Portal B' because 'Portal A' should show what is seen over by 'Portal B'.
     
  9. GreedyCorporationGames

    GreedyCorporationGames

    Joined:
    Apr 20, 2017
    Posts:
    24
    That works! I had to adjust some of the game objects but it is working as intended now.

    Thanks for all your help