using UnityEngine; using System.Collections; namespace MoreMountains.Tools { /// /// Add this class to a GameObject to make it rotate on itself /// [AddComponentMenu("More Mountains/Tools/Movement/MMAutoRotate")] 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); [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; private Vector3 _previousPosition; /// /// On start, we initialize our plane /// protected virtual void Start() { _rotationPlane = new Plane(); } /// /// Makes the object rotate on its center at Update /// protected virtual void Update() { if (UpdateMode == UpdateModes.Update) { Rotate(); } } /// /// Makes the object rotate on its center at FixedUpdate /// protected virtual void FixedUpdate() { if (UpdateMode == UpdateModes.FixedUpdate) { Rotate(); } } /// /// Makes the object rotate on its center at LateUpdate /// protected virtual void LateUpdate() { if (UpdateMode == UpdateModes.LateUpdate) { Rotate(); } } /// /// Sets Rotating to true or false /// /// public virtual void Rotate(bool status) { Rotating = status; } /// /// Sets Orbiting to true or false /// /// public virtual void Orbit(bool status) { Orbiting = status; } /// /// Rotates the object /// 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; } } } }