2
votes

I have a player position, a pointer indicating the players view direction, a distance and a horizontal and vertical angle. I want to calculate a target position:

  • that is distance away from the players position
  • that, from the players view direction, is horizontal angle to the right and vertical angle up

It's about positioning a Hololens-Application UI in a sphere around the player. The UI should i.e. be 40 degrees to the leftand 20 degrees up from the players view direction.

Edit: Added image to clarify. Given is the Player Pos (pX|pY|pZ), the radius (= length of the black bold line) and both angles in degree.

I'm looking for how to calculate the UI Center position (x?|y?|z?).

enter image description here

4
the question is why you insist to calculate something by yourself what is already provided by the API. Seems like an XY-Problem than .. StackOverflow is about coding problems. If instead you are more interested in the maths behind it you rather should have asked this on Maths and it would have nothing to do with Unity which you tagged herederHugo
RotateAround() only works if you have a game object with a transform component attached. It works within this use case, since I'm manipulating a gameObject. But in another case, for example if you want to shoot a raycast in the calculated direction, instantiating a gameObject for the purpose of manipulating it's position to calculate the target direction is not the right way. So while I'm very happy with the answer provided by you and CaTs, I've wanted to add the math way for the sake of completeness. I agree, the posted solution is not Unity-specific. But I didn't know that before.Jonas Zimmer
The solution posted by CaTs is exactly that! It calculates the target position. You don't need to aply the calculated position to a transform.. you can use it like you want. Btw every GameObject automatically has a transform component. Even the UI stuff since RectTransform inherits from Transform as wellderHugo
You're completely right! I'm sorry - crunch time. Not much sleep.Jonas Zimmer

4 Answers

2
votes

You can use Quaternion.Euler to create a rotation based on angles in world space and then get the desired result by multiplying it with a known position.

So by using your example you could find the position like this:

float radius, x_rot, y_rot;
Vector3 forwardDirection, playerPos;

Vector3 forwardPosition = playerPos + (forwardDirection * radius);
Vector3 targetPosition = Quaternion.Euler(x_rot, y_rot, 0) * forwardPosition;

Try check out the docs on Quaternion and Quaternion.AngleAxis for more handy rotation stuff.

1
votes
// Set UI in front of player with the same orientation as the player
ui.transform.position = player.transform.position + player.transform.forward * desiredDistance;
ui.transform.rotation = player.transform.rotation;

// turn it to the left on the players up vector around the the player
ui.transform.RotateAround(player.transform.position, player.transform.up, -40);

// Turn it up on the UI's right vector around the player
ui.transform.RotateAround(player.transform.position, ui.transform.right, 20);

assuming you also want the UI to face the player, otherwise you have to set another rotation after this.

No need to calculate it yourself, the Unity API already does it for you ( see Rotate around)

0
votes

If i am understanding you correctly you want to create a UI that hovers above a point. I recently did a similar thing in my game. and this is how i did it.

 if (Input.GetMouseButtonDown(0)) // use the ray cast to get a vector3 of the location your ui      
                                 // you could also do this manualy of have the computer do it the main thing is to 
                                  // get the location in the world where you want your ui to be and the
                                 // WorldTOScreenPoint() will do the rest
        {
            RaycastHit hit;
            Vector3 pos;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit))
            {
                pos = hit.point;
                pos.y += yOffset; // use the offset if you want to have it hover above the point
                ui.transform.position = cam.WorldToScreenPoint(pos); // use your main cammera here              
                // then either make your ui vissible or instanciati it here and make sure if you instanciate it 
                // that you make it a child of your cnavas


            }
        }

I hope this solves you problem. If i am not understanding what you are trying to do let me know and i will try to help.

Note: if you want to make the ui look farther away when you move away from the point scale the ui down as you move farther away, and scale it up when you get closer.

0
votes

Answer by a mathematician:

To calculate the spherical position with the given information (distance between objects, x angle, y angle) you use trigonometry:

float x = distance * Mathf.Cos(yAngle) * Mathf.Sin(xAngle);
float z = distance * Mathf.Cos(yAngle) * Mathf.Cos(xAngle);
float y = distance * Mathf.Sin(yAngle);

ui.transform.position = player.transform.position + new Vector3(x,y,z);