Rotation in Unity
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.
Update Method:
The
Update
method is called on each frame and selects the turret orientation method according to the_turretAimType
value.
LookAt Method:
Uses Unity's
LookAt
method to make the turret look directly at the target.
LookAtWithQuaternion Method:
Uses quaternions to smooth the turret's rotation toward the target.
LookAtWithAtan2 Method:
Uses the
Mathf.Atan2
function to calculate the angle and then creates a Quaternion rotation to orient the turret toward the target.
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.
LookAtPerSteps Method:
Uses
Vector3.RotateTowards
to calculate a new direction gradually, so that the turret orients toward the target in steps limited by_rotationSpeed
.
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