Checking if a Transform is behind another Transform in Unity3d

The title is a bit misleading, because what I’m actually trying to figure out today is if a Transform sees another one from behind. The reason why I used this title is because I saw a lot of people asking questions formulated like the topic of this entry when they were actually trying to find a way to check if their game characters saw the backs of their opponents. The most popular SO / Unity forum answers only mentioned the Vector3.Dot method which is insufficient in this case.

With that out of the picture, let’s dive in and define what it means to “see from behind”. First off, if an object can see another one from behind, the Vector3.Dot will return something close to 1, as the docs say: https://docs.unity3d.com/ScriptReference/Vector3.Dot.html . The second thing is the “see” part. In order to see an object, there have to be no obstacles in between you and the object – it works in Unity as well as in real life 🙂 Luckily Unity framework has the method we’re looking for and its name is Physics.Raycast. Summing the algorithm up:

  1. Check the angle between transforms using the Vector3.Dot function.
  2. Check if there’s an unobstructed path from the Transform to the target using Physics.Raycast
  3. That’s it! 🙂

Implementation below (this time I’m not uploading it to github, as it’s only one method that you can just copy and paste from here if needed):

public static bool SeesBehind(this Transform transform, Transform other, float range) {
    var direction = (other.position - transform.position).normalized;
    var dot = Vector3.Dot(direction, transform.forward);

    if (dot < .8f) {
        return false;
    }

    var adjustedPosition = transform.position + Vector3.up;
    RaycastHit hitInfo;
    var raycastHasHit = Physics.Raycast(
        adjustedPosition,
        (other.position - adjustedPosition).normalized,
        out hitInfo,
        100);
    var hitCheckPasses = raycastHasHit && hitInfo.collider.transform == other;

    return hitCheckPasses;
}

There are two important things to be aware of in this code. The first one is the dot product check. If the dot variable holds a value lower than 0.8, then we still may be behind the targeted object, but not looking in its direction. In your case you may want to make that threshold a bit bigger. The second one is the adjustedPosition variable. In my project I had a transform that was anchored at the bottom, so doing a raycast from there very often returned false because it was hitting the plane. I figured that I may move the origin point to the spot where my characters have their eyes.

And that’s it! I hope some of you will find this helpful 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s