Files
AppleHillsProduction/Assets/Scripts/Minigames/Airplane/Interactive/ParallaxElement.cs

151 lines
5.0 KiB
C#
Raw Normal View History

2025-12-17 12:39:44 +01:00
using Core;
using Minigames.Airplane.Data;
using UnityEngine;
namespace Minigames.Airplane.Interactive
{
/// <summary>
/// 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.
/// </summary>
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();
}
/// <summary>
/// Set the parallax layer for this element.
/// </summary>
public void SetLayer(ParallaxLayer newLayer)
{
layer = newLayer;
EnsureSortLayer();
if (showDebugLogs)
{
Logging.Debug($"[ParallaxElement] Layer set to {layer}");
}
}
/// <summary>
/// Set the camera transform to track.
/// Call this when camera changes.
/// </summary>
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<SpriteRenderer>();
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}");
}
}
}
}
}