- Home /
How to spawn objects on a restricted sphere surface relative to camera?
Hello everyone,
I'm trying to spawn targets at random positions relative to my camera with certain restrictions, however I'm having plenty of trouble getting the transformations right.
How can I spawn an object at some distance D from my camera with
A random horizontal angle offset from my current orientation between [-hA, hA] where a horizontal offset would correspond to moving the mouse left/right.
A random vertical angle between [-vA, vA] where vertical angle would correspond to moving the mouse up/down.
Thanks, Tom.
Answer by elenzil · May 18, 2016 at 05:43 PM
look up spherical-to-cartesian conversion. it's pretty straight forward.
lmk if you can't find something that works for you.
Thanks elenzil, that helped me arrive at working solution.
This is what I came up with:
private Vector3 generateTargetPosition() {
float currentPhi = 180 - (centerEulerRotationRange(Camera.main.transform.localRotation.eulerAngles.x) + 90);
//radial distance r, polar angle θ (theta), and azimuthal angle φ (phi)
float r = targetDistance;
float theta = Random.Range(-targetRelativeHorizontalFOV/2, targetRelativeHorizontalFOV/2); // Random horizontal angle change relative to facing
float phi = 90 + Random.Range(-targetAbsoluteVerticalFOV/2, targetAbsoluteVerticalFOV/2) + (90 - currentPhi); // Random vertical angle change relative to horizon angle
theta *= $$anonymous$$athf.Deg2Rad;
phi *= $$anonymous$$athf.Deg2Rad;
float x = r * $$anonymous$$athf.Sin (phi) * $$anonymous$$athf.Cos (theta);
float y = r * $$anonymous$$athf.Sin (phi) * $$anonymous$$athf.Sin (theta);
float z = r * $$anonymous$$athf.Cos (phi);
Vector3 targetOffset = new Vector3(y, z, x); // Swap coordinates around to match unity coordinate system
Vector3 targetPosition = Camera.main.transform.TransformPoint(targetOffset);
return targetPosition;
}
// eulerAngles.x ranges from 90 (down) to 0 (forward), 360 (forward) to 270 (up)
// This function transforms the range to -90 to 90
private float centerEulerRotationRange(float ang) {
if (ang >= 0 && ang <= 90) {
return -ang;
} else if (ang >= 270 && ang <= 360) {
return 90 - (ang - 270);
} else {
throw new UnityException("I don't know how eulerAngles work");
}
}
nice! glad you got it working. and looks like you definitely grappled w/ the details.