How to know if an object is in the angle of range of another object?

First I do apologize since I’m sure that my question is super-easy to solve, but I’m really bad at this math stuff, so if I can ask I would like to receive and answer with more than the lines of code because I want to try to understand what is going on.

So here is my problem

I have a big cannon, when this big cannon shoot I have to simulate the sonic wave (simple simulation and I already have the code for that) to all the soldier near to the cannon in 3 different areas, front, left and right.


This terrible image in paint will show it better. The black cube is the cannon that is facing left in this case, now that cannon shoots and I have to apply the sonic wave to the soldier (I have an array with all the soldiers) but I don’t know how to know where they are, because if they are infront of the cannon red area (between -45° and 45°) they have to get a strong shock wave if they are in the yellow zone a less powerfull shock wave if they are outside of these areas they will not get any shock wave.

Someone can help me?

Thank you.

I’m just writing this from memory so it might be slightly wrong but this is a general way of doing it:

  1. Create 2 vectors to find the angle between. For this example I would create them as 3d vectors but have the Y value be zero.

  2. Normalize the vectors (there are optimisations you can do here by only normalizing one of them but we’ll leave that for now)

  3. Do a cross product between the two 3d vectors (Vector3.Cross( Vec1 , Vec2 ) )

  4. You now have a new cross product vector which will point upwards from the 2 input vectors.

  5. The angle between your 2 initial vectors is the Y component of the new cross product vector (this is in radians so you might want to multiply by Mathf.Rad2Deg to get it in degrees)

Tony

Hi Tony any help is appriciate, sorry can you explain it better? so I create to vector pointing where? in my specifica case I have the Vector3 with the position of the cannon, the Vector3 of each of the soldier and the direction that the cannon it’s facing.

Hi,

If you want to find the angle between the cannon and the soldier you need these two vectors:

  1. Cannon direction vector (in your image above the cannon is facing left so just use -1,0,0 as the vector).

  2. Vector between the cannon and the solider. This is just the SoliderPosition minus the CannonPosition

e.g. in code:

Vector3 CannonPosition = new Vector3( 0 , 0 , 0 );
Vector3 SoliderPosition = new Vector3( 0 , 1 , 0 );
Vector3 CannonDirection = new Vector3( -1 , 0 , 0 );

Vector3 CrossVector1 = CannonDirection;
Vector3 CrossVector2 = SoldierPosition - CannonPosition;

CrossVector1.Normalize();
CrossVector2.Normalize();

Vector3 CrossResult = Vector3.Cross( CrossVector1,CrossVector2 );
float AngleBetween = CrossResult.y * Mathf.Rad2Deg;

Not quite right.

Get your two vectors as already noted and normalize them.

Then take the dot product between the two vectors (not the cross product). Take the arc cos of that value to get the angle (in radians) between the two vectors. This will give you a value between 0 and PI (the smallest angle of the two possible angles between the vectors). Convert to degrees if you want, but better to just do your angle comparisons in radians as well.

The dot product is only useful for calculating the angle between 2 vectors if you don’t need to know the sign. I was assuming the OP was wanting to know the sign so that’s why I was using the cross product method.

Even simpler.

If you have a list of all of your soldiers. When your cannon shoots and a shockwave should play, get the dot product between the forward facing direction of your cannon and the direction towards the soldier (soldier.position - cannon.position)…

Then, if that dot product is less than 0.5, it means the solider is “behind” the cannon. Obviously 0.5 means going past perpindicular so you will need to tweak it to get your 45 degree limit.

And of course there should be a prior check to make sure the solider is actually in an acceptable range around the cannon to actually be selected for a shockwave test.

It also means you could actually use the value of the dot product in the amount of shockwave you apply which is cool. Directly in front of the cannon will have a dot product of 1, so the full effect. Then it will die down all the way until full perpindicular which will be 0.

Thank you guys it’s awesome I’m still understanding how this things work but that is awesome.

If you are able to keep a list of active enemies or enemies in range, this is what I use

//if there are enemies in range, if not we dont care
if(enemiesinrange.Count>0){
//for all enemies in range
        for (int i = 0; i < enemiesinrange.Count; i++) {
            //Get the distance from enemy and player
            float distance = Vector3.Distance(enemiesinrange[i].transform.position,  player.position);
            //in range?
            if (distance <= attackDistance){
//imagine a line shooting straight forward from the player to the enemy in question
                Vector3 targetsRange = enemiesinrange[i].transform.position - player.position;
                //defined angle, imagine 2 lines now, the line above and a line shooting forward out of the player, we want the angle between these two lines
                float angle = Vector3.Angle(targetsRange, player.forward);
                //within angle?
                if (angle <= attackAngle){
                    //it hit, do stuff to the enemy here
                }
            }
        }
    }

Test it:

using UnityEngine;
using System.Collections;
 
public class temp : MonoBehaviour {
 
    public float angleFront = 135f;
    public float angleRight = 45f;
    public float angleLeft = 45f;
    public Transform Enemy;
    public bool front;
    public bool right;
    public bool left;
 
    void Update() {
 
        Vector3 enemyVector = Enemy.position-transform.position;
 
        front = Vector3.Angle( transform.forward,enemyVector) <= angleFront*0.5f;
        right = Vector3.Angle( transform.right  ,enemyVector) <= angleRight*0.5f;
        left  = Vector3.Angle(-transform.right  ,enemyVector) <= angleLeft *0.5f;
 
    } 
 
}

Do not know if it’s 3D or 2D, but all objects must be similarly high. If is 3D an equal or approximate Y axis, and if it is 2D the Z axis.

From image, front angle is approximately 135º and left and right angle 45º.