using System.Collections; using System.Collections.Generic; using UnityEngine; public class BackgroundManager : MonoBehaviour { [System.Serializable] public class BackgroundLayer { public float yThreshold; public Sprite backgroundSprite; public float transitionDistance = 3f; // Distance over which the transition occurs [Range(0f, 1f)] public float parallaxEffect = 0.5f; } [SerializeField] private SpriteRenderer spriteRenderer; [SerializeField] private SpriteRenderer transitionRenderer; // Add this field [SerializeField] private BackgroundLayer[] backgroundLayers; [SerializeField] private Transform playerTransform; // Add this field private bool isTransitioning = false; // Add this field private Transform cameraTransform; private Vector3 lastCameraPosition; private int currentLayerIndex = 0; private float startPositionX; private float lastUpdatePlayerY = 0f; // Track the last Y position of the player private bool isMovingUp = false; // Track if the player is moving up private void Start() { cameraTransform = Camera.main.transform; lastCameraPosition = cameraTransform.position; if (spriteRenderer == null) spriteRenderer = GetComponent(); // Set initial background based on player position if (backgroundLayers != null && backgroundLayers.Length > 0) { float playerY = playerTransform.position.y; int initialLayerIndex = 0; // Find the correct background layer for the player's position for (int i = 0; i < backgroundLayers.Length; i++) { if (playerY > backgroundLayers[i].yThreshold) { initialLayerIndex = i; break; } } spriteRenderer.sprite = backgroundLayers[initialLayerIndex].backgroundSprite; currentLayerIndex = initialLayerIndex; } if (transitionRenderer == null) { var transitionObj = new GameObject("TransitionLayer"); transitionObj.transform.parent = transform; transitionObj.transform.localPosition = new Vector3(0, 0, -2); // Set Z to -2 transitionObj.transform.localScale = Vector3.one; // Match scale transitionRenderer = transitionObj.AddComponent(); transitionRenderer.sortingOrder = spriteRenderer.sortingOrder + 1; transitionRenderer.sortingLayerName = spriteRenderer.sortingLayerName; // Match background layer } transitionRenderer.color = new Color(1, 1, 1, 0); // Start fully transparent } private void Update() { // Calculate parallax movement Vector3 cameraDelta = cameraTransform.position - lastCameraPosition; Vector3 newPosition = transform.position; // Update X position with parallax float parallaxX = (cameraTransform.position.x - startPositionX) * GetCurrentParallaxEffect(); newPosition.x = startPositionX + parallaxX; // Update Y position to follow camera newPosition.y = cameraTransform.position.y; transform.position = newPosition; // Check for background change float currentY = cameraTransform.position.y; int newLayerIndex = currentLayerIndex; for (int i = 0; i < backgroundLayers.Length; i++) { if (currentY > backgroundLayers[i].yThreshold) { newLayerIndex = i; break; } } if (newLayerIndex != currentLayerIndex && !isTransitioning) // Add transition check { StartCoroutine(TransitionBackground(backgroundLayers[newLayerIndex])); currentLayerIndex = newLayerIndex; } lastCameraPosition = cameraTransform.position; float lastUpdatePlayerYRounded = Mathf.Round(lastUpdatePlayerY * 10) / 10; float playerYRounded = Mathf.Round(playerTransform.position.y * 10) / 10; if (lastUpdatePlayerYRounded != playerYRounded) // Check if player has moved { if (lastUpdatePlayerYRounded > playerYRounded) // Check if player is moving down { isMovingUp = false; } else if (lastUpdatePlayerYRounded < playerYRounded) // Check if player is moving up { isMovingUp = true; } lastUpdatePlayerY = playerYRounded; // Update the last Y position } } private float GetCurrentParallaxEffect() { if (backgroundLayers == null || backgroundLayers.Length == 0) return 0.5f; return backgroundLayers[currentLayerIndex].parallaxEffect; } private IEnumerator TransitionBackground(BackgroundLayer newLayer) { // Check if the transition is already in progress or if the new sprite is the same as the current one if (isTransitioning || newLayer.backgroundSprite.name == spriteRenderer.sprite.name) yield break; isTransitioning = true; // Setup transition renderer transitionRenderer.sprite = newLayer.backgroundSprite; transitionRenderer.transform.localPosition = Vector3.zero; bool initialMovingUp = isMovingUp; // Store the initial moving direction float initialY = playerTransform.position.y; //bool movingUp = playerTransform.position.y > initialY; // Fade in new sprite over old one while (true) { float currentY = playerTransform.position.y; // Check if the direction has changed if (initialMovingUp != isMovingUp && ((initialMovingUp ? initialY > currentY : initialY < currentY) )) { transitionRenderer.color = new Color(1, 1, 1, 0); isTransitioning = false; yield break; } // Calculate the alpha based on the distance moved float alpha = Mathf.Abs(currentY - initialY) / newLayer.transitionDistance; transitionRenderer.color = new Color(1, 1, 1, Mathf.Clamp01(alpha)); // Check if transition is complete if (alpha >= 1f) break; yield return null; } // Ensure the final alpha value is set correctly transitionRenderer.color = new Color(1, 1, 1, 1); // Switch the sprites spriteRenderer.sprite = newLayer.backgroundSprite; transitionRenderer.color = new Color(1, 1, 1, 0); isTransitioning = false; } }