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

Axis of moving object changes when camera turns?

Discussion in 'Scripting' started by patrick508, Apr 14, 2017.

  1. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    So i'm creating a AR app with the Google Tango. Players are able to place objects, rotate etc. Dragging the object to change it's positions works but when the player rotates to place an object behind him, it starts acting weird.

    When i start the app, it scans the room. i place an object and everything works perfect. Dragging up, drags the object further away in the Z axis, and dragging down drags it closer. Left and right work as well. However, when i turn around to place a object behind me, left and right still work. but dragging up bring the object closer, and dragging towards me makes the object get further away. So basicly when i turn around the up/down dragging does the opposite.

    Here's my movement code:
    Code (CSharp):
    1.   private float factor = 1f;
    2.  
    3.    private Vector3 v3StartPos;  // Initial position of object
    4.    private Vector3 v3DownPos;   // Initial position of the mouse in world coordinates
    5.    private float fZMap;         // Base Z distance to use in conversion
    6.  
    7.    void OnMouseDown() {
    8.        v3StartPos = transform.localPosition;
    9.        Vector3 v3T = Camera.main.WorldToScreenPoint(v3StartPos);
    10.        fZMap = v3T.z;
    11.        v3DownPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, fZMap);
    12.        v3DownPos = Camera.main.ScreenToWorldPoint(v3DownPos);
    13.    }
    14.  
    15.    void OnMouseDrag() {
    16.        Vector3 v3T = Camera.main.WorldToScreenPoint(v3StartPos);
    17.        fZMap = v3T.z;
    18.        v3T = new Vector3(Input.mousePosition.x, Input.mousePosition.y, fZMap);
    19.        v3T = Camera.main.ScreenToWorldPoint(v3T);
    20.  
    21.        Vector3 v3T2 = v3StartPos;
    22.        v3T2 = v3StartPos;
    23.        v3T2.x = v3T2.x + (v3T.x - v3DownPos.x);
    24.        v3T2.z = v3T2.z + (v3T.y - v3DownPos.y) * factor;
    25.  
    26. #if UNITY_EDITOR
    27.         transform.localPosition = v3T2;
    28. #endif
    29.         if (Input.touchCount == 1) {
    30.             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    31.             RaycastHit hit;
    32.             if (Physics.Raycast(ray, out hit)) {
    33.                 transform.localPosition = v3T2;
    34.             }
    35.         }
    36.     }
    I'm stuck and have been trying things for days now, so any help would be highly appreciated!

    Note: The reason it converts the Y axis to the Z axis is because dragging upwards should move the object on the Z axis. so the Y pos is basicly always 0. The object isnt able to move up. Since it's an app about placing furniture inside your living room (to check how it looks before you buy it) it doesn't need to be able to go up or down on the Y axis.
     
  2. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    No one can help me?
     
  3. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    A sort of simple idea might be to use an unmoving reference GameObject. Modify the furniture or what not, using that object's rotation instead of the player's.
    What do ya think?
     
  4. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    If i understand you correct, you mean always let it face that unmoving object right? Cause that way people can't rotate their object anymore. Or well, they can but it will change as soon as they move the object around.

    right?
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Sorry, I'm trying to think this over. I'm not entirely sure that my previous advice was good / relevant.
    So far, all I can think of is that your objects are probably going the opposite direction because their rotation (or at least that's one way of looking at it)
    I'm not an expert at this, but I wrote a simple drag script, similar to yours but just moving close/far and rotated 1 cube 180 deg around and then up / down movement pushed away/pulled closer.
     
  6. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    No need for a sorry, i appreciate the help. And yea, what happens is, my script converst the Y to Z. so when i drag up (on the Y) it moves in the Z. Nothing special. But what happens is, when i rotate the camera, the dragging behaviour stays the same. Resulting in, if i drag up from my start position it will go up (away from me) on the Z axis. But when i rotate the camera, and drag up. It still gets up from the Z axis, but since i rotated the camera it will than try to move towards me. Sicne dragging up will still add on the Z axis.

    What it think is the best solution is to find a way to check if i rotated the camera, and if i did. Change the behaviour. So when the camera is rotated to -180 dragging up should no longer add the Z axis, but rather go on the - in the Z axis.
    I just have no idea how to do this, hope this makes it a bit more clear and u can help me.
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Yep, that makes perfect sense and was one of the ideas that was also on my mind.
    Did the idea of rotating the objects you drop seem viable to you at all?
    Plus, one thing you never said explicitly, is are there just 2 directions that you can face? 0 and 180 ? Or can you pivot any amount, because then it's a bit more complicated..

    If you have a starting direction, say rotation 0. You could have a simple bool that switches when you turn. Then you could either: A) rotate any objects you drop 180 on Y when turned, and use the original up/down logic that you had.
    or B) according to the bool, inverse the drag logic that you have now for the Z.

    for just 2 directions, either is good (almost the same anyways).
     
  8. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    I dont think it's viable, as than, as i said people would have trouble with rotating the furniture right, since it changes when they move the object. And unfortunately you can pivot any amount you want. As you can decorate your entire room, and look around/walk around all you want. objects stay where they're placed/moved to.

    To give you a better general idea of the app, it's similar to this:

    That's kind off the end result we're going for but better and with our own twist of course.
     
  9. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I get what you mean.. Sorry I couldn't be more help. Good luck with your project :)
     
  10. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    No problem! Thanks for the help and good luck with your future projects! :)

    Hope anyone else can help me
     
  11. robson_depaula

    robson_depaula

    Joined:
    Sep 30, 2014
    Posts:
    37
    Hello @patrick508 I had a similar problem regarding the Z axis when rotating the Tango Device to look at what was behind it's initial position.

    In my case I had to check for this inversion, and compensate:

    Code (CSharp):
    1. zOffset = _cameraTrans.forward.z * Z_FACTOR;
    2.  
    3.         if (_camera.transform.rotation.eulerAngles.y < -90.0f || (_camera.transform.rotation.eulerAngles.y > 90.0f && _camera.transform.rotation.eulerAngles.y < 270.0f))
    4.         {
    5.             zOffset = -1.0f * zOffset;
    6.         }
    Hope it might give you some clue.
     
  12. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    Hi robson, first of all thanks for replying! Second, i cant really find a way to implement that in my code to test it. Perhaps i'm overlooking something? Or maybe you can give me a push in the right direction. Would appreciate it.
     
  13. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    968
    Code (csharp):
    1.  
    2. // Get the cameras forward direction, limited to the plane
    3. Vector3 camFwd = Vector3.ProjectOnPlane(Camera.main.forward).normalized;
    4. // Calculate the dot product with the forward vector
    5. float dot = Vector3.Dot(Vector3.forward, camFwd);
    6. // Use the dot product to determine direction
    7. if (dot >= 0f) {
    8.     MoveThisWay();
    9. } else {
    10.     MoveThatWay();
    11. }
    12.  
     
  14. robson_depaula

    robson_depaula

    Joined:
    Sep 30, 2014
    Posts:
    37
    Hi @patrick508, I took another look at you code and maybe (big maybe) what you overlooked is that during your OnMouseDrag you'll have the opportunity to check the angles and see if the device rotated to face it's rear (in comparison to when the app started).

    Sorry for not being specific to your scenario, try to experiment with something like the code below:
    Code (CSharp):
    1. // your code
    2. private Camera _camera;
    3. private Transform _cameraTrans;
    4.  
    5. void Start()
    6. {
    7.     _camera = Camera.main; // if more than one camera in the scene, make sure this is the 'Tango Camera'
    8.     _cameraTrans = _camera.transform;
    9. }
    10.  
    11. void OnMouseDown()
    12. {
    13.     //your code, but now check if the device is inverted from where it started
    14.     if (_cameraTrans.rotation.eulerAngles.y < -90.0f || (_cameraTrans.rotation.eulerAngles.y > 90.0f && _cameraTrans.rotation.eulerAngles.y < 270.0f))
    15.     {
    16.         // maybe you need to invert your calculations, mine was like below
    17.         // zOffset = -1.0f * zOffset;
    18.     }
    19. }
    20.  
    21. void OnMouseDrag()
    22. {
    23.      //your code, but now check if the device is inverted from where it started
    24.     if (_cameraTrans.rotation.eulerAngles.y < -90.0f || (_cameraTrans.rotation.eulerAngles.y > 90.0f && _cameraTrans.rotation.eulerAngles.y < 270.0f))
    25.     {
    26.         // maybe you need to invert your calculations, mine was like below
    27.         // zOffset = -1.0f * zOffset;
    28.     }
    29. }
     
  15. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    I've been messing around with your code and some own idea's. Unfortunately not the results i was looking for. I've tried out a bunch of things. The thing that worked almost as wanted i guess is doing your suggestion but than with the Z axis. Like so:
    I added that just above the movement part in OnMouseDrag();
    The answer is probably right in front of me but i'm just staring myself to death on the code atm.
     
  16. robson_depaula

    robson_depaula

    Joined:
    Sep 30, 2014
    Posts:
    37
    Hmmm, hard to guess at the distance. Try to break the problem into smaller ones an test.

    Anyway, maybe the answer is not just inverting the Z axis like you showed above but maybe work on the math that you are doing:
    Code (CSharp):
    1. if (_cameraTrans.rotation.eulerAngles.y < -90.0f || (_cameraTrans.rotation.eulerAngles.y > 90.0f && _cameraTrans.rotation.eulerAngles.y < 270.0f))
    2. {
    3.      v3T2.z = v3T2.z - (v3T.y - v3DownPos.y) * factor;
    4. }
    5. else
    6. {
    7.     v3T2.z = v3T2.z + (v3T.y - v3DownPos.y) * factor;  
    8. }
     
  17. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    Your example actually almost works! When standing on start position (0 degrees) it works fine, and when rotating 180 degrees it works fine as well! But inbetween those numbers it's acting weird (dragging sideways when touching up)

    It's an improvement tho. I think the main problem is since you can walk and rotate around freely you have a lot of different situations.

    Thanks a lot for helping me by the way, appreciate the kindness :)
     
  18. robson_depaula

    robson_depaula

    Joined:
    Sep 30, 2014
    Posts:
    37
  19. Qwoxx

    Qwoxx

    Joined:
    May 9, 2017
    Posts:
    2
    Do i understand you right, you want to drag up and move the object away from the camera independent of it's rotation?

    If this is the case, isn't:

    Code (CSharp):
    1. Vector3 dir;
    2.  
    3. dir.x = cos(camAngle) - sin(camAngle);
    4. dir.z = sin(camAngle) - cos(camAngle);
    dir = direction vector to move the object?

    Maybe you need atan2(camDir.x, camDir.z) to get the cam angle between -180 and 180.

    I may be totally wrong here, I'm on mobile and can't test it. It's just what was on my mind.
     
  20. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    Euler angles are almost never the answer. This sounds like the cause of your weirdness with the suggested code. You should read the linked article, but the short version of it in this case would be that the Y component of Euler angles is nearly meaningless without considering the other two components as well. If you want to check for inversion, use transform.up < 0f instead of checking Euler angles.

    If I understand the original problem correctly, I think you probably want to make a new rotation by which you modify your "user is dragging in this direction" vector. The easiest way to do that is to simply "multiply" the rotation by the vector. (It's not really multiplying, but it uses the * operator.) But just using camera.transform.rotation would send it through the floor if you drag forward, so you can't do that. If that's an accurate way to phrase the problem, then it can be solved by created a "flattened" rotation.

    This code assumes that dragMovedThisFrame is a Vector2 with X,Y being how much the user dragged the mouse/touch this frame.
    Code (csharp):
    1. Vector3 flatForward = _cameraTrans.forward;
    2. flatForward.y = 0f;
    3. Quaternion flatLookRot = Quaternion.LookRotation(flatForward);
    4. Vector3 flattenedDragVector = new Vector3(dragMovedThisFrame.x, 0f, dragMovedThisFrame.y);
    5. Vector3 moveObjectVector = flatLookRot * flattenedDragVector;
    Hope this helps.
     
  21. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    First of all, thanks for the detailed answer, I've read through your article and that seems to make sense.
    However i have no clue about how to implement your given code, or experiment with it.
     
  22. patrick508

    patrick508

    Joined:
    May 21, 2015
    Posts:
    40
    Independent of the camera's(the player in this case) rotation yes.