- Home /
Check if position is inside area?
Hey guys, I am trying to make a more realistic visual cone for my AI. I think Ive got a reasonable system set up. But I am not sure how I can check if my player is inside the green area (see picture)!
If I know wheter or not the player is inside the green area, the rest is easy to find out!
Here is the code I am using inside OnTriggerStay to find the position of the player and the positions of the cone:
Vector3 dir = o.transform.position - head.position;
float a = Vector3.Angle(dir, transform.forward);
float d = Vector3.Distance(o.transform.position, head.position);
#region Sweetspot Debug
byte fov = (byte)120f; //TODO Make dynamic based on rendertextures cameras fov
float ssmp = 0f;
// float y = 0f; //TODO Store
float r1 = 10; //TODO Make public
float r2 = 16; //TODO Make public
float r3 = 20; //TODO Make public
float x = r3*Mathf.Sin(Mathf.Deg2Rad*(fov/6))/Mathf.Sin(Mathf.Deg2Rad*(180-(fov/3)));
Debug.Log(x);
Debug.DrawRay(transform.position, transform.right*r1, Color.red);
Debug.DrawRay(transform.position, -transform.right*r1, Color.red);
Ray ray0 = new Ray(transform.position, transform.right+transform.forward*Mathf.Rad2Deg/(fov/3));
Ray ray1 = new Ray(transform.position, -transform.right+transform.forward*Mathf.Rad2Deg/(fov/3));
Debug.DrawRay(transform.position, ray0.direction*r3, Color.cyan);
Debug.DrawRay(transform.position, ray1.direction*r3, Color.cyan);
Debug.DrawRay(transform.position, ray0.direction*x, Color.green);
Debug.DrawRay(transform.position, ray1.direction*x, Color.green);
Ray ray4 = new Ray(transform.position, (transform.right/4+transform.forward));
Ray ray5 = new Ray(transform.position, (-transform.right/4+transform.forward));
Ray ray2 = new Ray(transform.position, transform.right+transform.forward*Mathf.Rad2Deg/(fov/2));
Ray ray3 = new Ray(transform.position, -transform.right+transform.forward*Mathf.Rad2Deg/(fov/2));
Debug.DrawRay(transform.position, ray2.direction*r2, Color.yellow);
Debug.DrawRay(transform.position, ray3.direction*r2, Color.yellow);
#region Draw lines
Debug.DrawRay(transform.position, transform.forward*r3, Color.blue);
Debug.DrawRay(transform.position, transform.forward*r2, Color.yellow);
Debug.DrawRay(transform.position, transform.forward*r1, Color.red);
Debug.DrawLine(transform.right*r1, ray2.direction*r1, Color.red);
Debug.DrawLine(-transform.right*r1, ray3.direction*r1, Color.red);
Debug.DrawLine(ray2.direction*r1, ray4.direction*r1, Color.red);
Debug.DrawLine(ray3.direction*r1, ray5.direction*r1, Color.red);
Debug.DrawLine(ray4.direction*r1, transform.forward*r1, Color.red);
Debug.DrawLine(ray5.direction*r1, transform.forward*r1, Color.red);
Debug.DrawLine(ray2.direction*r2, ray4.direction*r2, Color.yellow);
Debug.DrawLine(ray3.direction*r2, ray5.direction*r2, Color.yellow);
Debug.DrawLine(ray4.direction*r2, transform.forward*r2, Color.yellow);
Debug.DrawLine(ray5.direction*r2, transform.forward*r2, Color.yellow);
Debug.DrawLine(ray0.direction*r3, ray4.direction*r3, Color.blue);
Debug.DrawLine(ray1.direction*r3, ray5.direction*r3, Color.blue);
Debug.DrawLine(ray4.direction*r3, transform.forward*r3, Color.blue);
Debug.DrawLine(ray5.direction*r3, transform.forward*r3, Color.blue);
Debug.DrawLine(ray4.direction*r3, ray0.direction*x, Color.green);
Debug.DrawLine(ray5.direction*r3, ray1.direction*x, Color.green);
#endregion
#endregion
Is that green region dynamic? You can probably create a polygon collider and attach it to "eyes" (visual cone :/ ? And use OnTriggerEnter and check tag. Then set a boolean to true. Under OnTriggerExit, set boolean to false.
Though this has been solved, I'd like to add a different method that doesn't involve polygons and triangle intersection tests.
If you're specifically working with cones, you know that an object is in the cone when its angle with the center of the cone is less than some amount. (See the following diagram.)
Here, your cone is green, and the center of the cone is the blue vector. The angle from the edge of your cone to the center is marked by theta (red). To see if an object (magenta dot) is inside the cone, just take the vector from the start of the cone (black dot) to the object, and see if the angle formed by it with the center is greater than theta.
You can then check distance if the cone isn't infinitely long. In this example, you would check if the distance is less than r (brown). The nice thing about this is that you'll get a perfectly circular boundary on the edge of your cone ins$$anonymous$$d of constructing polygons for the edge of your cone.
@$$anonymous$$artik1607 Well the green area doesn't techincally need to be dynamic. But I want the entire thing to be dynamic, so different ais can easily act differently just by changing some variables! So all I need to assign for this is: - $$anonymous$$ax range aka trigger (blue circle) - Second range (yellow circle) - $$anonymous$$in rang (red circle) - FoV of AI
and then the script fills in the blanks :)
@_Gkxd That is some good input. But my script already does that. First it checks if the player is infront of the ai (the red cone), then it checks if the player is inside the yellow cone and then the cyan.
Then it makes some decisions based on that. This post is meant for non-ciruclar vision "cones"... Which means the vision cone isnt really a cone... Confusing :/
Anyways, non-circular vision cones like the green area. Google Game AI Pro or Object Identification Certainty if you wanna know why I am doing this, and why I chose this exact design!
Answer by slimsami · Jul 06, 2015 at 05:58 PM
You can divide your green zone in 3 triangles for example:
triangle 1
transform.position
ray0.direction*x
ray1.direction*x
trangle 2
ray0.direction*x
ray4.direction*r3
ray1.direction*x
triangle 3
ray1.direction*x
ray4.direction*r3
ray5.direction*r3
after that it should be easy there is already a lot of threads that cover the test of a point inside a triangle. This is a copy-paste from an answer found on the web ( thanks to Kornel Kisielewicz) :
float sign (fPoint p1, fPoint p2, fPoint p3)
{
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}
bool PointInTriangle (fPoint pt, fPoint v1, fPoint v2, fPoint v3)
{
bool b1, b2, b3;
b1 = sign(pt, v1, v2) < 0.0f;
b2 = sign(pt, v2, v3) < 0.0f;
b3 = sign(pt, v3, v1) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
Please format all code with 101010 button. This has been done for you.
Thats a much slicker way of doing it. It works great! However if you want this to work in a 3D game, you need to change .y to .z!
Answer by Bioinformatizer · Jul 06, 2015 at 05:22 PM
Create an empty gameObject and make it the child of the AI user.
Put a reference to it in your script with 'public GameObject backWardsCone'.
make a narrower cone from that backWardsCone.transform.position toward the Ai User.
Check to see if the player is in both of these cones, the red one and the backward one.
This is a pretty brute force way of doing what you would like, it may not have the flare you are looking for.
So you want me to place an empty gameObject at, say the point where the blue radius meets the green, and then check the angle from the player to that gameObject?
Ill ins$$anonymous$$d get the angle from said point, lets call it point p, and see if the player is inside both cones! Exactly what you said but without the empty gameObject, as I already have a position!