Projext/Assets/Editor/BossHealthBarCreator.cs
hydrozen e989d20668 카툰 쉐이더 추가 + 중복 스크립트 수정 + 전체 업데이트
- ToonPostProcess.shader: 횃불 고딕 스타일 후처리 쉐이더 (Built-in RP)
- ToonCameraEffect.cs: 카메라 자동 부착 후처리 스크립트
- 중복 UI 스크립트 제거 (MenuIntroController, ToggleCustom)
- 씬, 프리팹, 애니메이션 등 전체 업데이트

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:31:16 +09:00

335 lines
31 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine; // 임포트할거에요 -> Unity 엔진 기본 기능을
using UnityEngine.UI; // 임포트할거에요 -> Unity UI 시스템을
using UnityEditor; // 임포트할거에요 -> Unity 에디터 전용 기능을
using TMPro; // 임포트할거에요 -> TextMeshPro를
// ══════════════════════════════════════════════════════════════════════
// BossHealthBarCreator — 에디터 유틸리티 (다크 판타지 스타일)
//
// 디자인 레퍼런스: 화면 상단 풀 와이드, 얇은 HP 바,
// 좌측 보스 이름, 어두운 프레임, 페이즈 구분선
//
// 사용법: Unity 상단 메뉴 → Tools → Boss Health Bar → Create Boss HealthBar UI
// ※ 에디터 전용 스크립트 — 빌드에 포함되지 않음
// ══════════════════════════════════════════════════════════════════════
public static class BossHealthBarCreator // 정적 클래스를 정의할거에요 -> 에디터 유틸리티 클래스를
{
// ─────────────────────────────────────────────────────────────
// 상수 — 다크 판타지 디자인 수치
// ─────────────────────────────────────────────────────────────
private const float BAR_WIDTH = 750f; // 상수를 정의할거에요 -> 체력바 전체 너비를 (풀 와이드 느낌)
private const float BAR_HEIGHT = 16f; // 상수를 정의할거에요 -> 체력바 높이를 (얇은 바)
private const float ROOT_HEIGHT = 52f; // 상수를 정의할거에요 -> 루트 전체 높이를 (이름 + 바)
private const float FRAME_PADDING_H = 12f; // 상수를 정의할거에요 -> 프레임 좌우 여백을
private const float FRAME_PADDING_V = 6f; // 상수를 정의할거에요 -> 프레임 상하 여백을
private const float DIVIDER_WIDTH = 1.5f; // 상수를 정의할거에요 -> 구분선 너비를 (가는 선)
private const float TOP_OFFSET_Y = -20f; // 상수를 정의할거에요 -> 화면 상단에서의 Y 오프셋을 (바짝 붙임)
private const float NAME_FONT_SIZE = 16f; // 상수를 정의할거에요 -> 보스 이름 폰트 크기를
private const float HP_FONT_SIZE = 11f; // 상수를 정의할거에요 -> HP 수치 폰트 크기를
// ─────────────────────────────────────────────────────────────
// 색상 팔레트 — 다크 판타지 테마
// ─────────────────────────────────────────────────────────────
private static readonly Color COL_FRAME_BG = new Color(0.06f, 0.05f, 0.07f, 0.88f); // 프레임 배경 (거의 검정)
private static readonly Color COL_FRAME_BORDER = new Color(0.35f, 0.25f, 0.15f, 0.7f); // 프레임 테두리 (어두운 갈색)
private static readonly Color COL_FRAME_INNER = new Color(0.25f, 0.18f, 0.12f, 0.5f); // 안쪽 라인 (바랜 갈색)
private static readonly Color COL_BAR_BG = new Color(0.08f, 0.06f, 0.06f, 0.95f); // 바 배경 (짙은 검정)
private static readonly Color COL_HP_FILL = new Color(0.6f, 0.12f, 0.08f, 1f); // HP 바 (어두운 붉은색)
private static readonly Color COL_DAMAGE_FILL = new Color(0.7f, 0.3f, 0.1f, 0.6f); // 데미지 연출 (어두운 주황)
private static readonly Color COL_NAME_TEXT = new Color(0.85f, 0.78f, 0.65f, 1f); // 보스 이름 (바랜 금색)
private static readonly Color COL_HP_TEXT = new Color(0.7f, 0.65f, 0.55f, 0.85f); // HP 수치 (어두운 금색)
private static readonly Color COL_DIVIDER = new Color(0.5f, 0.4f, 0.25f, 0.45f); // 구분선 (어두운 금색 반투명)
private static readonly Color COL_DECO_LINE = new Color(0.4f, 0.3f, 0.18f, 0.35f); // 장식 라인 (은은한 갈색)
// ─────────────────────────────────────────────────────────────
// 메뉴 항목
// ─────────────────────────────────────────────────────────────
[MenuItem("Tools/Boss Health Bar/Create Boss HealthBar UI")] // 메뉴를 등록할거에요 -> Tools 하위에
public static void CreateBossHealthBarUI() // 함수를 정의할거에요 -> 체력바 UI 자동 생성을
{
// ════════════════════════════════════════════════════════
// 1단계: 기존 Canvas 찾기 또는 새로 생성
// ════════════════════════════════════════════════════════
Canvas existingCanvas = Object.FindObjectOfType<Canvas>(); // 찾을거에요 -> 씬에 이미 있는 Canvas를
GameObject canvasObj; // 변수를 선언할거에요 -> Canvas 오브젝트를
if (existingCanvas != null) // 조건이 맞으면 실행할거에요 -> 기존 Canvas가 있으면
{
canvasObj = existingCanvas.gameObject; // 사용할거에요 -> 기존 Canvas를 그대로
Debug.Log("[BossHealthBarCreator] 기존 Canvas를 사용합니다."); // 로그를 찍을거에요
}
else // 조건이 틀리면 실행할거에요 -> Canvas가 없으면 새로 생성
{
canvasObj = new GameObject("InGameCanvas"); // 생성할거에요 -> Canvas 오브젝트를
Canvas canvas = canvasObj.AddComponent<Canvas>(); // 추가할거에요 -> Canvas 컴포넌트를
canvas.renderMode = RenderMode.ScreenSpaceOverlay; // 설정할거에요 -> 렌더 모드를 오버레이로
canvas.sortingOrder = 10; // 설정할거에요 -> 정렬 순서를 (다른 UI 위에)
CanvasScaler scaler = canvasObj.AddComponent<CanvasScaler>(); // 추가할거에요 -> CanvasScaler를
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; // 설정할거에요 -> 해상도 대응 스케일 모드를
scaler.referenceResolution = new Vector2(1920, 1080); // 설정할거에요 -> 기준 해상도를 FHD로
scaler.matchWidthOrHeight = 0.5f; // 설정할거에요 -> 가로/세로 매칭 비율을
canvasObj.AddComponent<GraphicRaycaster>(); // 추가할거에요 -> UI 클릭 감지용 Raycaster를
Debug.Log("[BossHealthBarCreator] 새 Canvas를 생성했습니다."); // 로그를 찍을거에요
}
// ════════════════════════════════════════════════════════
// 2단계: BossHealthBar_Root (최상위 컨테이너)
// → 화면 상단 중앙에 풀 와이드로 배치
// ════════════════════════════════════════════════════════
GameObject root = CreateUIObject("BossHealthBar_Root", canvasObj.transform); // 생성할거에요 -> 체력바 루트 오브젝트를
RectTransform rootRect = root.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
rootRect.anchorMin = new Vector2(0.5f, 1f); // 설정할거에요 -> 앵커 최소를 (상단 중앙)
rootRect.anchorMax = new Vector2(0.5f, 1f); // 설정할거에요 -> 앵커 최대를 (상단 중앙)
rootRect.pivot = new Vector2(0.5f, 1f); // 설정할거에요 -> 피벗을 (상단 중앙)
rootRect.anchoredPosition = new Vector2(0f, TOP_OFFSET_Y); // 설정할거에요 -> 위치를 (상단에서 살짝 아래)
rootRect.sizeDelta = new Vector2(BAR_WIDTH, ROOT_HEIGHT); // 설정할거에요 -> 크기를 (750 × 52)
// ════════════════════════════════════════════════════════
// 3단계: 외곽 테두리 (가장 뒤, 어두운 갈색)
// ════════════════════════════════════════════════════════
GameObject outerBorder = CreateUIObject("OuterBorder", root.transform); // 생성할거에요 -> 외곽 테두리를
Image outerBorderImg = outerBorder.AddComponent<Image>(); // 추가할거에요 -> Image를
outerBorderImg.color = COL_FRAME_BORDER; // 설정할거에요 -> 어두운 갈색 테두리를
RectTransform outerBorderRect = outerBorder.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
SetStretch(outerBorderRect); // 실행할거에요 -> 부모에 스트레치
outerBorderRect.offsetMin = new Vector2(-1.5f, -1.5f); // 설정할거에요 -> 바깥으로 1.5px 확장을
outerBorderRect.offsetMax = new Vector2(1.5f, 1.5f); // 설정할거에요 -> 바깥으로 1.5px 확장을
// ════════════════════════════════════════════════════════
// 4단계: 프레임 배경 (거의 검정, 메인 배경)
// ════════════════════════════════════════════════════════
GameObject frame = CreateUIObject("Frame", root.transform); // 생성할거에요 -> 프레임 배경을
Image frameImg = frame.AddComponent<Image>(); // 추가할거에요 -> Image를
frameImg.color = COL_FRAME_BG; // 설정할거에요 -> 거의 검정색 배경을
RectTransform frameRect = frame.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
SetStretch(frameRect); // 실행할거에요 -> 부모에 스트레치
// ════════════════════════════════════════════════════════
// 5단계: 안쪽 장식 라인 (프레임 내부 은은한 테두리)
// ════════════════════════════════════════════════════════
GameObject innerLine = CreateUIObject("InnerLine", root.transform); // 생성할거에요 -> 안쪽 장식 라인을
Image innerLineImg = innerLine.AddComponent<Image>(); // 추가할거에요 -> Image를
innerLineImg.color = COL_FRAME_INNER; // 설정할거에요 -> 바랜 갈색 라인을
RectTransform innerLineRect = innerLine.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
SetStretch(innerLineRect); // 실행할거에요 -> 부모에 스트레치
innerLineRect.offsetMin = new Vector2(3f, 3f); // 설정할거에요 -> 안쪽으로 3px 축소
innerLineRect.offsetMax = new Vector2(-3f, -3f); // 설정할거에요 -> 안쪽으로 3px 축소
// 안쪽은 투명하게 (테두리만 보이도록)
// → Image를 쓰지만 배경 위에 겹쳐서 테두리 효과
// ════════════════════════════════════════════════════════
// 6단계: 좌측 장식 세로선 (이름 영역 구분)
// ════════════════════════════════════════════════════════
GameObject leftDeco = CreateUIObject("LeftDecoLine", root.transform); // 생성할거에요 -> 좌측 장식 세로선을
Image leftDecoImg = leftDeco.AddComponent<Image>(); // 추가할거에요 -> Image를
leftDecoImg.color = COL_DECO_LINE; // 설정할거에요 -> 은은한 갈색을
RectTransform leftDecoRect = leftDeco.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
leftDecoRect.anchorMin = new Vector2(0f, 0f); // 설정할거에요 -> 앵커를 좌측 전체로
leftDecoRect.anchorMax = new Vector2(0f, 1f); // 설정할거에요 -> 앵커를 좌측 전체로
leftDecoRect.pivot = new Vector2(0f, 0.5f); // 설정할거에요 -> 피벗을 좌측 중앙으로
leftDecoRect.anchoredPosition = new Vector2(160f, 0f); // 설정할거에요 -> 위치를 (이름 영역 끝)
leftDecoRect.sizeDelta = new Vector2(1f, -10f); // 설정할거에요 -> 크기를 (1px 너비, 상하 5px 여유)
// ════════════════════════════════════════════════════════
// 7단계: 보스 이름 텍스트 (좌측, 프레임 안)
// ════════════════════════════════════════════════════════
GameObject nameObj = CreateUIObject("BossName", root.transform); // 생성할거에요 -> 이름 텍스트 오브젝트를
TextMeshProUGUI nameText = nameObj.AddComponent<TextMeshProUGUI>(); // 추가할거에요 -> TMP를
nameText.text = "Norciel"; // 설정할거에요 -> 기본 보스 이름을
nameText.fontSize = NAME_FONT_SIZE; // 설정할거에요 -> 폰트 크기를 16
nameText.fontStyle = FontStyles.Normal; // 설정할거에요 -> 일반 스타일을 (다크 판타지는 볼드보다 일반이 어울림)
nameText.color = COL_NAME_TEXT; // 설정할거에요 -> 바랜 금색 텍스트를
nameText.alignment = TextAlignmentOptions.Center; // 설정할거에요 -> 중앙 정렬을
nameText.enableWordWrapping = false; // 설정할거에요 -> 줄바꿈 비활성화를
nameText.characterSpacing = 6f; // 설정할거에요 -> 자간을 넓혀서 (고풍스러운 느낌)
RectTransform nameRect = nameObj.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
nameRect.anchorMin = new Vector2(0f, 0f); // 설정할거에요 -> 앵커를 좌측 전체로
nameRect.anchorMax = new Vector2(0f, 1f); // 설정할거에요 -> 앵커를 좌측 전체로
nameRect.pivot = new Vector2(0f, 0.5f); // 설정할거에요 -> 피벗을 좌측 중앙으로
nameRect.anchoredPosition = new Vector2(FRAME_PADDING_H, 0f); // 설정할거에요 -> 위치를 (좌측 여백)
nameRect.sizeDelta = new Vector2(145f, 0f); // 설정할거에요 -> 너비를 145px로 (높이는 스트레치)
// ════════════════════════════════════════════════════════
// 8단계: 바 배경 (장식선 오른쪽, HP 바 영역)
// ════════════════════════════════════════════════════════
float barStartX = 170f; // 설정할거에요 -> 바 시작 X를 (이름 영역 + 구분선 뒤)
GameObject barBg = CreateUIObject("BarBackground", root.transform); // 생성할거에요 -> 바 배경을
Image barBgImg = barBg.AddComponent<Image>(); // 추가할거에요 -> Image를
barBgImg.color = COL_BAR_BG; // 설정할거에요 -> 짙은 검정 배경을
RectTransform barBgRect = barBg.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
barBgRect.anchorMin = new Vector2(0f, 0.5f); // 설정할거에요 -> 앵커를 좌측 중앙으로
barBgRect.anchorMax = new Vector2(1f, 0.5f); // 설정할거에요 -> 앵커를 우측 중앙으로
barBgRect.pivot = new Vector2(0f, 0.5f); // 설정할거에요 -> 피벗을 좌측 중앙으로
barBgRect.anchoredPosition = new Vector2(barStartX, 0f); // 설정할거에요 -> 위치를 (이름 영역 오른쪽)
barBgRect.sizeDelta = new Vector2(-barStartX - FRAME_PADDING_H, BAR_HEIGHT); // 설정할거에요 -> 크기를 (남은 너비 × 16px)
// ════════════════════════════════════════════════════════
// 9단계: 데미지 연출 바 (어두운 주황, 뒤쪽에서 천천히 따라감)
// ════════════════════════════════════════════════════════
GameObject damageFill = CreateUIObject("HP_DamageFill", barBg.transform); // 생성할거에요 -> 데미지 연출 바를
Image damageFillImg = damageFill.AddComponent<Image>(); // 추가할거에요 -> Image를
damageFillImg.color = COL_DAMAGE_FILL; // 설정할거에요 -> 어두운 주황색을
damageFillImg.type = Image.Type.Filled; // 설정할거에요 -> Filled 타입으로
damageFillImg.fillMethod = Image.FillMethod.Horizontal; // 설정할거에요 -> 가로 채우기를
damageFillImg.fillOrigin = 0; // 설정할거에요 -> 좌측부터 채우기를
damageFillImg.fillAmount = 1f; // 설정할거에요 -> 초기 100%를
SetStretch(damageFill.GetComponent<RectTransform>()); // 실행할거에요 -> 부모에 스트레치
// ════════════════════════════════════════════════════════
// 10단계: HP 바 (어두운 붉은색, 실제 HP)
// ════════════════════════════════════════════════════════
GameObject hpFill = CreateUIObject("HP_Fill", barBg.transform); // 생성할거에요 -> HP 바를
Image hpFillImg = hpFill.AddComponent<Image>(); // 추가할거에요 -> Image를
hpFillImg.color = COL_HP_FILL; // 설정할거에요 -> 어두운 붉은색을
hpFillImg.type = Image.Type.Filled; // 설정할거에요 -> Filled 타입으로
hpFillImg.fillMethod = Image.FillMethod.Horizontal; // 설정할거에요 -> 가로 채우기를
hpFillImg.fillOrigin = 0; // 설정할거에요 -> 좌측부터 채우기를
hpFillImg.fillAmount = 1f; // 설정할거에요 -> 초기 100%를
SetStretch(hpFill.GetComponent<RectTransform>()); // 실행할거에요 -> 부모에 스트레치
// ════════════════════════════════════════════════════════
// 11단계: HP 바 위 그라디언트 하이라이트 (위쪽 밝은 선)
// ════════════════════════════════════════════════════════
GameObject highlight = CreateUIObject("BarHighlight", barBg.transform); // 생성할거에요 -> 하이라이트를
Image highlightImg = highlight.AddComponent<Image>(); // 추가할거에요 -> Image를
highlightImg.color = new Color(1f, 1f, 1f, 0.06f); // 설정할거에요 -> 아주 연한 흰색을 (은은한 광택)
RectTransform highlightRect = highlight.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
highlightRect.anchorMin = new Vector2(0f, 0.6f); // 설정할거에요 -> 앵커를 (바 상단 40%)
highlightRect.anchorMax = new Vector2(1f, 1f); // 설정할거에요 -> 앵커를 (바 최상단)
highlightRect.offsetMin = Vector2.zero; // 설정할거에요 -> 여백 없음
highlightRect.offsetMax = Vector2.zero; // 설정할거에요 -> 여백 없음
// ════════════════════════════════════════════════════════
// 12단계: Phase2 구분선 (50% 지점)
// ════════════════════════════════════════════════════════
GameObject phase2Div = CreatePhaseDivider("Phase2_Divider", barBg.transform, 0.5f); // 생성할거에요 -> Phase2 구분선 (50%)
// ════════════════════════════════════════════════════════
// 13단계: Phase3 구분선 (25% 지점)
// ════════════════════════════════════════════════════════
GameObject phase3Div = CreatePhaseDivider("Phase3_Divider", barBg.transform, 0.25f); // 생성할거에요 -> Phase3 구분선 (25%)
// ════════════════════════════════════════════════════════
// 14단계: HP 수치 텍스트 (바 우측 끝)
// ════════════════════════════════════════════════════════
GameObject hpTextObj = CreateUIObject("HP_Text", barBg.transform); // 생성할거에요 -> HP 수치 텍스트를
TextMeshProUGUI hpText = hpTextObj.AddComponent<TextMeshProUGUI>(); // 추가할거에요 -> TMP를
hpText.text = "1000 / 1000"; // 설정할거에요 -> 기본 텍스트를
hpText.fontSize = HP_FONT_SIZE; // 설정할거에요 -> 폰트 크기를 11
hpText.color = COL_HP_TEXT; // 설정할거에요 -> 어두운 금색을
hpText.alignment = TextAlignmentOptions.Right; // 설정할거에요 -> 우측 정렬을 (바 끝쪽)
hpText.enableWordWrapping = false; // 설정할거에요 -> 줄바꿈 비활성화를
hpText.outlineWidth = 0.15f; // 설정할거에요 -> 얇은 외곽선을
hpText.outlineColor = new Color32(0, 0, 0, 200); // 설정할거에요 -> 검정 외곽선을
RectTransform hpTextRect = hpTextObj.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
SetStretch(hpTextRect); // 실행할거에요 -> 부모에 스트레치
hpTextRect.offsetMax = new Vector2(-6f, 0f); // 설정할거에요 -> 우측에 6px 여백을
// ════════════════════════════════════════════════════════
// 15단계: 페이즈 텍스트 (이름 아래 작게)
// ════════════════════════════════════════════════════════
GameObject phaseObj = CreateUIObject("Phase_Text", root.transform); // 생성할거에요 -> 페이즈 텍스트를
TextMeshProUGUI phaseTmp = phaseObj.AddComponent<TextMeshProUGUI>(); // 추가할거에요 -> TMP를
phaseTmp.text = "Phase 1"; // 설정할거에요 -> 기본 텍스트를
phaseTmp.fontSize = 10f; // 설정할거에요 -> 작은 폰트를
phaseTmp.color = new Color(0.5f, 0.45f, 0.35f, 0.6f); // 설정할거에요 -> 아주 어둡고 투명한 색을
phaseTmp.alignment = TextAlignmentOptions.Center; // 설정할거에요 -> 중앙 정렬을
phaseTmp.enableWordWrapping = false; // 설정할거에요 -> 줄바꿈 비활성화를
phaseTmp.characterSpacing = 4f; // 설정할거에요 -> 자간을 약간 넓게
RectTransform phaseRect = phaseObj.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
phaseRect.anchorMin = new Vector2(0f, 0f); // 설정할거에요 -> 앵커를 좌하단으로
phaseRect.anchorMax = new Vector2(0f, 0f); // 설정할거에요 -> 앵커를 좌하단으로
phaseRect.pivot = new Vector2(0f, 1f); // 설정할거에요 -> 피벗을 좌상단으로
phaseRect.anchoredPosition = new Vector2(FRAME_PADDING_H, -2f); // 설정할거에요 -> 프레임 아래에 배치
phaseRect.sizeDelta = new Vector2(145f, 16f); // 설정할거에요 -> 이름 영역과 같은 너비
// ════════════════════════════════════════════════════════
// 16단계: BossHealthBarUI 컴포넌트 추가 + 참조 자동 연결
// ════════════════════════════════════════════════════════
BossHealthBarUI uiComponent = root.AddComponent<BossHealthBarUI>(); // 추가할거에요 -> BossHealthBarUI 컴포넌트를
SerializedObject so = new SerializedObject(uiComponent); // 생성할거에요 -> SerializedObject를 (private 필드 접근용)
so.FindProperty("hpFillImage").objectReferenceValue = hpFillImg; // 연결할거에요 -> HP Fill 이미지를
so.FindProperty("hpDamageFillImage").objectReferenceValue = damageFillImg; // 연결할거에요 -> 데미지 바를
so.FindProperty("bossNameText").objectReferenceValue = nameText; // 연결할거에요 -> 보스 이름을
so.FindProperty("hpValueText").objectReferenceValue = hpText; // 연결할거에요 -> HP 수치를
so.FindProperty("phaseText").objectReferenceValue = phaseTmp; // 연결할거에요 -> 페이즈 텍스트를
so.FindProperty("frameImage").objectReferenceValue = frameImg; // 연결할거에요 -> 프레임을
so.FindProperty("bossIconImage").objectReferenceValue = null; // 비워둘거에요 -> 아이콘 없음 (다크 판타지 스타일)
so.FindProperty("phase2Divider").objectReferenceValue = phase2Div.GetComponent<RectTransform>(); // 연결할거에요 -> Phase2 구분선을
so.FindProperty("phase3Divider").objectReferenceValue = phase3Div.GetComponent<RectTransform>(); // 연결할거에요 -> Phase3 구분선을
so.ApplyModifiedProperties(); // 적용할거에요 -> 직렬화 데이터를
// ════════════════════════════════════════════════════════
// 17단계: 초기 상태 비활성화
// ════════════════════════════════════════════════════════
root.SetActive(false); // 비활성화할거에요 -> 전투 시작 전에는 숨김
// ════════════════════════════════════════════════════════
// 완료
// ════════════════════════════════════════════════════════
Undo.RegisterCreatedObjectUndo(root, "Create Boss HealthBar UI"); // 등록할거에요 -> Undo 기록을
Selection.activeGameObject = root; // 선택할거에요 -> 생성된 오브젝트를
Debug.Log("✅ [BossHealthBarCreator] 다크 판타지 보스 체력바 생성 완료! Inspector에서 Boss Monster / Phase Manager를 연결해주세요."); // 로그를 찍을거에요
}
// ─────────────────────────────────────────────────────────────
// 유틸리티 헬퍼 함수들
// ─────────────────────────────────────────────────────────────
/// <summary>RectTransform 포함 빈 UI 오브젝트 생성</summary>
private static GameObject CreateUIObject(string name, Transform parent) // 헬퍼를 정의할거에요 -> UI 오브젝트 생성용
{
GameObject obj = new GameObject(name); // 생성할거에요 -> 오브젝트를
obj.transform.SetParent(parent, false); // 설정할거에요 -> 부모를
if (obj.GetComponent<RectTransform>() == null) // 조건이 맞으면 실행할거에요 -> RectTransform 없으면
obj.AddComponent<RectTransform>(); // 추가할거에요 -> RectTransform을
return obj; // 반환할거에요 -> 오브젝트를
}
/// <summary>RectTransform을 부모에 꽉 차게 스트레치</summary>
private static void SetStretch(RectTransform rect) // 헬퍼를 정의할거에요 -> 스트레치 설정용
{
rect.anchorMin = Vector2.zero; // 설정할거에요 -> (0,0)
rect.anchorMax = Vector2.one; // 설정할거에요 -> (1,1)
rect.offsetMin = Vector2.zero; // 설정할거에요 -> 여백 없음
rect.offsetMax = Vector2.zero; // 설정할거에요 -> 여백 없음
}
/// <summary>페이즈 구분선 — 앵커 비율 기반 배치, 다크 판타지 색상</summary>
private static GameObject CreatePhaseDivider(string name, Transform parent, float ratio) // 헬퍼를 정의할거에요 -> 구분선 생성용
{
GameObject divider = CreateUIObject(name, parent); // 생성할거에요 -> 구분선 오브젝트를
Image divImg = divider.AddComponent<Image>(); // 추가할거에요 -> Image를
divImg.color = COL_DIVIDER; // 설정할거에요 -> 어두운 금색 반투명을
RectTransform divRect = divider.GetComponent<RectTransform>(); // 가져올거에요 -> RectTransform을
divRect.anchorMin = new Vector2(ratio, 0f); // 설정할거에요 -> 앵커를 (비율, 하단)
divRect.anchorMax = new Vector2(ratio, 1f); // 설정할거에요 -> 앵커를 (비율, 상단)
divRect.pivot = new Vector2(0.5f, 0.5f); // 설정할거에요 -> 피벗을 중앙으로
divRect.anchoredPosition = Vector2.zero; // 설정할거에요 -> 위치를 앵커 기준
divRect.sizeDelta = new Vector2(DIVIDER_WIDTH, 0f); // 설정할거에요 -> 너비 1.5px, 높이 스트레치
return divider; // 반환할거에요 -> 구분선을
}
}