using UnityEngine; // 왼쪽 끝으로 이동한 배경을 오른쪽 끝으로 재배치하는 스크립트 [ExecuteAlways] public class BackgroundLoop : MonoBehaviour { public Sprite[] backgroundSprites; // 순서대로 교체할 공항 배경 스프라이트 public bool useResourceBackground = true; // Resources 폴더의 맵 배경을 자동으로 사용 public string resourceBackgroundPath = ""; // 맵 데이터가 없을 때 사용할 Resources 배경 public int startSpriteIndex = 0; // 이 배경 오브젝트가 시작할 스프라이트 번호 public int spriteAdvanceOnLoop = 2; // 배경 오브젝트가 두 장이므로 재배치될 때 두 칸씩 진행 private static string activeResourceBackgroundPath = ""; private float width; // 배경의 가로 길이 private int currentSpriteIndex; // 현재 표시 중인 스프라이트 번호 private SpriteRenderer spriteRenderer; // 배경을 표시하는 스프라이트 렌더러 private BoxCollider2D backgroundCollider; // 루프 폭 계산용 콜라이더 private Sprite[] originalBackgroundSprites; // 맵 배경 리소스가 없을 때 되돌릴 기본 배경 private bool originalBackgroundSpritesCached = false; public static void ApplyResourceBackground(string resourcePath) { activeResourceBackgroundPath = resourcePath; BackgroundLoop[] backgroundLoops = FindObjectsByType(FindObjectsSortMode.None); for(int i = 0; i < backgroundLoops.Length; i++) { if(backgroundLoops[i] != null) { backgroundLoops[i].InitializeBackground(); } } } private void Awake() { InitializeBackground(); } private void OnEnable() { InitializeBackground(); } private void OnValidate() { InitializeBackground(); } private void Update() { if(!Application.isPlaying) { return; } // 현재 위치가 원점에서 왼쪽으로 width 이상 이동했을때 위치를 리셋 if(transform.position.x <= -width) { Reposition(); } } private void InitializeBackground() { CacheComponents(); CacheOriginalBackgroundSprites(); EnsureResourceBackground(); currentSpriteIndex = NormalizeSpriteIndex(startSpriteIndex); ApplyBackgroundSprite(currentSpriteIndex); SyncColliderSize(); RefreshWidth(); } private void CacheComponents() { if(spriteRenderer == null) { spriteRenderer = GetComponent(); } if(backgroundCollider == null) { backgroundCollider = GetComponent(); } } private void EnsureResourceBackground() { if(!useResourceBackground) { return; } string finalResourcePath = !string.IsNullOrEmpty(activeResourceBackgroundPath) ? activeResourceBackgroundPath : resourceBackgroundPath; if(string.IsNullOrEmpty(finalResourcePath)) { backgroundSprites = originalBackgroundSprites; return; } Sprite resourceSprite = Resources.Load(finalResourcePath); if(resourceSprite == null) { return; } if(backgroundSprites != null && backgroundSprites.Length == 1 && backgroundSprites[0] == resourceSprite) { return; } backgroundSprites = new Sprite[] { resourceSprite }; } private void CacheOriginalBackgroundSprites() { if(originalBackgroundSpritesCached) { return; } originalBackgroundSprites = backgroundSprites; originalBackgroundSpritesCached = true; } private void RefreshWidth() { if(spriteRenderer != null && spriteRenderer.sprite != null) { width = spriteRenderer.bounds.size.x; return; } if(backgroundCollider != null) { width = backgroundCollider.size.x * Mathf.Abs(transform.lossyScale.x); return; } width = 0f; } private void SyncColliderSize() { if(spriteRenderer == null || spriteRenderer.sprite == null || backgroundCollider == null) { return; } Vector2 spriteSize = spriteRenderer.sprite.bounds.size; backgroundCollider.size = spriteSize; backgroundCollider.offset = Vector2.zero; backgroundCollider.isTrigger = true; } // 위치를 리셋하는 메서드 private void Reposition() { Vector2 offset = new Vector2(width * 2f, 0); transform.position = (Vector2) transform.position + offset; currentSpriteIndex = NormalizeSpriteIndex(currentSpriteIndex + spriteAdvanceOnLoop); ApplyBackgroundSprite(currentSpriteIndex); SyncColliderSize(); RefreshWidth(); } private int NormalizeSpriteIndex(int index) { if(backgroundSprites == null || backgroundSprites.Length == 0) { return 0; } int normalizedIndex = index % backgroundSprites.Length; if(normalizedIndex < 0) { normalizedIndex += backgroundSprites.Length; } return normalizedIndex; } private void ApplyBackgroundSprite(int index) { if(spriteRenderer == null || backgroundSprites == null || backgroundSprites.Length == 0) { return; } Sprite backgroundSprite = backgroundSprites[index]; if(backgroundSprite != null) { spriteRenderer.enabled = true; spriteRenderer.sprite = backgroundSprite; spriteRenderer.color = Color.white; } } }