# EnemyAI rotating on Y-axis in opposite direction

After a battle flag has gone off and the player has entered an enemy's battle zone I want to keep track of the player when it moves and make sure the enemy's Z-axis is always pointing towards the player.

Upon the player entering the battle zone, the enemy automatically marks the player as its target However there is a chance that the Z-axis may not be pointing towards the enemy's target when the battle is first initiated. I decided to shoot a ray cast from the Z-axis of the enemy when the battle flag goes off and rotate the enemy until the ray and the player intersect thus telling me that enemy's Z-Axis is lined up correctly.

the enemy always has a reference to its current target. My idea was that as once the enemy spots its target initially, it can save the position of the most recent spotting and then take the delta of the CurrentTargetPosition.x and the LastSpottingPosition.x If the delta is positive rotate right and if the delta is negative rotate left.

THE ISSUE: my math or logic must be flawed somewhere because although it works sometimes, other times the enemy will randomly rotate itself in the opposite direction and the ray cast will essentially take the long route to hit the player instead of the shortest route as intended. Also the Local Origin of the enemy and the player are at different height respectively but I dont think that should matter in my case Code Below.

//create ray from enemy position orgin and point it on the Z-Axis
Ray ray = new Ray(CurrentEnemyTransform.position, CurrentEnemyTransform.forward);
RaycastHit hit;

if (Physics.Raycast(ray, out hit, 50f))
{
Debug.DrawLine(ray.origin, hit.point);

//ray hits current enemy target
if (hit.transform == CurrentTargetTransform)
{
//check if enemy has seen its target before while in this battle
//or is it the first time
if (enemy.hasTargetLastPosition)
//replace old last seen position with most recent spotting
enemy.ReplaceTargetLastPosition(hit.transform.position);
//or add the first spotting of target while in this battle
}
//ray is not intersectiing with the enemy's current target so rotate to look for it
if (hit.transform != CurrentTargetTransform)
{
//check if enemy has seen its target once before in battle
if (enemy.hasTargetLastPosition)
{
//since last spotting has my target moved more to the left or right?
if (enemy.targetLastPosition.value.x > CurrentTargetTransform.position.x)
{
//rotate right
CurrentEnemyTransform.Rotate(-Vector3.up, 5f, Space.Self);
}
//rotate left
else CurrentEnemyTransform.Rotate(Vector3.up, 5f, Space.Self);
}
//never seen target yet during this battle so default rotation to right till you found it
else CurrentEnemyTransform.Rotate(-Vector3.up, 5f, Space.Self);
}

• I answered, but I can help more if you supply more information. Is this a 2D or 3D problem? Feb 26, 2018 at 15:22
• This is a 3D problem in unity engine Feb 26, 2018 at 19:33

if (enemy.targetLastPosition.value.x > CurrentTargetTransform.position.x)


does not tell you which direction to rotate in. You are just determining whether the player has moved left or right. You need the difference between the angles of the vectors formed between the target and the enemy at the current and last position.

Imagine the following scenarios where E is the enemy and T is target:

    T

E


If T moves in the positive x direction, then E must rotate clockwise.

and

E

T


If T moves in the positive x direction, then E must rotate counterclockwise.

So you can see that dx is not always the same sign as dtheta.

EDIT:

vector1 = CurrentEnemyTransform.forward;
vector2 = normalize(targetPos - enemyPos);


Then you need to rotate from vector1 to vector2 in 3d space. I'm not an expert at Unity, but I believe it works like this...

[get quaternions for vector 1 and 2]

dq = Quaternion.rotateTowards(quat1, quat2, dTheta);

CurrentEnemyTransform.forward = dq * CurrentEnemyTransform.forward;