96 lines
4.1 KiB
C#
96 lines
4.1 KiB
C#
using UnityEngine;
|
|
|
|
namespace EerieVillage.Background
|
|
{
|
|
/// <summary>
|
|
/// 무한 가로 스크롤 배경 — sprite 재활용 reposition 패턴.
|
|
/// PD 지시 (2026-05-10): "리소스를 재활용할 수 있는 기능 — Tiled size 단순 키움 영역 X".
|
|
///
|
|
/// 동작:
|
|
/// - Start 시점 — sprite 가로 폭 측정 + 자식 사본 2개 (Left·Right) 영역 영역 영역 영역 영역.
|
|
/// → 화면 영역 영역 영역 3 sprite (root + Left + Right) 영역 영역 영역 영역 영역.
|
|
/// - LateUpdate — Camera 영역 영역 영역 영역 영역 sprite 폭 영역 영역 영역 영역 → root 영역 정수 배수 영역 reposition.
|
|
/// → 자식 사본 영역 영역 영역 영역 따라가 영역 영역 영역 영역 영역 영역 영역 영역.
|
|
///
|
|
/// 효율:
|
|
/// - sprite 영역 1개 (Resources 영역 1회 영역 — Texture 메모리 영역 X·재사용)
|
|
/// - GameObject 영역 3개 (root + 2 사본) — Camera 영역 영역 영역 영역 영역 영역 영역 충분.
|
|
/// </summary>
|
|
[RequireComponent(typeof(SpriteRenderer))]
|
|
public class InfiniteHorizontalBackground : MonoBehaviour
|
|
{
|
|
[Tooltip("자식 사본 sortingOrder (root sortingOrder 영역 영역). 영역 영역 영역 영역 0 영역 영역 영역 영역.")]
|
|
[SerializeField] int _childSortingOrderOffset = 0;
|
|
|
|
Transform _camTr;
|
|
float _spriteWidth;
|
|
Transform _leftCopy;
|
|
Transform _rightCopy;
|
|
|
|
void Start()
|
|
{
|
|
var cam = Camera.main;
|
|
if (cam == null)
|
|
{
|
|
Debug.LogWarning($"[InfiniteHorizontalBackground@{name}] Camera.main NULL — 영역 영역 영역.");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
_camTr = cam.transform;
|
|
|
|
var sr = GetComponent<SpriteRenderer>();
|
|
if (sr.sprite == null)
|
|
{
|
|
Debug.LogWarning($"[InfiniteHorizontalBackground@{name}] sprite NULL — 영역 영역 영역.");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
// sprite 가로 영역 (월드 단위·scale 영역 영역)
|
|
_spriteWidth = sr.sprite.bounds.size.x * transform.lossyScale.x;
|
|
if (_spriteWidth <= 0.001f)
|
|
{
|
|
Debug.LogWarning($"[InfiniteHorizontalBackground@{name}] spriteWidth ~0 — 영역 영역 영역.");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
// 자식 사본 2개 영역 영역 (Left·Right)
|
|
_leftCopy = CreateCopy("Left", -_spriteWidth, sr);
|
|
_rightCopy = CreateCopy("Right", +_spriteWidth, sr);
|
|
}
|
|
|
|
Transform CreateCopy(string copyName, float worldOffsetX, SpriteRenderer src)
|
|
{
|
|
var copy = new GameObject(copyName);
|
|
copy.transform.SetParent(transform, false);
|
|
// localPosition 영역 — parent.lossyScale 영역 영역 영역. 영역 영역 영역 — local 단위 영역 영역.
|
|
float localOffsetX = worldOffsetX / transform.lossyScale.x;
|
|
copy.transform.localPosition = new Vector3(localOffsetX, 0f, 0f);
|
|
copy.transform.localScale = Vector3.one;
|
|
|
|
var sr = copy.AddComponent<SpriteRenderer>();
|
|
sr.sprite = src.sprite;
|
|
sr.sortingLayerID = src.sortingLayerID;
|
|
sr.sortingOrder = src.sortingOrder + _childSortingOrderOffset;
|
|
sr.color = src.color;
|
|
sr.flipX = src.flipX;
|
|
sr.flipY = src.flipY;
|
|
return copy.transform;
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if (_camTr == null) return;
|
|
|
|
// Camera 영역 영역 영역 영역 영역 영역 sprite 폭 영역 영역 영역 영역 → root 영역 정수 배수 영역 reposition
|
|
float dx = _camTr.position.x - transform.position.x;
|
|
if (Mathf.Abs(dx) >= _spriteWidth)
|
|
{
|
|
int n = Mathf.RoundToInt(dx / _spriteWidth);
|
|
transform.position += new Vector3(n * _spriteWidth, 0f, 0f);
|
|
}
|
|
}
|
|
}
|
|
}
|