Files
Continentis/Assets/OtherPlugins/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs
SoulliesOfficial 9b1b5ca93f initial
2025-10-03 00:02:43 -04:00

195 lines
6.1 KiB
C#

using UnityEngine;
using System.Collections;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this class to a GameObject to make it rotate on itself
/// </summary>
[AddComponentMenu("More Mountains/Tools/Movement/MM Auto Rotate")]
public class MMAutoRotate : MonoBehaviour
{
public enum UpdateModes { Update, LateUpdate, FixedUpdate }
[Header("Rotation")]
/// whether or not this object should be rotating right now
public bool Rotating = true;
[MMCondition("Rotating", true)]
/// the space to apply the rotation in
public Space RotationSpace = Space.Self;
/// whether movement should happen at Update, FixedUpdate or LateUpdate
public UpdateModes UpdateMode = UpdateModes.Update;
[MMCondition("Rotating", true)]
/// The rotation speed. Positive means clockwise, negative means counter clockwise.
public Vector3 RotationSpeed = new Vector3(100f, 0f, 0f);
/// Whether or not the rotation speed should be randomized
public bool RandomizeRotationSpeed = false;
/// the minimum rotation speed to use if RandomizeRotationSpeed is true
[MMCondition("RandomizeRotationSpeed", true)]
public Vector3 RotationSpeedMin = new Vector3(100f, 0f, 0f);
/// the maximum rotation speed to use if RandomizeRotationSpeed is true
[MMCondition("RandomizeRotationSpeed", true)]
public Vector3 RotationSpeedMax = new Vector3(300f, 0f, 0f);
/// an offset, in seconds, to apply before starting the rotation, to allow for a delay
[MMVector("Min", "Max")]
public Vector2 RandomInitialDelay = Vector2.zero;
[Header("Orbit")]
/// if this is true, the object will also move around a pivot (only the position is affected, not the rotation)
public bool Orbiting = false;
[MMCondition("Orbiting", true)]
/// if this is true, the orbit plane will rotate along with the parent
public bool AdditiveOrbitRotation = false;
/// the pivot to rotate around (if left blank, will be the object itself
[MMCondition("Orbiting", true)]
public Transform OrbitCenterTransform;
/// the pivot (relative to the object's position in local space) to rotate around
[MMCondition("Orbiting", true)]
public Vector3 OrbitCenterOffset = Vector3.zero;
/// the axis around which the object should rotate (don't make it zero)
[MMCondition("Orbiting", true)]
public Vector3 OrbitRotationAxis = new Vector3(0f, 1f, 0f);
/// the speed at which to rotate
[MMCondition("Orbiting", true)]
public float OrbitRotationSpeed = 10f;
/// the radius at which to orbit
[MMCondition("Orbiting", true)]
public float OrbitRadius = 3f;
/// the speed at which the object catches up when orbit radius or axis changes
[MMCondition("Orbiting", true)]
public float OrbitCorrectionSpeed = 10f;
[Header("Settings")]
/// if this is true, will draw gizmos to show the plane, orbit and direction
public bool DrawGizmos = true;
[MMCondition("DrawGizmos", true)]
/// the color of the orbit disc
public Color OrbitPlaneColor = new Color(54f, 169f, 225f, 0.02f);
[MMCondition("DrawGizmos", true)]
/// the color of the orbit line
public Color OrbitLineColor = new Color(225f, 225f, 225f, 0.1f);
[HideInInspector]
public Vector3 _orbitCenter;
[HideInInspector]
public Vector3 _worldRotationAxis;
[HideInInspector]
public Plane _rotationPlane;
[HideInInspector]
public Vector3 _snappedPosition;
[HideInInspector]
public Vector3 _radius;
protected Quaternion _newRotation;
protected Vector3 _desiredOrbitPosition;
protected float _initialDelay = 0f;
private Vector3 _previousPosition;
protected float _startTime = 0f;
/// <summary>
/// On start, we initialize our plane
/// </summary>
protected virtual void Start()
{
_rotationPlane = new Plane();
_startTime = Time.time;
_initialDelay = Random.Range(RandomInitialDelay.x, RandomInitialDelay.y);
if (RandomizeRotationSpeed)
{
RotationSpeed = new Vector3(
Random.Range(RotationSpeedMin.x, RotationSpeedMax.x),
Random.Range(RotationSpeedMin.y, RotationSpeedMax.y),
Random.Range(RotationSpeedMin.z, RotationSpeedMax.z));
}
}
/// <summary>
/// Makes the object rotate on its center at Update
/// </summary>
protected virtual void Update()
{
if (Time.time - _startTime < _initialDelay)
{
return;
}
if (UpdateMode == UpdateModes.Update)
{
Rotate();
}
}
/// <summary>
/// Makes the object rotate on its center at FixedUpdate
/// </summary>
protected virtual void FixedUpdate()
{
if (UpdateMode == UpdateModes.FixedUpdate)
{
Rotate();
}
}
/// <summary>
/// Makes the object rotate on its center at LateUpdate
/// </summary>
protected virtual void LateUpdate()
{
if (UpdateMode == UpdateModes.LateUpdate)
{
Rotate();
}
}
/// <summary>
/// Sets Rotating to true or false
/// </summary>
/// <param name="status"></param>
public virtual void Rotate(bool status)
{
Rotating = status;
}
/// <summary>
/// Sets Orbiting to true or false
/// </summary>
/// <param name="status"></param>
public virtual void Orbit(bool status)
{
Orbiting = status;
}
/// <summary>
/// Rotates the object
/// </summary>
protected virtual void Rotate()
{
if (Rotating)
{
transform.Rotate(RotationSpeed * Time.deltaTime, RotationSpace);
}
if (Orbiting)
{
_orbitCenter = OrbitCenterTransform.transform.position + OrbitCenterOffset;
if (AdditiveOrbitRotation)
{
_worldRotationAxis = OrbitCenterTransform.TransformDirection(OrbitRotationAxis);
}
else
{
_worldRotationAxis = OrbitRotationAxis;
}
_rotationPlane.SetNormalAndPosition(_worldRotationAxis.normalized, _orbitCenter);
_snappedPosition = _rotationPlane.ClosestPointOnPlane(this.transform.position);
_radius = OrbitRadius * Vector3.Normalize(_snappedPosition - _orbitCenter);
_newRotation = Quaternion.AngleAxis(OrbitRotationSpeed * Time.deltaTime, _worldRotationAxis);
_desiredOrbitPosition = _orbitCenter + _newRotation * _radius;
this.transform.position = Vector3.Lerp(this.transform.position, _desiredOrbitPosition, OrbitCorrectionSpeed * Time.deltaTime);
_previousPosition = _desiredOrbitPosition;
}
}
}
}