Finding the relationship between two rotations in worldspace

I’ve been wracking my brain over this and I haven’t been able to find a direct answer anywhere. I’m making space dogfighting AI, and I want the ship to know when its target is facing towards it. Not via raycast, but towards with some leeway, for example, a ten degree margin. This way I could have the AI understand something is flying toward it as opposed to away, so that they stop playing chicken, but don’t evade something that they’re tailing.

Hi @Rehtael

Like already mentioned, you could use Vector class Angle method. But it only gives you less information; manual says “The result is never greater than 180 degrees.” so you can’t know exactly what angle that might be.

Vector class also has .Dot method, that returns dot product. Manual says: “For normalized vectors Dot returns 1 if they point in exactly the same direction, -1 if they point in completely opposite directions and zero if the vectors are perpendicular.”

Edit (new content starts here):

I’ll clarify what i meant by using dot based on @Ermiq 's answer. I think usefulness of dot product is more than that. If you just take it as “dot product” of two forward transforms, it doesn’t do anything. I pointed towards above link… which has very nice example, that gives a hint how it should be used.

Here’s how I’ve used it earlier - plug something like this in some script, add it to your enemy for easy testing (so that you can see inspector when you move enemy around player):

playerToEnemy = (enemy.position - player.position).normalized;
enemyToPlayer = enemy.forward.normalized;

Debug.DrawRay(player.position, player.forward * 5f, Color.blue);
Debug.DrawRay(player.position, playerToEnemy * 5f, Color.green);
Debug.DrawRay(enemy.position, enemyToPlayer * 5f, Color.red);

facingDot = Vector3.Dot(player.forward, enemy.forward);
enemyViewConeDot = Vector3.Dot(enemyToPlayer,playerToEnemy);		

seesPlayer = enemyViewConeDot < -0.9f;
fowardsAligned = facingDot > 0f;

So you see, just comparing “facing directions” does it self very little. It just gives the answer that both enemy and player forward directions are either facing each other or not, in the world space.

But what I’m interested in, is the line between player-enemy, and direction of enemy forward.

Enemy forward == enemy view cone.

Player-enemy vector == optimal aim towards player from enemy viewpoint.

With this, “seesPlayer” will be true when enemy has player in front of him.

Depending on the “cone width” (fowardsAligned greater than number) , view cone can be made narrower or wider.

When enemy (imaginary) view cone does not touch player, player is not visible, and even if view cone is very wide, when enemy passes the plane define by player’s local x and y, enemy will stop seeing player.

Edit 2:

This is actually even simpler, just using previously mentioned vectors, but instead of dot, using angle:

enemyToPlayer = (player.position - enemy.position).normalized;
enemyForward = enemy.forward.normalized;

Debug.DrawRay(player.position, player.forward * 5f, Color.blue);
Debug.DrawRay(enemy.position, enemyToPlayer * 5f, Color.green);
Debug.DrawRay(enemy.position, enemyForward * 5f, Color.red);

angle = Vector3.Angle(enemyToPlayer.normalized, enemy.forward);
seesPlayer = angle < viewConeDeg;

Here’s a gif:

123007-20180819-angle-viewcone.gif

Well, both Vector3.Angle and Vector3.Dot options are could be usefull, but the problem is:

With Vector3.Angle you’ll get the same angle for these ships:

        The Angle will be the same
        <-here     and here ->
  0                             0
  /                             /
 
 |                                          |
 0                                          0

With the Vector3.Dot you’ll get the same result for all parallel and for all perpendicular vectors in the scene:

     Both the right and the left will return  
      'isParallel' result from 'Vector3.Dot'
  0                                 0
  |                                 |
  |                                              |
  0                                              0

So, you also need to determine are those two ships have the same (or similar) axis values.

Y axis
|
|      0                                         0
|      /     <-the same position.X               /     <-different position.X & position.Y
|      |       and the angle is 10 degrees                 though the angle is 10 degrees
|      0                                                   |
|                                                          0
|____________________________________________________________________________________X axis

In 3D this going to be a pain to compare coordinates relative to the rotation.

I would try to predict the positions of the ships by their current direction and speed. Say:

// pseudocode
public class Ship {

    void GetNextPosition () {
        myNextPosition = myCurrentPosition + transform.forward * speed;
        // send my next position to the global center of air space control
        Dispatcher.ShipsPositions.FindKey (transform).Value = myNextPosition;
    }
    
    void ChangeTheCourse () {
    // check if the center has my next position and it's not my position
    // so I know that some other ship is going to the same position as I do
    if (Dispatcher.ShipsPositions.TryFindValue (myNextPosition)
         && Dispatcher.ShipsPositions.TryFindValue (myNextPosition).Key != this)
        TurnAway ();
    }
}

public class Dispatcher {
    // global air control center data
    public Dictionary<Transform, Vector3> ShipsPositions;
}

Heyo,

So, here’s my thinking looking at 2D example, maybe like a top-down view of the planes. Let’s say that the circles are the planes and the lines are the direction they are facing:

O
 \

|
O 

Let’s also just put them next to each other so that they take up less space…

O     |
 \    O

So, these to planes are pretty much looking at each other, right? Well, how do we know that? It’s because, like you’re wanting, there is the little view angle (like 15 degrees or something) that they can see in. How might we check what angle they are currently looking at? Well, do this. Grab the forward vector of one of the planes, rotate it by 180 degrees, and check the angle between the two forward vectors. If it is less than or equal to 15, then they are looking at each other.

O     O
 \    |      <--- Check the angle between these vectors

Sooo, that’s an example of it in 2D. And it could be translated to 3D, but 2D was easier to explain. You could also then put a distance check between the two planes to see if they are close enough to be seen. That’s one way to do this (I think). It’s POSSIBLE that there is a flaw in this logic, but I haven’t thought of one. Just firing off an idea to you before I go to sleep hah.