Rotation in Unity

  1. Turret Class:

    • target: A Transform that represents the target that the turret should aim at.

    • _turretAimType: An enum that indicates the turret orientation method to use.

    • _rotationSpeed: The rotation speed of the turret.

  2. Update Method:

    • The Update method is called on each frame and selects the turret orientation method according to the _turretAimType value.

  3. LookAt Method:

    • Uses Unity's LookAt method to make the turret look directly at the target.

  4. LookAtWithQuaternion Method:

    • Uses quaternions to smooth the turret's rotation toward the target.

  5. LookAtWithAtan2 Method:

    • Uses the Mathf.Atan2 function to calculate the angle and then creates a Quaternion rotation to orient the turret toward the target.

  6. LookAtByAngle Method:

    • Orients the turret toward the target through incremental rotations, adjusting the rotation per step according to the angle between the current direction and the direction to the target.

  7. LookAtPerSteps Method:

    • Uses Vector3.RotateTowards to calculate a new direction gradually, so that the turret orients toward the target in steps limited by _rotationSpeed.

  8. TurretAimType Enum:

    • Enumeration that defines the possible turret orientation methods.

In summary, this script provides several ways to make the turret aim at a target in a Unity game, and you can choose the desired orientation method through the _turretAimType enum.

using System;
using UnityEngine;

namespace Turret
{
    public class Turret : MonoBehaviour
    {
        [SerializeField] private Transform target;

        [SerializeField] private TurretAimType _turretAimType;
        [SerializeField] private float _rotationSpeed;

        void Update()
        {
            switch (_turretAimType)
            {
                case TurretAimType.LookAt:
                    LookAt();
                    break;
                case TurretAimType.Atan2:
                    LookAtWithAtan2();
                    break;
                case TurretAimType.Quaternion:
                    LookAtWithQuaternion();
                    break;
                case TurretAimType.Steps:
                    LookAtPerSteps();
                    break;
                case TurretAimType.ByAngle:
                    LookAtByAngle();
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        void LookAt()
        {
            transform.LookAt(target);
        }

       void LookAtWithQuaternion()
        {
            var targetDirection = target.position - transform.position;
            var targetRotation = Quaternion.LookRotation(targetDirection);

            // Calculate rotation toward target with constant speed
            float step = _rotationSpeed * Time.deltaTime;
            transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, step);
        }

        void LookAtWithAtan2()
        {
            Vector3 directionToTarget = target.position - transform.position;

            float targetAngleY = Mathf.Atan2(directionToTarget.x, directionToTarget.z) * Mathf.Rad2Deg;
            Quaternion targetRotation = Quaternion.Euler(0, targetAngleY, 0);

            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, _rotationSpeed * Time.deltaTime);
        }

        void LookAtByAngle()
        {
            var forwardVector = transform.forward;
            var directionToTarget = (target.position - transform.position).normalized;
            var angleToTargetDirection = Vector3.SignedAngle(forwardVector, directionToTarget, transform.up);
            
            
            if (angleToTargetDirection == 0)
            {
                return;
            }
            else if (angleToTargetDirection < -5)
            {
                transform.Rotate(-transform.up, _rotationSpeed * Time.deltaTime);
            }
            else if (angleToTargetDirection > 5f)
            {
                transform.Rotate(transform.up, _rotationSpeed * Time.deltaTime);
            }
        }

        void LookAtPerSteps()
        {
            // Calculate direction toward target
            Vector3 directionToTarget = (target.position - transform.position).normalized;

            // Calculate angle between current direction and direction to target
            float angle = Vector3.Angle(transform.forward, directionToTarget);

            // Calculate allowed rotation in this frame
            float step = _rotationSpeed * Time.deltaTime;

            // If current angle is greater than allowed angle to rotate in this frame
            if (angle > step)
            {
                // Calculate new rotation using RotateTowards
                Vector3 newDirection = Vector3.RotateTowards(transform.forward, directionToTarget, step, 0.0f);

                // Apply rotation to object
                transform.rotation = Quaternion.LookRotation(newDirection);
            }
            else
            {
                // If angle is less than allowed angle, simply look directly at target
                transform.LookAt(target);
            }
        }
    }

    public enum TurretAimType
    {
        LookAt,
        Atan2,
        Quaternion,
        Steps,
        ByAngle
    }
}

Last updated