Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411467 Posts in 69368 Topics- by 58422 Members - Latest Member: daffodil_dev

April 22, 2024, 09:29:46 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Detecting what direction an object is relative to another object?
Pages: [1]
Print
Author Topic: Detecting what direction an object is relative to another object?  (Read 1036 times)
Lycaon
Guest
« on: September 16, 2014, 05:14:38 PM »

For the record, I'm using Unity and C#.

So, apologies if I don't explain this well. I have an object (an enemy), and I need to be able to tell when the player is in one of eight directions (front, back, left, right, but also the diagonals).

Basically, I'm doing a DOOM-style sprite-based 3D effect, so I need to change what animations the monsters are using depending on how the player is looking at them.

How should I go about this?

Logged
jgrams
Level 3
***



View Profile
« Reply #1 on: September 16, 2014, 06:00:12 PM »

Something like:

Code:
(atan2(x, y) + PI/8) % (PI/4)

This should give you an octant (0 through 7, or -3 through 4? it's late and I don't remember the range of atan2). atan2 gives you the angle in radians, given x, y (or x, z? whichever way your floor goes). Take the remainder from dividing by PI/4 (45 degrees, one-eighth of a circle) to get the octant, except you want to shift it by half that (PI/8 radians or 22.5 degrees) first so that it rounds properly.

Hope that helps...
Logged
JakobProgsch
Level 1
*



View Profile
« Reply #2 on: September 17, 2014, 06:23:19 AM »

Urgh, why use angles (for anything really, they are evil).

If you take the difference of the positions then you can just "look at the components". The sign of the x and y differences instantly tell you left, right, up and down. To tell if something is on a diagonal you can look at something like abs(min/max) > tan(pi/8). And since that tan is of a constant you don't actually have to compute it in code...

Logged

jgrams
Level 3
***



View Profile
« Reply #3 on: September 17, 2014, 08:07:58 AM »

Because I think what the OP is looking for is an angle (an integer-valued angle in a system of units where 8 units is a full turn)?

I thought about mentioning the "look at the components" approach, but it's messy and I think it expresses the intent poorly. I could definitely see taking a vector approach if you wanted the unit vector in the nearest of the eight directions, to avoid converting from a vector to an angle and then immediately back. But in this case I don't think it makes sense.

Both approaches are discussed a bit in this SE question:
http://gamedev.stackexchange.com/questions/49290/whats-the-best-way-of-translating-a-2d-vector-into-the-closest-8-way-compass-di
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #4 on: September 17, 2014, 11:15:29 AM »

atan2 works fine, but for the hell of it I tried doing it as neatly as possible without angles.

Code:
s = 0.3826834324
c = 0.9238795325
t1 = c*x+s*y
t2 = -s*x+c*y
q1 = t1 > 0
q2 = t2 > 0
d = (q1 ? 4 : 0) + (q1 ^ q2 ? 2 : 0) + (q1 ^ q2 ^ (abs(t1) > abs(t2)) ? 1 : 0)
Logged
Lycaon
Guest
« Reply #5 on: September 17, 2014, 12:35:48 PM »

Something like:

Code:
(atan2(x, y) + PI/8) % (PI/4)

This should give you an octant (0 through 7, or -3 through 4? it's late and I don't remember the range of atan2). atan2 gives you the angle in radians, given x, y (or x, z? whichever way your floor goes). Take the remainder from dividing by PI/4 (45 degrees, one-eighth of a circle) to get the octant, except you want to shift it by half that (PI/8 radians or 22.5 degrees) first so that it rounds properly.

Hope that helps...

Thanks. I've never used atan2 before, but it's only returning numbers less than one and greater than negative one. I'm feeding it the player's x and z coordinates converted to the enemy's local spaaaaaace. Is this supposed to happen?

Code:
		relativePoint = transform.parent.InverseTransformPoint(player.position);

octant = (Mathf.Atan2(relativePoint.x, relativePoint.z) + Mathf.PI/8) % (Mathf.PI/4);
Logged
jgrams
Level 3
***



View Profile
« Reply #6 on: September 17, 2014, 12:47:54 PM »

@BorisTheBrave: Sweeeet!

@Lycaon: gah, I'm sorry, I did totally screw that up. Should be divide and round, not mod. Try the math from the stackexchange post:

Code:
octant = round(8 * atan2(x, z) / (2*PI) + 8) % 8
Logged
Lycaon
Guest
« Reply #7 on: September 17, 2014, 01:34:01 PM »

@BorisTheBrave: Sweeeet!

@Lycaon: gah, I'm sorry, I did totally screw that up. Should be divide and round, not mod. Try the math from the stackexchange post:

Code:
octant = round(8 * atan2(x, z) / (2*PI) + 8) % 8

Thanks much! That works perfectly.
Logged
gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #8 on: September 23, 2014, 10:38:10 AM »

another way, since it's unity is to do teh dot product of the transform.forward with the forward and right vector of the target vector.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic