using System; using System.Collections.Generic; using UnityEngine; #if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER using UnityEngine.InputSystem; #endif namespace MoreMountains.Tools { /// /// Use this class to bind a number of UI layers to the movements of a mouse cursor, or a mobile device gyroscope, or even have it be piloted by another script /// By setting different speed/amplitude values for each of your UI layers, you'll be able to create a nice parallax effect /// public class MMParallaxUI : MonoBehaviour { /// /// A class used to store layer settings /// [Serializable] public class ParallaxLayer { /// the rect transform for this layer public RectTransform Rect; /// the speed at which this layer should move public float Speed = 2f; /// the maximum distance this layer can travel from its starting position public float Amplitude = 50f; /// the starting position for this layer [HideInInspector] public Vector2 StartPosition; /// if this is false, this layer won't move public bool Active = true; } /// the possible modes used to pilot this parallax rig public enum Modes { Mouse, Gyroscope, Script } /// the selected mode for this parallax setup. note that gyroscope mode is only available on mobile devices public Modes Mode = Modes.Mouse; /// a multiplier to apply to all layers' amplitudes public float AmplitudeMultiplier = 1f; /// a speed multiplier to apply to all layers' speeds public float SpeedMultiplier = 1f; /// a list of all the layers to pilot public List ParallaxLayers; protected Vector2 _referencePosition; protected Vector3 _newPosition; protected Vector2 _mousePosition; /// /// On Start we initialize our reference position /// protected virtual void Start() { Initialization(); } /// /// Initializes the start position of all layers /// public virtual void Initialization() { foreach (ParallaxLayer layer in ParallaxLayers) { layer.StartPosition = layer.Rect.position; } } /// /// On Update, moves all layers according to the selected mode /// protected virtual void Update() { MoveLayers(); } /// /// Computes the input data according to the selected mode, and moves the layers accordingly /// protected virtual void MoveLayers() { switch (Mode) { case Modes.Gyroscope: _referencePosition = MMGyroscope.CalibratedInputAcceleration; break; case Modes.Mouse: #if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER _mousePosition = Mouse.current.position.ReadValue(); #else _mousePosition = Input.mousePosition; #endif _referencePosition = Camera.main.ScreenToViewportPoint(_mousePosition); break; } foreach (ParallaxLayer layer in ParallaxLayers) { if (layer.Active) { _newPosition.x = Mathf.Lerp(layer.Rect.position.x, layer.StartPosition.x + _referencePosition.x * layer.Amplitude * AmplitudeMultiplier, layer.Speed * SpeedMultiplier * Time.deltaTime); _newPosition.y = Mathf.Lerp(layer.Rect.position.y, layer.StartPosition.y + _referencePosition.y * layer.Amplitude * AmplitudeMultiplier, layer.Speed * SpeedMultiplier * Time.deltaTime); _newPosition.z = 0; layer.Rect.position = _newPosition; } } } /// /// Sets a new reference position, to use when in Script mode /// /// public virtual void SetReferencePosition(Vector3 newReferencePosition) { _referencePosition = newReferencePosition; } } }