Tuesday, September 15, 2015

Directional Hit Detection with Dot Products

Note: Before proceeding with this article, please make sure you have a basic understanding of Dot products as I will not be covering them in this post. That may be a topic for a future article. :)

To begin lets say that you have two objects; one doing the shooting and one being shot. We'll call them Gun (Shooting) and Enemy (Being Shot).


Since all of the math will be calculated around the Enemy we'll first need to get the Vector3 from the Enemy to the Gun, which can be done by taking the Enemy's position and subtracting the Gun's position (Enemy.position - Gun.position). We'll call this variable the Direction Vector



Next we'll have to calculate the Dot product of the Direction Vector around the the Enemy's Forward and Right Vectors. Doing so we can get some values which will help determine which 'quadrant' the Direction Vector is in, which can be used as a basic direction. For convenience I usually put these values into a Vector2, the X being the "Front-Back" value and the Y being the "Left-Right" value.


Now to explain what these numbers actually mean; you may have already guessed what they stand for because of my Front-Back-Left-Right names. So if the X (Front-Back) value is positive that means it is pointing in the same direction as the Enemy's forward, thus it is being hit from in front. And if it is negative then the Enemy is being hit from behind. Similarly, the Y (Left-Right) value works the same; with Right being positive and Left being negative.
Finally just compare the absolute value of the two values (X & Y) and the bigger value is the one that is closer to the point of impact on the Enemy.


Following this article should get you to detect collisions on the cardinal directions (Front, Back, Left & Right). However this can also be taken further to provide omni-directional detection by checking the corner cases. It should be noted that this method only works on 2D collisions, as there is no code to check for shots from above or shots from below (however is some cases those could be considered your Front-Back depending on the type of game being coded).
The following will be some example code; it should be noted that I am generalizing a Dot Product and Absolute Value functions so you'll have to make those yourselves, the first parameter for the Dot Function is the Vector we want to Dot towards and the second parameter is the Vector that we're getting from the Gun (the Direction Vector).

---

Vector3 directionVec = Enemy.Position - Gun.Position;
Vector2 dotVec = new Vector2(/*Front-Back Value*/Vec3Dot(Enemy.transform.forward, directionVec),
                                /*Left-Right Value*/Vec3Dot(Enemy.transform.right, directionVec));
//Front-Back value is greater than Left-Right value
if(AbsVal(dotVec.x) > AbsVal(dotVec.y))
{
//Front
if(dotVec.x > 0)
{
//Shot from the Front
}
      //Back
else
{
//Shot from the Back
}
}
//Left-Right value is greater than Front-Back
else
{
//Right
if(dotVec.y > 0)
{
//Shot from the Right
}
//Left
else
{
//Shot from the Left
}
}

No comments:

Post a Comment