using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MoreMountains.Tools
{
///
/// Use this script to have a Transform automatically face a certain direction, whether its own movement direction, or a specific target Transform
///
public class MMFaceDirection : MonoBehaviour
{
/// the possible Updates this script should run at
public enum UpdateModes { Update, LateUpdate, FixedUpdate }
/// the vector to point towards the direction
public enum ForwardVectors { Forward, Up, Right }
/// whether to point at this transform's movement direction, or at a target
public enum FacingModes { MovementDirection, Target }
[Header("Facing Mode")]
/// whether to point at this transform's movement direction, or at a target
public FacingModes FacingMode = FacingModes.MovementDirection;
/// the target to face
[MMEnumCondition("FacingMode", (int) FacingModes.Target)]
public Transform FacingTarget;
/// the minimum distance to consider when computing the movement direction
[MMEnumCondition("FacingMode", (int) FacingModes.MovementDirection)]
public float MinimumMovementThreshold = 0.2f;
[Header("Directions")]
/// the vector to point towards the direction
public ForwardVectors ForwardVector = ForwardVectors.Forward;
/// the angles by which to rotate the direction (in degrees)
public Vector3 DirectionRotationAngles = Vector3.zero;
[Header("Axis Locks")]
public bool LockXAxis = false;
public bool LockYAxis = false;
public bool LockZAxis = false;
[Header("Timing")]
/// the possible Updates this script should run at
public UpdateModes UpdateMode = UpdateModes.LateUpdate;
/// the speed at which to interpolate the rotation
public float InterpolationSpeed = 0.15f;
protected Vector3 _direction;
protected Vector3 _positionLastFrame;
protected Transform _transform;
protected Vector3 _upwards;
protected Vector3 _targetPosition;
///
/// On Awake we initialize our behaviour
///
protected virtual void Awake()
{
Initialization();
}
///
/// Caches upwards vector and transform
///
protected virtual void Initialization()
{
_transform = this.transform;
_positionLastFrame = _transform.position;
switch (ForwardVector)
{
case ForwardVectors.Forward:
_upwards = Vector3.forward;
break;
case ForwardVectors.Up:
_upwards = Vector3.up;
break;
case ForwardVectors.Right:
_upwards = Vector3.right;
break;
}
}
///
/// Computes the direction to face
///
protected virtual void FaceDirection()
{
if (FacingMode == FacingModes.Target)
{
_targetPosition = FacingTarget.position;
if (LockXAxis) { _targetPosition.x = _transform.position.x; }
if (LockYAxis) { _targetPosition.y = _transform.position.y; }
if (LockZAxis) { _targetPosition.z = _transform.position.z; }
_direction = _targetPosition - _transform.position;
_direction = Quaternion.Euler(DirectionRotationAngles.x, DirectionRotationAngles.y, DirectionRotationAngles.z) * _direction;
ApplyRotation();
}
if (FacingMode == FacingModes.MovementDirection)
{
_direction = (_transform.position - _positionLastFrame).normalized;
if (LockXAxis) { _direction.x = 0; }
if (LockYAxis) { _direction.y = 0; }
if (LockZAxis) { _direction.z = 0; }
_direction = Quaternion.Euler(DirectionRotationAngles.x, DirectionRotationAngles.y, DirectionRotationAngles.z) * _direction;
if (Vector3.Distance(_transform.position, _positionLastFrame) > MinimumMovementThreshold)
{
ApplyRotation();
_positionLastFrame = _transform.position;
}
}
}
///
/// Rotates the transform
///
protected virtual void ApplyRotation()
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(_direction, _upwards), InterpolationSpeed * Time.time);
}
///
/// On Update we compute our direction if needed
///
protected virtual void Update()
{
if (UpdateMode == UpdateModes.Update) { FaceDirection(); }
}
///
/// On LateUpdate we compute our direction if needed
///
protected virtual void LateUpdate()
{
if (UpdateMode == UpdateModes.LateUpdate) { FaceDirection(); }
}
///
/// On FixedUpdate we compute our direction if needed
///
protected virtual void FixedUpdate()
{
if (UpdateMode == UpdateModes.FixedUpdate) { FaceDirection(); }
}
}
}