Hello. I'm using Unity3d to create a simple turret simulation and I have run in to a problem.

I need to find the angle to an object from the turret in 3d space.

Up to this point I thought I could just take the (arc)trig values retrieved from certain perspectives (ie. looking towards the turret from X+ or Y+). Unity uses the left-hand coordinate system, with Y+ being upward and Z+ forward.

However in many tests the turret does not aim directly at the object. I have determined that the problem is the length of my direction vector. After being normalized it is indeed 1 unit in length but this is in 3d space which means that length is longer than comparable 2d vectors (having the same position from an orthographic perspective along an axis). This fact is making all of my inverse trig functions give me incorrect values for this problem.

So my question is:

Can somebody provide me with a mathematical solution and explanation of it (for my own learning)? I can work out the code sure enough I just do not know the mathematics to solve it.

Dani AI

Generated

A compact, robust way is to split the aim into yaw (turn around Y) and pitch (elevation). Let T be the turret pivot and P the target. Form the world-space direction D = P - T, then treat the horizontal (XZ) projection and vertical component separately. This is the same math that Transform.LookAt encapsulates, but shown explicitly so angle issues from 3D normalization become clear.

D = P - T            // (dx, dy, dz)
r = sqrt(dx*dx + dz*dz)    // horizontal distance

// yaw: angle around Y measured from +Z toward +X
// many atan2 implementations use atan2(y, x), so pass (dx, dz)
yaw  = atan2(dx, dz)       

// pitch: elevation above horizontal plane
pitch = atan2(dy, r)       

// convert radians -> degrees when needed:
yawDeg  = yaw  * 180.0 / PI
pitchDeg = pitch * 180.0 / PI

Why this fixes the OP's normalization confusion: scaling a vector by a positive scalar does not change atan2(dx, dz) (the ratio between components is preserved), so normalization alone does not change the computed angles. The misleading comparison comes from comparing a normalized 3D vector to an orthographic 2D projection: a unit 3D vector has horizontal magnitude sqrt(1 - ny*ny), not 1, so directly reading a single component can give the wrong intuition. atan2(dy, r) is numerically stable; asin(dy/|D|) gives the same pitch but is less robust near the domain limits.

Practical notes: compute yaw in world space and apply it to the yaw pivot, then compute pitch in the yaw-pivot local space (or transform D into that local space) before applying the pitch. Clamp pitch to turret limits and handle the r == 0 case (target exactly above/below) explicitly. 's vector-angle pointers align with this derivation. 's θ' = π - θ remark usually signals an orientation/sign convention issue (which axis or order is being measured), not a different underlying formula.

Recommended Answers

All 4 Replies

Crap. I've actually solved this before using trig just thought I could do it again. The code for it is around here somewhere I just haven't looked for it... just decided to use the transform.lookat() function and copy values. Thanks.

So, I was in a similar programm assignement not to long ago, and these 2 links helped out for me. One is to help me understand the solution in the form of vector math, and the other help me verify my answers.

http://www.mathportal.org/calculators/matrices-calculators/vector-calculator.php
https://www.studypug.com/algebra-help/vectors/direction-angle-of-a-vector

I know, tempting to just go and hack at it, until your canon ball start defying the Newton's law and gravity.

turretangle.png

This is physics and has to do, in my opinion, with OOP more or less like physical.
The solution I think is θ' = π - θ because I should have taken PP' instead of P'P.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.