using UnityEngine; using Unity.Cinemachine; namespace EerieVillage.Background { /// /// CinemachineConfiner2D 의 BoundingShape (PolygonCollider2D) 를 배경 SpriteRenderer bounds 정합으로 동적 갱신. /// Camera ortho size · screen aspect 변경 시 자동 정합 — 해상도 동적 처리. /// /// PD 지시 (2026-05-12): /// - 점프 후 카메라 원래 위치 복귀 /// - 카메라가 배경 이미지 벗어나는 지점 표시 X /// - 해상도 고려 동적 판단 /// /// 동작: /// - Update / LateUpdate (Editor·Runtime 동시 호출): 배경 bounds 와 boundShape 의 transform offset 기준으로 PolygonCollider2D points 4개를 단순 사각형으로 갱신. /// - 배경 bounds 또는 boundShape offset 변경 감지 시에만 SetPath + Confiner.InvalidateBoundingShapeCache. /// - Confiner 자체가 Camera ortho · aspect 를 알아서 카메라 보이는 영역이 polygon 안에 머물도록 강제. /// [ExecuteAlways] public class CameraBackgroundLimit : MonoBehaviour { [Tooltip("배경 SpriteRenderer — bounds 가 카메라 한계 기준")] public SpriteRenderer backgroundSprite; [Tooltip("Confiner BoundingShape — PolygonCollider2D")] public PolygonCollider2D boundShape; [Tooltip("CinemachineConfiner2D — InvalidateBoundingShapeCache 호출 대상")] public CinemachineConfiner2D confiner; Vector3 _lastMin; Vector3 _lastMax; Vector3 _lastShapePos; void Update() { UpdateShape(); } void LateUpdate() { UpdateShape(); } void UpdateShape() { if (backgroundSprite == null || boundShape == null) return; var bg = backgroundSprite.bounds; var shapePos = boundShape.transform.position; if (bg.min == _lastMin && bg.max == _lastMax && shapePos == _lastShapePos) return; _lastMin = bg.min; _lastMax = bg.max; _lastShapePos = shapePos; // Polygon points 를 배경 bounds 정합 직사각형으로 갱신 (local space = world - shape.position) float minX = bg.min.x - shapePos.x; float maxX = bg.max.x - shapePos.x; float minY = bg.min.y - shapePos.y; float maxY = bg.max.y - shapePos.y; var pts = new Vector2[] { new Vector2(maxX, maxY), new Vector2(minX, maxY), new Vector2(minX, minY), new Vector2(maxX, minY) }; boundShape.SetPath(0, pts); if (confiner != null) confiner.InvalidateBoundingShapeCache(); } } }