diff --git a/Assets/Scenes/Ingame.unity b/Assets/Scenes/Ingame.unity
index 3c99727..d84f587 100644
--- a/Assets/Scenes/Ingame.unity
+++ b/Assets/Scenes/Ingame.unity
@@ -4447,7 +4447,7 @@ PrefabInstance:
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMax.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
@@ -4457,27 +4457,27 @@ PrefabInstance:
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMin.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.x
- value: 0
+ value: 480
objectReference: {fileID: 0}
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.y
- value: 0
+ value: 600
objectReference: {fileID: 0}
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.x
- value: 0
+ value: 750
objectReference: {fileID: 0}
- target: {fileID: 1561733016117246437, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.y
- value: 0
+ value: -300
objectReference: {fileID: 0}
- target: {fileID: 3550758221024711263, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
@@ -4597,7 +4597,7 @@ PrefabInstance:
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMax.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
@@ -4607,27 +4607,27 @@ PrefabInstance:
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMin.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.x
- value: 0
+ value: 480
objectReference: {fileID: 0}
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.y
- value: 0
+ value: 600
objectReference: {fileID: 0}
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.x
- value: 0
+ value: 1260
objectReference: {fileID: 0}
- target: {fileID: 6974954132386231314, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.y
- value: 0
+ value: -300
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
@@ -4637,7 +4637,7 @@ PrefabInstance:
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMax.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
@@ -4647,27 +4647,27 @@ PrefabInstance:
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchorMin.y
- value: 0
+ value: 1
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.x
- value: 0
+ value: 480
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_SizeDelta.y
- value: 0
+ value: 600
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.x
- value: 0
+ value: 240
objectReference: {fileID: 0}
- target: {fileID: 9212598073689065413, guid: 9071d6ddb5d4f854185629ee1970af50,
type: 3}
propertyPath: m_AnchoredPosition.y
- value: 0
+ value: -300
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
@@ -141782,6 +141782,7 @@ GameObject:
m_Component:
- component: {fileID: 1251841319}
- component: {fileID: 1251841318}
+ - component: {fileID: 1251841320}
m_Layer: 0
m_Name: Background_BgImage1
m_TagString: Untagged
@@ -141843,7 +141844,7 @@ SpriteRenderer:
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
- m_DrawMode: 2
+ m_DrawMode: 0
m_Size: {x: 500, y: 7}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
@@ -141859,11 +141860,24 @@ Transform:
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.5, z: 10}
- m_LocalScale: {x: 1, y: 1, z: 1}
+ m_LocalScale: {x: 1.77, y: 1.77, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1251841320
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1251841317}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 4de83d4e43dec1541b816717e1fd2afd, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::EerieVillage.Background.InfiniteHorizontalBackground
+ _childSortingOrderOffset: 0
--- !u!1 &1252911031
GameObject:
m_ObjectHideFlags: 0
diff --git a/Assets/Scripts/Background/InfiniteHorizontalBackground.cs b/Assets/Scripts/Background/InfiniteHorizontalBackground.cs
new file mode 100644
index 0000000..4912de1
--- /dev/null
+++ b/Assets/Scripts/Background/InfiniteHorizontalBackground.cs
@@ -0,0 +1,95 @@
+using UnityEngine;
+
+namespace EerieVillage.Background
+{
+ ///
+ /// 무한 가로 스크롤 배경 — 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 영역 영역 영역 영역 영역 영역 영역 충분.
+ ///
+ [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();
+ 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();
+ 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);
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/Background/InfiniteHorizontalBackground.cs.meta b/Assets/Scripts/Background/InfiniteHorizontalBackground.cs.meta
new file mode 100644
index 0000000..c40b4d2
--- /dev/null
+++ b/Assets/Scripts/Background/InfiniteHorizontalBackground.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 4de83d4e43dec1541b816717e1fd2afd
\ No newline at end of file