Rotate enemy to make gun point at player.

I have a humanoid enemy, and I want him to shoot at my player with a rifle. My idea to accomplish this was to make the enemy rotate around the y-axis towards my player, and rotate its rifle up and down (the x-axis) towards my player. My enemy’s forward isn’t the same as its rifle’s forward, so I also needed to rotate it in a way where the rifle is pointing the player.

Quaternion relativeRot = Quaternion.Inverse(rifle.rotation) *
                transform.rotation;

            Vector3 desiredLookDirection = player.position - rifle.position;

            Quaternion desiredRotation = Quaternion.LookRotation(desiredLookDirection, transform.up) * relativeRot;

            Vector3 rotationEuler = desiredRotation.eulerAngles;
            rotationEuler.x = 0;
            rotationEuler.z = 0;
            desiredRotation = Quaternion.Euler(rotationEuler);

            transform.rotation = Quaternion.Slerp(transform.rotation, desiredRotation, _rotateSpeed);

            Quaternion rifleRotation = Quaternion.LookRotation(player.position - rifle.position, rifle.up);
            rifle.rotation = Quaternion.Slerp(rifle.rotation, rifleRotation, _rotateSpeed);

That script is attached to my enemy. All of it works fine…until the player jumps over the enemy. Then the rotation gets all weird, with the gun pointing at the player but the enemy is completely flipped around. I think that this is because the enemy is taking the rifle’s rotation into consideration, and somehow the rifle looks at the player before the enemy does. So it counts it as the rifle looking at the player, and stops rotating. But I’m not really sure how I could fix something like this…any help is appreciated!

Used sources: c# - Rotate parent so child looks in a certain direction - Stack Overflow

This was my solution, as applied to a gun turret:

You can leap over it and it will slew around as expected.

Not familiar with the above code, but perhaps it looks unbounded in the vertical angle, so perhaps it is gimbal-locking.

1 Like

Hey again (you’ve answered one of my other forums as well, haha)!

I took a look at your code and messed around with it for a couple of hours. I finally got it to work, and it’s almost perfect! None of my previous problems are coming up, and I like having control over both object’s rotation separately. The only issue that I get is that when the player gets really close to the enemy and is above it, the rifle points slightly away to the side. Maybe you would know why?

            Vector3 DeltaToTarget = player.position - rifle.position;

            float range = Mathf.Sqrt(DeltaToTarget.x * DeltaToTarget.x + DeltaToTarget.z * DeltaToTarget.z);
            float DesiredElevation = Mathf.Atan2(-DeltaToTarget.y, range) * Mathf.Rad2Deg;

            float DesiredTraverse = Mathf.Atan2(DeltaToTarget.x, DeltaToTarget.z) * Mathf.Rad2Deg;
           
            // This is to make the rifle's forward look at the player instead of the enemy's
            float RotationAddition = Vector3.Angle(transform.forward, rifle.forward);

            Quaternion rifleDesiredRotation = Quaternion.Euler(DesiredElevation - 90, 90, 0);
            Quaternion desiredRotation = Quaternion.Euler(0, DesiredTraverse + RotationAddition, 0);

            transform.localRotation = Quaternion.Lerp(transform.localRotation, desiredRotation, _traverseSpeed * Time.deltaTime);
            rifle.localRotation = Quaternion.Lerp(rifle.localRotation, rifleDesiredRotation, _rifleSpeed * Time.deltaTime);

Perhaps the real pivot point of the rifle (or the point the gun is looking at?) isn’t quite where you think it is? That’s about the only thing I can imagine, and at distance it probably is a tiny error, but up close it looks funny. Imagine if I was looking at you across the room, but actually focusing on your shoulder. You wouldn’t notice from across the room, but if you walked up to me and I was looking at your shoulder, it would be pretty obvious.

You can use OnDrawGizmos() to visual points in space in the scene to help debug this. You can just draw tiny little boxes or circles where each of your input Vector3s actually are in space, then when you see the problem, press PAUSE in the editor and study the scene looking for those little markers.

Pretty handy behind the scenes visualizer.

Thanks for the help.
I encountered a bigger issue later on. As my player gets farther, the gun doesn’t continue to stay on target. It starts to drop down until it’s pointing at the ground. It keeps the same rotation, so as player gets farther, it’s not pointing at it anymore. Sorry to ask you again…but any idea why this might be? The code that I have now is the same as above.