Raycasting

Hey guys! So I have been at this for the better part of today and am totally stumped. Basically I want to check if my Player is facing an enemy. I am attempting to use ray casting to achieve this.

Here is what I have! It actually prints out, but ONLY if I walk into the enemy… so I feel like I am really close to having this working. I believe for some reason my raycastDist is not working properly!

private var raycastDist : float = 100.0;

function Update()
{

     var hit : RaycastHit;
     var fwd = transform.TransformDirection (Vector3.forward);

     if(Physics.Raycast(transform.position, fwd, hit, raycastDist))
     {
          if(hit.collider.gameObject.tag == "Creature")
          {
               print("There is something in front of the Player!");
          }
     }

}

Any thoughts or suggestions would be greatly appreciated! Thanks guys!

Is the script attached to a child object?
What does

Debug.Log(fwd);

print to the console?
Btw, shortcut for the line with TransformDirection

transform.forward

Yep the script is attached to my FirstPersonCharacter which is on the FPSController. I think the issue is related to my tag… I have my ‘Enemy’ object however with several children… I thought giving the tag ‘Creature’ to the parent would give all the children the same tag? But it looks like they are Untagged? Is there a way to tag all of them?

Change the tag on the parent. It will ask you if you want to retag all children too.

Hm… I am not getting this message… :frowning:

Here is my Hierarchy view of the object in question…

http://s29.postimg.org/7wxvtjpl3/enemy_hierarchy.png

I recall in past projects getting this message but for some reason am not right now.

These should tell alot:

Debug.Log(fwd);
Debug.Log(hit.collider.gameObject);
Debug.Log(hit.collider.gameObject.tag);

Use a Debug.DrawRay to visualise it.

If all you need to check is if the enemy is facing the player then just use dot product between the forward vector and the direction from the enemy to the player (requires player transform which is easy to get). Bright side is that its a lot faster (most shaders use dot products all over the place when shading each pixel of their material surface) it avoids using the physics engine (optionally, up and to the point if its actually needed), and it it gives you control on the enemy’s cone of vision.

public class Vision:MonoBehaviour
{
    public Transform target;

    public float coneOfVision; //viewer's peripheral vision
    public float range; //how far away they can see a target

    void Reset()
    {
        coneOfVision = 90; //default extends 45 degress to the left and 45 degress to the right, 90 total
        range = 20; //default can see up to 20 units away
    }

    public bool InView
    {
        get
        {
            if(target==null)
            {
                //target doesn't exist
                return false;
            }

            Vector3 direction =  target.position - transform.position;

            if(direction.magnitude<range)
            {
                // target out of range
                return false;
            }

            //convert cone of vision from human readable to dot threashold
            float threshold = Mathf.Cos(coneOfVision%360 * 0.5f * Mathf.Deg2Rad);

            if(Vector3.Dot(direction,transform.forward) < threshold)
            {
                // returns false if dotproduct is lower value than the threshold (meaning target is outside the cone of vision)
                return false;
            }


            //doesn't take vision obstruction into account, but now that you know its in the cone
            // you can do a simple raytrace if need be
            return true;
        }
    }
}

dot product has so many uses when it comes to calculating facing. many jrpgs use it to determine if an enemy in the world detects the party before they sneak up to ambush. they are also useful for visual triggers (where an event waits til the player looks at something before it triggers)

2 Likes

Awesome! Thanks so much for all the answers guys! Sorry I am just getting to them now I was sleeping!

I was able to get this to work with my code above by simply tagging an invisible sphere to the object as Creature. The issue definitely had something to do with how buried my Creature tag was inside of the actual Enemy objects hierarchy… I still am not sure why that would matter, but maybe Unity was having issues finding the tag. It seems to work perfect now using a simple object! However after all of this, I still am not sure if this is the solution for me, as the Enemy could be on the screen, but not contacting the players raycast, which is not ideal. My plan was to have it so, if the enemy is visually on the screen for the person playing the game, my code can know that.

I think I might give dot product a shot!

Thanks again guys! Your assistance and feedback has been greatly appreciated!

That’s cool, unfortunately you need to know the target for this to work.

Probably a typo in the hurry of writing it, but i guess you meant “greater than”

 if(direction.magnitude>range)

Also, for this scenario I’d strongly recommend to use direction.normalized in the dot product, otherwise you may easily get extremely incorrect values.

Nevertheless, apparently it’s not that much faster than a raycast even if raycasts sound extremly expensive. They almost performed the same in a 100.000 iteration loop. Only with some micro optimizations i could achieve a slightly better performance. (the point with shaders doesn’t count :stuck_out_tongue: GPUs are a totally different world and the dot product exactly fullfills the need there) :stuck_out_tongue:

So it’s really use-case dependant which one you’ll go for (or a mix of both).

1 Like

Additionally, you can use a collider to collect candidates for a visibility test, then a dot product to test if the target is in fov and finally a raycast for an occlusion test.