Add duty free systems and travel stage updates
This commit is contained in:
@@ -1,15 +1,23 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
// 왼쪽 끝으로 이동한 배경을 오른쪽 끝으로 재배치하는 스크립트
|
||||
[ExecuteAlways]
|
||||
public class BackgroundLoop : MonoBehaviour {
|
||||
public Sprite[] backgroundSprites; // 순서대로 교체할 공항 배경 스프라이트
|
||||
public bool useResourceBackground = true; // Resources 폴더의 맵 배경을 자동으로 사용
|
||||
public bool fitToMainCamera = true; // 맵 배경을 카메라 화면 크기에 맞춰 표시
|
||||
public float cameraFitPadding = 1f; // 가장자리 빈틈 방지용 배경 확대 여유
|
||||
public string resourceBackgroundPath = ""; // 맵 데이터가 없을 때 사용할 Resources 배경
|
||||
public int startSpriteIndex = 0; // 이 배경 오브젝트가 시작할 스프라이트 번호
|
||||
public int spriteAdvanceOnLoop = 2; // 배경 오브젝트가 두 장이므로 재배치될 때 두 칸씩 진행
|
||||
|
||||
private static string activeResourceBackgroundPath = "";
|
||||
private static string[] activeResourceBackgroundPaths = new string[0];
|
||||
private static int activeBackgroundLoopCount = 1;
|
||||
private static float activeCameraFitScaleMultiplier = 1f;
|
||||
private static float activeVerticalOffset = 0f;
|
||||
|
||||
private float width; // 배경의 가로 길이
|
||||
private int currentSpriteIndex; // 현재 표시 중인 스프라이트 번호
|
||||
@@ -17,9 +25,24 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
private BoxCollider2D backgroundCollider; // 루프 폭 계산용 콜라이더
|
||||
private Sprite[] originalBackgroundSprites; // 맵 배경 리소스가 없을 때 되돌릴 기본 배경
|
||||
private bool originalBackgroundSpritesCached = false;
|
||||
private Vector3 originalLocalPosition; // 배경 루프를 초기 배치로 되돌릴 때 사용할 위치
|
||||
private Vector3 originalLocalScale = Vector3.one; // 자동 맞춤 해제 시 되돌릴 기본 스케일
|
||||
private bool originalTransformCached = false;
|
||||
|
||||
public static void ApplyResourceBackground(string resourcePath) {
|
||||
activeResourceBackgroundPath = resourcePath;
|
||||
ApplyResourceBackground(string.IsNullOrEmpty(resourcePath)
|
||||
? new string[0]
|
||||
: new string[] { resourcePath });
|
||||
}
|
||||
|
||||
public static void ApplyResourceBackground(string[] resourcePaths) {
|
||||
ApplyResourceBackground(resourcePaths, 1f, 0f);
|
||||
}
|
||||
|
||||
public static void ApplyResourceBackground(string[] resourcePaths, float cameraFitScaleMultiplier, float verticalOffset) {
|
||||
activeResourceBackgroundPaths = NormalizeResourcePaths(resourcePaths);
|
||||
activeCameraFitScaleMultiplier = Mathf.Max(0.1f, cameraFitScaleMultiplier);
|
||||
activeVerticalOffset = verticalOffset;
|
||||
|
||||
BackgroundLoop[] backgroundLoops = FindObjectsByType<BackgroundLoop>(FindObjectsSortMode.None);
|
||||
for(int i = 0; i < backgroundLoops.Length; i++)
|
||||
@@ -29,6 +52,9 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
backgroundLoops[i].InitializeBackground();
|
||||
}
|
||||
}
|
||||
|
||||
AlignLoopPositions(backgroundLoops);
|
||||
AssignSequentialSpriteIndices(backgroundLoops);
|
||||
}
|
||||
|
||||
private void Awake() {
|
||||
@@ -59,10 +85,12 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
private void InitializeBackground() {
|
||||
CacheComponents();
|
||||
CacheOriginalBackgroundSprites();
|
||||
CacheOriginalTransform();
|
||||
EnsureResourceBackground();
|
||||
|
||||
currentSpriteIndex = NormalizeSpriteIndex(startSpriteIndex);
|
||||
ApplyBackgroundSprite(currentSpriteIndex);
|
||||
FitSpriteToCamera();
|
||||
SyncColliderSize();
|
||||
RefreshWidth();
|
||||
}
|
||||
@@ -80,33 +108,92 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
}
|
||||
|
||||
private void EnsureResourceBackground() {
|
||||
if(!useResourceBackground)
|
||||
bool hasActiveResourceBackground = activeResourceBackgroundPaths != null
|
||||
&& activeResourceBackgroundPaths.Length > 0;
|
||||
if(!useResourceBackground && !hasActiveResourceBackground)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string finalResourcePath = !string.IsNullOrEmpty(activeResourceBackgroundPath)
|
||||
? activeResourceBackgroundPath
|
||||
: resourceBackgroundPath;
|
||||
string[] finalResourcePaths = hasActiveResourceBackground
|
||||
? activeResourceBackgroundPaths
|
||||
: NormalizeResourcePaths(string.IsNullOrEmpty(resourceBackgroundPath)
|
||||
? new string[0]
|
||||
: new string[] { resourceBackgroundPath });
|
||||
|
||||
if(string.IsNullOrEmpty(finalResourcePath))
|
||||
if(finalResourcePaths.Length == 0)
|
||||
{
|
||||
backgroundSprites = originalBackgroundSprites;
|
||||
return;
|
||||
}
|
||||
|
||||
Sprite resourceSprite = Resources.Load<Sprite>(finalResourcePath);
|
||||
if(resourceSprite == null)
|
||||
Sprite[] resourceSprites = LoadResourceBackgroundSprites(finalResourcePaths);
|
||||
if(resourceSprites.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(backgroundSprites != null && backgroundSprites.Length == 1 && backgroundSprites[0] == resourceSprite)
|
||||
if(SpriteArraysMatch(backgroundSprites, resourceSprites))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
backgroundSprites = new Sprite[] { resourceSprite };
|
||||
backgroundSprites = resourceSprites;
|
||||
}
|
||||
|
||||
private Sprite[] LoadResourceBackgroundSprites(string[] resourcePaths) {
|
||||
Sprite[] loadedSprites = new Sprite[resourcePaths.Length];
|
||||
int loadedCount = 0;
|
||||
|
||||
for(int i = 0; i < resourcePaths.Length; i++)
|
||||
{
|
||||
Sprite resourceSprite = LoadResourceBackgroundSprite(resourcePaths[i]);
|
||||
if(resourceSprite == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
loadedSprites[loadedCount] = resourceSprite;
|
||||
loadedCount++;
|
||||
}
|
||||
|
||||
if(loadedCount == loadedSprites.Length)
|
||||
{
|
||||
return loadedSprites;
|
||||
}
|
||||
|
||||
Sprite[] compactSprites = new Sprite[loadedCount];
|
||||
for(int i = 0; i < loadedCount; i++)
|
||||
{
|
||||
compactSprites[i] = loadedSprites[i];
|
||||
}
|
||||
|
||||
return compactSprites;
|
||||
}
|
||||
|
||||
private Sprite LoadResourceBackgroundSprite(string resourcePath) {
|
||||
Sprite resourceSprite = Resources.Load<Sprite>(resourcePath);
|
||||
if(resourceSprite != null)
|
||||
{
|
||||
return resourceSprite;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string assetPath = "Assets/Resources/" + resourcePath + ".png";
|
||||
Sprite editorSprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
|
||||
if(editorSprite != null)
|
||||
{
|
||||
return editorSprite;
|
||||
}
|
||||
|
||||
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
|
||||
if(texture != null)
|
||||
{
|
||||
return Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f), 8f);
|
||||
}
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void CacheOriginalBackgroundSprites() {
|
||||
@@ -119,6 +206,17 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
originalBackgroundSpritesCached = true;
|
||||
}
|
||||
|
||||
private void CacheOriginalTransform() {
|
||||
if(originalTransformCached)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
originalLocalPosition = transform.localPosition;
|
||||
originalLocalScale = transform.localScale;
|
||||
originalTransformCached = true;
|
||||
}
|
||||
|
||||
private void RefreshWidth() {
|
||||
if(spriteRenderer != null && spriteRenderer.sprite != null)
|
||||
{
|
||||
@@ -147,13 +245,77 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
backgroundCollider.isTrigger = true;
|
||||
}
|
||||
|
||||
private void FitSpriteToCamera() {
|
||||
if(spriteRenderer == null || spriteRenderer.sprite == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!fitToMainCamera)
|
||||
{
|
||||
transform.localScale = originalLocalScale;
|
||||
ApplyVerticalOffset();
|
||||
return;
|
||||
}
|
||||
|
||||
Camera targetCamera = Camera.main;
|
||||
if(targetCamera == null || !targetCamera.orthographic)
|
||||
{
|
||||
ApplyVerticalOffset();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 spriteSize = spriteRenderer.sprite.bounds.size;
|
||||
if(spriteSize.x <= 0f || spriteSize.y <= 0f)
|
||||
{
|
||||
ApplyVerticalOffset();
|
||||
return;
|
||||
}
|
||||
|
||||
float cameraHeight = targetCamera.orthographicSize * 2f;
|
||||
float cameraWidth = cameraHeight * GetCameraAspect(targetCamera);
|
||||
float parentScaleX = transform.parent != null
|
||||
? Mathf.Abs(transform.parent.lossyScale.x)
|
||||
: 1f;
|
||||
float parentScaleY = transform.parent != null
|
||||
? Mathf.Abs(transform.parent.lossyScale.y)
|
||||
: 1f;
|
||||
float scaleX = cameraWidth / (spriteSize.x * Mathf.Max(parentScaleX, 0.0001f));
|
||||
float scaleY = cameraHeight / (spriteSize.y * Mathf.Max(parentScaleY, 0.0001f));
|
||||
float fitScale = Mathf.Max(scaleX, scaleY)
|
||||
* Mathf.Max(cameraFitPadding, 1f)
|
||||
* activeCameraFitScaleMultiplier;
|
||||
float signX = Mathf.Sign(originalLocalScale.x);
|
||||
float signY = Mathf.Sign(originalLocalScale.y);
|
||||
|
||||
if(Mathf.Approximately(signX, 0f))
|
||||
{
|
||||
signX = 1f;
|
||||
}
|
||||
|
||||
if(Mathf.Approximately(signY, 0f))
|
||||
{
|
||||
signY = 1f;
|
||||
}
|
||||
|
||||
transform.localScale = new Vector3(fitScale * signX, fitScale * signY, originalLocalScale.z);
|
||||
ApplyVerticalOffset();
|
||||
}
|
||||
|
||||
private void ApplyVerticalOffset() {
|
||||
Vector3 localPosition = transform.localPosition;
|
||||
localPosition.y = originalLocalPosition.y + activeVerticalOffset;
|
||||
transform.localPosition = localPosition;
|
||||
}
|
||||
|
||||
// 위치를 리셋하는 메서드
|
||||
private void Reposition() {
|
||||
Vector2 offset = new Vector2(width * 2f, 0);
|
||||
transform.position = (Vector2) transform.position + offset;
|
||||
|
||||
currentSpriteIndex = NormalizeSpriteIndex(currentSpriteIndex + spriteAdvanceOnLoop);
|
||||
currentSpriteIndex = NormalizeSpriteIndex(currentSpriteIndex + GetSpriteAdvanceOnLoop());
|
||||
ApplyBackgroundSprite(currentSpriteIndex);
|
||||
FitSpriteToCamera();
|
||||
SyncColliderSize();
|
||||
RefreshWidth();
|
||||
}
|
||||
@@ -189,4 +351,187 @@ public class BackgroundLoop : MonoBehaviour {
|
||||
spriteRenderer.color = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCurrentSpriteIndex(int index) {
|
||||
currentSpriteIndex = NormalizeSpriteIndex(index);
|
||||
ApplyBackgroundSprite(currentSpriteIndex);
|
||||
FitSpriteToCamera();
|
||||
SyncColliderSize();
|
||||
RefreshWidth();
|
||||
}
|
||||
|
||||
private float GetCurrentWidth() {
|
||||
if(width > 0f)
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
RefreshWidth();
|
||||
return width;
|
||||
}
|
||||
|
||||
private int GetSpriteAdvanceOnLoop() {
|
||||
if(backgroundSprites != null && backgroundSprites.Length > 1 && activeBackgroundLoopCount > 1)
|
||||
{
|
||||
return activeBackgroundLoopCount;
|
||||
}
|
||||
|
||||
return Mathf.Max(1, spriteAdvanceOnLoop);
|
||||
}
|
||||
|
||||
private static float GetCameraAspect(Camera targetCamera) {
|
||||
if(targetCamera.aspect > 0f)
|
||||
{
|
||||
return targetCamera.aspect;
|
||||
}
|
||||
|
||||
if(Screen.height > 0)
|
||||
{
|
||||
return (float) Screen.width / Screen.height;
|
||||
}
|
||||
|
||||
return 16f / 9f;
|
||||
}
|
||||
|
||||
private static string[] NormalizeResourcePaths(string[] resourcePaths) {
|
||||
if(resourcePaths == null || resourcePaths.Length == 0)
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
string[] normalizedPaths = new string[resourcePaths.Length];
|
||||
int pathCount = 0;
|
||||
for(int i = 0; i < resourcePaths.Length; i++)
|
||||
{
|
||||
if(string.IsNullOrEmpty(resourcePaths[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
normalizedPaths[pathCount] = resourcePaths[i];
|
||||
pathCount++;
|
||||
}
|
||||
|
||||
if(pathCount == normalizedPaths.Length)
|
||||
{
|
||||
return normalizedPaths;
|
||||
}
|
||||
|
||||
string[] compactPaths = new string[pathCount];
|
||||
for(int i = 0; i < pathCount; i++)
|
||||
{
|
||||
compactPaths[i] = normalizedPaths[i];
|
||||
}
|
||||
|
||||
return compactPaths;
|
||||
}
|
||||
|
||||
private static bool SpriteArraysMatch(Sprite[] firstSprites, Sprite[] secondSprites) {
|
||||
if(firstSprites == null || secondSprites == null || firstSprites.Length != secondSprites.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i = 0; i < firstSprites.Length; i++)
|
||||
{
|
||||
if(firstSprites[i] != secondSprites[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void AlignLoopPositions(BackgroundLoop[] backgroundLoops) {
|
||||
if(backgroundLoops == null || backgroundLoops.Length <= 1)
|
||||
{
|
||||
activeBackgroundLoopCount = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
int validCount = 0;
|
||||
for(int i = 0; i < backgroundLoops.Length; i++)
|
||||
{
|
||||
if(backgroundLoops[i] != null)
|
||||
{
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(validCount <= 1)
|
||||
{
|
||||
activeBackgroundLoopCount = Mathf.Max(1, validCount);
|
||||
return;
|
||||
}
|
||||
|
||||
activeBackgroundLoopCount = validCount;
|
||||
BackgroundLoop[] sortedLoops = new BackgroundLoop[validCount];
|
||||
int sortedIndex = 0;
|
||||
for(int i = 0; i < backgroundLoops.Length; i++)
|
||||
{
|
||||
if(backgroundLoops[i] != null)
|
||||
{
|
||||
sortedLoops[sortedIndex] = backgroundLoops[i];
|
||||
sortedIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
System.Array.Sort(sortedLoops, (first, second) =>
|
||||
first.originalLocalPosition.x.CompareTo(second.originalLocalPosition.x));
|
||||
|
||||
float loopWidth = sortedLoops[0].GetCurrentWidth();
|
||||
if(loopWidth <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float baseX = sortedLoops[0].originalLocalPosition.x;
|
||||
for(int i = 0; i < sortedLoops.Length; i++)
|
||||
{
|
||||
Vector3 localPosition = sortedLoops[i].originalLocalPosition;
|
||||
localPosition.x = baseX + loopWidth * i;
|
||||
sortedLoops[i].transform.localPosition = localPosition;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssignSequentialSpriteIndices(BackgroundLoop[] backgroundLoops) {
|
||||
if(backgroundLoops == null || backgroundLoops.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int validCount = 0;
|
||||
for(int i = 0; i < backgroundLoops.Length; i++)
|
||||
{
|
||||
if(backgroundLoops[i] != null)
|
||||
{
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(validCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BackgroundLoop[] sortedLoops = new BackgroundLoop[validCount];
|
||||
int sortedIndex = 0;
|
||||
for(int i = 0; i < backgroundLoops.Length; i++)
|
||||
{
|
||||
if(backgroundLoops[i] != null)
|
||||
{
|
||||
sortedLoops[sortedIndex] = backgroundLoops[i];
|
||||
sortedIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
System.Array.Sort(sortedLoops, (first, second) =>
|
||||
first.originalLocalPosition.x.CompareTo(second.originalLocalPosition.x));
|
||||
|
||||
for(int i = 0; i < sortedLoops.Length; i++)
|
||||
{
|
||||
sortedLoops[i].SetCurrentSpriteIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user