3
votes

I've been struggling with what I think should be a very simple problem:

Diagram of the problem.

I know the current heading angle (say 15 deg), and given a target gameObject's transform, I want to calculate the angle that I should rotate towards to face the target. In the above example I want to calculate say 335ish deg.

Note that I need to calculate the target angle, I have another class that, given an angle, takes care of rotating the heading to the desired angle. I'm aware of the Transform.LookAt() and other similar functions, they don't apply in this situation because reasons (in the other class I basically calculate a Euler Quaternion and Lerp until I reach the target angle, due to project constraints, Transform.LookAt() doesn't work).

In the first approach, I tried calculating angle theta with the Dot product of Vector3.forward and the direction vector, didn't quite work right (either rotated forever or in the wrong direction)

Diagram of the problem

targetAngle = Vector3.Angle(Vector3.forward, (target pos - current pos).normalized);

I thought maybe if I could calculate the current heading direction vector, I could take the Dot product of that and the target direction vector to get angle theta, then use theta and the current angle to figure out the target angle (360 - theta or something?) to get the angle I want to rotate to. Thing is, I only have the current angle and current pos, I don't understand how to calculate the current heading direction vector from that info. Do I just add some arbitrary constant to the current position's Z value and subtract from that the current position, to get a dir vector? Seems hacky and like it shouldn't work.

Diagram of the problem

Any ideas are welcome.

Edit: Additional Info

The orientation code /u/Asad asked about:

    // Calculate the target Quat to rotate all children by
    Quaternion targ = Quaternion.Euler(0, 0, targetAngleHeading);
    // Calculate the Linear interpolation to apply to all children
    Quaternion lerp = Quaternion.Lerp(children[0].transform.localRotation, targ, Time.deltaTime * speedHeading_dps);

    foreach (GameObject c in children)
    {
        // Apply lerp calcualted above to all children
        c.transform.localRotation = lerp;
    }
    // Update the current heading angle 1st child's local z angle
    currentAngleHeading = turrets[0].transform.localEulerAngles.z;

Then in FixedUpdate() I have:

    if (currentAngleHeading != targetAngleHeading)
    {
        DesiredHeading();
    }
2
Is this in 2D? If not, you need a unit vector to indicate your current bearing, not a scalar angle like 15 deg. - Asad Saeeduddin
Also, it would help if you showed what your code does with the angle you're computing. You're correctly computing the angle between (0, 0, 1) and the desired heading. Are you sure your rotation code is also interpreting the angle provided relative to (0, 0, 1)? - Asad Saeeduddin
The comment "didn't quite work right (either rotated forever or in the wrong direction)", along with the evidence of your diagrams, strongly suggests that you have not been careful with your signs. The math you describe should be both correct and almost trivial to implement; about the only thin you can do wrong is to mix up your signs, - Pieter Geerkens
It's 3D, right I can convert from angle to unit vector, but where do I go from there? - Murkantilism
Yea I'm sure the rotation code in the other class works, I wrote another script that used it to ping-pong between two given angles, it works given a desired angle. - Murkantilism

2 Answers

2
votes

You can take your transform's forward, and the vector to your target, and get an angle or rotation from those:

Vector3 vectorToTarget = target.transform.position - transform.position;
Vector3 facingDirection = transform.forward; // just for clarity!

float angleInDegrees = Vector3.Angle(facingDirection, vectorToTarget);
Quaternion rotation = Quaternion.FromToRotation(facingDirection, vectorToTarget);

Note that the rotation is relative; i.e., it's the rotation you need to apply from the current position to be facing the target.

0
votes

try this instead

you can directly take the vector distance vector from transform.position and then vector3.normalize (target.position - object.position)

this is the angle object'll want to move