Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Calculate a new position based using an angle and distance

Discussion in 'Scripting' started by centaurianmudpig, May 18, 2012.

  1. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    Hello,

    I am trying to calculate a position in world space for my AI ship to fly to when avoiding an obstacle. I originally tried to do this using Quaternion.Euler() and not had any success in solving this on unity answers.

    I am now trying to use Mathf.Sin() instead of Quaternion.Euler() but I am not having any success here either. Here is the new code I have tried using Sin(), the above link showed the code for the Euler() attempt.

    Code (csharp):
    1.  
    2.         rot = Vector3.zero;
    3.        
    4.         if (Input.GetKeyUp(KeyCode.DownArrow)) rot.x = -45;
    5.         else if (Input.GetKeyUp(KeyCode.UpArrow)) rot.x = 45;
    6.         else if (Input.GetKeyUp(KeyCode.LeftArrow)) rot.y = -45;
    7.         else if (Input.GetKeyUp(KeyCode.RightArrow)) rot.y = 45;
    8.        
    9.         if (rot != Vector3.zero) {
    10.             Vector3 myEulerAngles = Vector3.zero;
    11.             myEulerAngles = Quaternion.Euler(rot) * -transform.forward;
    12.            
    13.             Vector3 lookToPosition = transform.position;
    14.             lookToPosition.y = (Mathf.Sin( (transform.rotation.eulerAngles.x+rot.x%360) * Mathf.Deg2Rad) * 100000);
    15.             lookToPosition.x = (Mathf.Sin( (transform.rotation.eulerAngles.y+rot.y%360) * Mathf.Deg2Rad) * 100000);
    16.  
    17.             transform.LookAt(lookToPosition);
    18.            
    19.         }
    20.     }
    21.  
    *Should have posted this in Scripting. Mod's please move accordingly.
     
    Last edited: May 18, 2012
  2. George Foot

    George Foot

    Joined:
    Feb 22, 2012
    Posts:
    399
    Replace the whole 'if' block with:

    Code (csharp):
    1.  
    2.     transform.Rotate(rot, Space.World);
    3.  
    Does that do what you want?
     
  3. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    No. I don't want to do anything with the transform. I need to calculate a new position without having to modify the existing transform.

    While I can understand the confusion, the code above has been simplified for what I intend to do. The transform.LookAt() is just there for debugging to check if the new position was calculated correctly.
     
  4. George Foot

    George Foot

    Joined:
    Feb 22, 2012
    Posts:
    399
    The first half of rutter's answer shows how to calculate a point 1m away in space.
     
  5. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    Yeah, I tried that though the rotation still does not work as required when used with LookAt() as suggested.
     
  6. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    Something like this:

     
  7. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    Hi Aubergine, I tried your code and it has the same rotation problem I had with the code I posted on Unity Answers (see link in first post).

    If the object has been rotated to the right or left by 90 degrees it cannot then be rotated up or down.

    Here is the code to rotate the object up/down, based on your snippet:
     
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    You should use;

    Vector3 newPos = transform.position + Quaternion.AngleAxis(rot.x, transform.right) * transform.forward * 100000;
     
  9. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    I corrected the mistake, though it still does not rotate correctly.

    If you would try the below code in a new project, with initial rotation starting at 0,0,0. Use up or down keys to try and rotate all the way round. Then re-start with the initial rotation starting at 0,90,0.
     
  10. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    how was it supposed to rotate? That will rotate an object in local space.

    If you are trying to do yaw-pitch-roll in world space, try these functions: (But there will be gimbal lock)

     
  11. Myx

    Myx

    Joined:
    Nov 29, 2010
    Posts:
    196
    Edit: Ehum, disregard this. I'm not at all describing euler angles, but rather normalized directions. Give me a few minutes and I'll think this through.

    Hello there!

    I'm looking at the code you've posted but I'm honestly a bit unsure about your whole approach.

    Correct me if I'm wrong but you have a start position, an euler angle and a distance? The position you want to reach is then calculated with:

    Code (csharp):
    1.  
    2. Vector3 targetPos = startPos + eulerAngle * distance;
    3.  
    If you want to use your current rotation and rotate according to your euler angle, simply add the two together. Just make sure that both angles are normalized. The result should also be normalized.

    Code (csharp):
    1.  
    2. Vector3 resultEuler = (newEuler.normalized + oldEuler.normalized).normalized;
    3.  
     
    Last edited: May 20, 2012
  12. Myx

    Myx

    Joined:
    Nov 29, 2010
    Posts:
    196
    Right. I've looked over the problem a bit. Since I'm not entirely certain on what convention Unity uses when translating euler angles to direction vectors I'm a bit stumped. The simplest way to get a correct result would therefor be to use the math built in to Unity's transforms.

    Code (csharp):
    1.  
    2. public Vector3 mEuler;
    3. public float mDist;
    4.  
    5. void Awake()
    6. {
    7.     Transform uglySolution = new GameObject().transform;
    8.     uglySolution.rotation = Quaternion.Euler(mEuler);
    9.     Vector3 targetPosition = transform.position + uglySolution.forward * mDist;
    10. }
    11.  
    As you can probably tell from the naming convention this is not a solution I'm very pleased with. It should give you results consistent with those from unity's other math functions, but it's not pretty.
     
    Last edited: May 20, 2012
  13. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    Not quite sure the meaning of your question. My goal is to calculate a new position, intended for an AI ship to fly to. This bit of code is just a test to get the calculation working before implementation. I suppose it would have been more clearer if I added a destination marker instead of rotating a game object.

    I was hoping to stay away from that, though I have to admit that I did not know you could instantiate a Transform like that. It appear's to do what I am looking for and I will try implementing that into my final solution.

    Thanks to both of you for your efforts, this seemingly simple concept has been a pain in my butt for too long!
     
  14. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    Myx, I have been investigating your bit of code and I have an extra request. It appears to not take account of model rotation. My model rotates on all axis in the game world. If I change the rotation on the z axis, i.e. rotated 90 degrees on its side, telling to model to pull up (think a fighter pilot pulling back on a joystick) does not do this.

    I thought it might have been a simple cludge, making the z of the Transform to be the same as the model z axis before calculating the target position, but no luck.
     
    Last edited: May 22, 2012
  15. centaurianmudpig

    centaurianmudpig

    Joined:
    Dec 16, 2011
    Posts:
    92
    I was able to update the position based on the roll using the RotateAround() function on the transform.
     
  16. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    Something like this?
    Code (csharp):
    1.  
    2. // Get a rotation based on input keys
    3. Vector3 rot = Vector3.zero;
    4. if (Input.GetKeyUp(KeyCode.DownArrow)) rot.x = -45;
    5. else if (Input.GetKeyUp(KeyCode.UpArrow)) rot.x = 45;
    6. else if (Input.GetKeyUp(KeyCode.LeftArrow)) rot.y = -45;
    7. else if (Input.GetKeyUp(KeyCode.RightArrow)) rot.y = 45;
    8.  
    9. // change that direction according to the transform
    10. rot = transform.TransformDirection(rot);
    11.  
    12. // conver it to a Quaternion for rotation
    13. Quaternion qrot = Quaternion.Euler(rot);
    14.  
    15. // create a vector from the rotation
    16. Vector3 pos = qrot * new Vector3(0,0,distance) + transform.position;
    17.  
    pos is the position that you would be at, and qrot is the quaternion rotation. facing away from the transform.
     
  17. HarvesteR

    HarvesteR

    Joined:
    May 22, 2009
    Posts:
    530
    A distance and an angle are not enough information to calculate a point in 3D space. You will also need an axis to pivot around. That axis must be normal to the plane along which you want to have your position.

    Then, you can get your vector by doing something like this:

    Vector3 pos = Quaternion.AngleAxis(myAngle, Vector3.up) * Vector3.forward * distance;

    This example assumes that the angle is measured from the north (0°, or Z+), and I'm assuming that your axis is the absolute Y axis, so your position is somewhere along the XZ plane. If not, you'll need to do some more rotations to offset the positioning plane.

    Cheers
     
    xjjon, clwmckenna and Clearline like this.
  18. eidercarlos

    eidercarlos

    Joined:
    May 14, 2014
    Posts:
    9
    Hi Guys!
    I am with this same problem to solve! any true result which works well?
    Has anyone tried the examples above?
    I will be very grateful by any help!
     
    prakyath_unity likes this.
  19. GXMark

    GXMark

    Joined:
    Oct 13, 2012
    Posts:
    514
    Just remember you add pos to the position that you are observing from. So if for example you want to calculate the new position at a defined distance from the camera then you would do

    Vector3 pos = Camera.main.transform.position + Quaternion.AngleAxis(Camera.main.transform.eulerAngles.y, Vector3.up) * Vector3.forward * distance;
     
    SamwiseLA, clwmckenna and mpateck like this.
  20. clwmckenna

    clwmckenna

    Joined:
    Mar 9, 2013
    Posts:
    1
    Harvester and Gxmark, you guys are lifesavers. This solution worked perfectly!