using Core; using Minigames.Airplane.Data; using UnityEngine; namespace Minigames.Airplane.Interactive { /// /// Parallax element that adjusts position based on camera movement. /// Creates depth illusion by moving at different speeds for different layers. /// Continuously tracks active camera for seamless transitions. /// public class ParallaxElement : MonoBehaviour { [Header("Layer Configuration")] [Tooltip("Which parallax layer this element belongs to")] [SerializeField] private ParallaxLayer layer = ParallaxLayer.Background; [Header("Parallax Settings")] [Tooltip("Global parallax strength multiplier (0 = no parallax, 1 = full)")] [SerializeField] private float globalStrength = 1f; [Tooltip("Per-layer parallax factors (Background/Middle/Foreground)")] [SerializeField] private float backgroundFactor = 0.3f; [SerializeField] private float middleFactor = 0.6f; [SerializeField] private float foregroundFactor = 0.9f; [Header("Debug")] [SerializeField] private bool showDebugLogs; private Transform _cameraTransform; private Vector3 _startPosition; private float _startCameraX; private bool _isInitialized; private void Awake() { // Ensure correct sort layer EnsureSortLayer(); } private void Start() { _startPosition = transform.position; if (_cameraTransform != null) { _startCameraX = _cameraTransform.position.x; _isInitialized = true; } } private void Update() { if (!_isInitialized || _cameraTransform == null) return; ApplyParallax(); } /// /// Set the parallax layer for this element. /// public void SetLayer(ParallaxLayer newLayer) { layer = newLayer; EnsureSortLayer(); if (showDebugLogs) { Logging.Debug($"[ParallaxElement] Layer set to {layer}"); } } /// /// Set the camera transform to track. /// Call this when camera changes. /// public void SetCameraTransform(Transform cameraTransform) { if (cameraTransform == null) return; // If camera changed, recalculate base position if (_cameraTransform != null && _cameraTransform != cameraTransform) { // Smooth transition: current world position becomes new start position _startPosition = transform.position; } _cameraTransform = cameraTransform; _startCameraX = _cameraTransform.position.x; _isInitialized = true; if (showDebugLogs) { Logging.Debug($"[ParallaxElement] Camera set, starting camera X={_startCameraX:F2}"); } } private void ApplyParallax() { // Calculate camera displacement from start float cameraDisplacement = _cameraTransform.position.x - _startCameraX; // Get layer-specific parallax factor float layerFactor = GetLayerFactor(); // Calculate parallax offset (reduced displacement based on layer depth) float parallaxOffset = cameraDisplacement * layerFactor * globalStrength; // Apply offset to start position Vector3 newPosition = _startPosition; newPosition.x += parallaxOffset; transform.position = newPosition; } private float GetLayerFactor() { return layer switch { ParallaxLayer.Background => backgroundFactor, ParallaxLayer.Middle => middleFactor, ParallaxLayer.Foreground => foregroundFactor, _ => 1f }; } private void EnsureSortLayer() { SpriteRenderer spriteRenderer = GetComponentInChildren(); if (spriteRenderer == null) return; // Sort layer is set by spawner, this is just a validation/fallback string expectedLayer = layer switch { ParallaxLayer.Background => "Background", ParallaxLayer.Middle => "Midground", ParallaxLayer.Foreground => "Foreground", _ => "Default" }; if (spriteRenderer.sortingLayerName != expectedLayer) { if (showDebugLogs) { Logging.Debug($"[ParallaxElement] Adjusting sort layer to '{expectedLayer}' for {layer}"); } } } } }