105 lines
4.5 KiB
C#
105 lines
4.5 KiB
C#
|
|
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.
|
|||
|
|
/// Configuration is provided by ParallaxBackgroundSpawner at initialization.
|
|||
|
|
/// IMPORTANT: Always calculates position relative to ORIGINAL spawn position and camera,
|
|||
|
|
/// ensuring deterministic behavior during camera blends and switches.
|
|||
|
|
/// </summary>
|
|||
|
|
public class ParallaxElement : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
// Runtime state (set by spawner via Initialize)
|
|||
|
|
private ParallaxLayer _layer;
|
|||
|
|
private float _layerSpeed;
|
|||
|
|
private float _globalStrength;
|
|||
|
|
|
|||
|
|
// Current camera being tracked
|
|||
|
|
private Transform _cameraTransform;
|
|||
|
|
|
|||
|
|
// ORIGINAL spawn state - NEVER reset after initialization
|
|||
|
|
// This ensures objects return to spawn position when camera returns to spawn position
|
|||
|
|
private Vector3 _originalSpawnPosition;
|
|||
|
|
private float _originalCameraX;
|
|||
|
|
|
|||
|
|
private bool _isInitialized;
|
|||
|
|
|
|||
|
|
private void Update()
|
|||
|
|
{
|
|||
|
|
if (!_isInitialized || _cameraTransform == null) return;
|
|||
|
|
|
|||
|
|
ApplyParallax();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Initialize the parallax element with spawner-provided settings.
|
|||
|
|
/// Called by ParallaxBackgroundSpawner when spawning.
|
|||
|
|
/// Sets the ORIGINAL spawn position and camera position - these are never reset.
|
|||
|
|
/// IMPORTANT: Uses Camera.main for tracking to ensure smooth updates during Cinemachine blends.
|
|||
|
|
/// </summary>
|
|||
|
|
public void Initialize(ParallaxLayer layer, float layerSpeed, float globalStrength, Transform cameraTransform)
|
|||
|
|
{
|
|||
|
|
_layer = layer;
|
|||
|
|
_layerSpeed = layerSpeed;
|
|||
|
|
_globalStrength = globalStrength;
|
|||
|
|
|
|||
|
|
// ALWAYS use Camera.main for tracking - this ensures smooth updates during Cinemachine blends
|
|||
|
|
// Virtual cameras don't move during blends, but Camera.main does
|
|||
|
|
_cameraTransform = Camera.main != null ? Camera.main.transform : cameraTransform;
|
|||
|
|
|
|||
|
|
// Store ORIGINAL spawn position - never reset
|
|||
|
|
_originalSpawnPosition = transform.position;
|
|||
|
|
|
|||
|
|
if (_cameraTransform != null)
|
|||
|
|
{
|
|||
|
|
// Store ORIGINAL camera X - never reset
|
|||
|
|
_originalCameraX = _cameraTransform.position.x;
|
|||
|
|
_isInitialized = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Update the camera transform when camera changes.
|
|||
|
|
/// Called by ParallaxBackgroundSpawner when camera switches or blends.
|
|||
|
|
/// ONLY updates the camera reference - does NOT reset start position or camera X.
|
|||
|
|
/// This ensures parallax remains deterministic across camera switches.
|
|||
|
|
/// IMPORTANT: Always uses Camera.main to ensure smooth updates during blends.
|
|||
|
|
/// </summary>
|
|||
|
|
public void UpdateCamera(Transform newCameraTransform)
|
|||
|
|
{
|
|||
|
|
// ALWAYS use Camera.main for tracking - this ensures smooth updates during Cinemachine blends
|
|||
|
|
// We ignore the passed transform and always use Camera.main
|
|||
|
|
Transform mainCamera = Camera.main != null ? Camera.main.transform : newCameraTransform;
|
|||
|
|
|
|||
|
|
if (mainCamera == null) return;
|
|||
|
|
|
|||
|
|
// Simply update the camera reference - do NOT reset positions
|
|||
|
|
// The parallax will continue to calculate relative to original spawn state
|
|||
|
|
_cameraTransform = mainCamera;
|
|||
|
|
_isInitialized = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void ApplyParallax()
|
|||
|
|
{
|
|||
|
|
// Calculate camera displacement from ORIGINAL camera position
|
|||
|
|
// This ensures objects return to spawn position when camera returns to spawn position
|
|||
|
|
float cameraDisplacement = _cameraTransform.position.x - _originalCameraX;
|
|||
|
|
|
|||
|
|
// Calculate parallax offset - negative to move opposite direction
|
|||
|
|
// Lower speed = appears further away (moves less)
|
|||
|
|
// Camera moves right (+) → background moves left (-) at reduced speed
|
|||
|
|
float parallaxOffset = -cameraDisplacement * _layerSpeed * _globalStrength;
|
|||
|
|
|
|||
|
|
// Apply offset to ORIGINAL spawn position
|
|||
|
|
Vector3 newPosition = _originalSpawnPosition;
|
|||
|
|
newPosition.x += parallaxOffset;
|
|||
|
|
transform.position = newPosition;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|