using UnityEngine; using UnityEngine.UI; namespace Streamingle.Contents.BossRaid { /// /// 유저 HP바. 머리 위 월드스페이스 캔버스로 표시됩니다. /// public class PlayerHPBar : MonoBehaviour { #region Fields [Header("설정")] [SerializeField] private Vector3 offset = new Vector3(0f, 0.3f, 0f); [SerializeField] private float barWidth = 1.2f; [SerializeField] private float barHeight = 0.12f; [SerializeField] private float smoothSpeed = 8f; [Header("색상")] [SerializeField] private Color hpColor = new Color(0.2f, 0.85f, 0.3f); [SerializeField] private Color hpColorLow = new Color(0.95f, 0.2f, 0.15f); [SerializeField] private Color bgColor = new Color(0.1f, 0.1f, 0.1f, 0.85f); [SerializeField] private Color frameColor = new Color(0.3f, 0.3f, 0.35f); private Canvas _canvas; private Image _hpFill; private RectTransform _fillRect; private Transform _followTarget; private float _targetRatio = 1f; private float _displayRatio = 1f; private bool _isVisible; private Font _font; private Text _nameText; #endregion #region Unity Messages private void LateUpdate() { if (!_isVisible || _followTarget == null) return; // 머리 위 따라다님 transform.position = _followTarget.position + offset; // 카메라를 향하도록 if (Camera.main != null) _canvas.transform.rotation = Camera.main.transform.rotation; // 부드러운 HP 감소 _displayRatio = Mathf.Lerp(_displayRatio, _targetRatio, Time.deltaTime * smoothSpeed); _fillRect.anchorMax = new Vector2(Mathf.Clamp01(_displayRatio), 1f); _hpFill.color = _displayRatio > 0.3f ? hpColor : hpColorLow; } #endregion #region Public Methods public void Initialize(Transform headTarget, string playerName = "", Vector3? customOffset = null) { _font = BossRaidFontLoader.Load(); _followTarget = headTarget; if (customOffset.HasValue) offset = customOffset.Value; CreateUI(); _isVisible = true; if (_nameText != null && !string.IsNullOrEmpty(playerName)) _nameText.text = playerName; } public void SetHP(float ratio) { _targetRatio = Mathf.Clamp01(ratio); } public void Show() { _isVisible = true; if (_canvas != null) _canvas.gameObject.SetActive(true); } public void Hide() { _isVisible = false; if (_canvas != null) _canvas.gameObject.SetActive(false); } #endregion #region Private Methods private void CreateUI() { var canvasObj = new GameObject("PlayerHPBar_Canvas"); canvasObj.transform.SetParent(transform); canvasObj.transform.localPosition = Vector3.zero; _canvas = canvasObj.AddComponent(); _canvas.renderMode = RenderMode.WorldSpace; _canvas.sortingOrder = 90; var rt = canvasObj.GetComponent(); rt.sizeDelta = new Vector2(barWidth, barHeight + 0.15f); rt.localScale = Vector3.one; // 프레임 var frameObj = new GameObject("Frame"); frameObj.transform.SetParent(canvasObj.transform, false); var frameRect = frameObj.AddComponent(); frameRect.anchorMin = new Vector2(0f, 0f); frameRect.anchorMax = new Vector2(1f, 0.7f); frameRect.offsetMin = Vector2.zero; frameRect.offsetMax = Vector2.zero; var frameImg = frameObj.AddComponent(); frameImg.color = frameColor; frameImg.raycastTarget = false; // 배경 var bgObj = new GameObject("BG"); bgObj.transform.SetParent(frameObj.transform, false); var bgRect = bgObj.AddComponent(); bgRect.anchorMin = Vector2.zero; bgRect.anchorMax = Vector2.one; bgRect.offsetMin = new Vector2(0.01f, 0.01f); bgRect.offsetMax = new Vector2(-0.01f, -0.01f); var bgImg = bgObj.AddComponent(); bgImg.color = bgColor; bgImg.raycastTarget = false; // HP Fill var fillObj = new GameObject("Fill"); fillObj.transform.SetParent(bgObj.transform, false); _fillRect = fillObj.AddComponent(); _fillRect.anchorMin = Vector2.zero; _fillRect.anchorMax = Vector2.one; _fillRect.offsetMin = Vector2.zero; _fillRect.offsetMax = Vector2.zero; _hpFill = fillObj.AddComponent(); _hpFill.color = hpColor; _hpFill.raycastTarget = false; // 이름 텍스트 (바 위) var nameObj = new GameObject("Name"); nameObj.transform.SetParent(canvasObj.transform, false); var nameRect = nameObj.AddComponent(); nameRect.anchorMin = new Vector2(0f, 0.7f); nameRect.anchorMax = Vector2.one; nameRect.offsetMin = Vector2.zero; nameRect.offsetMax = Vector2.zero; _nameText = nameObj.AddComponent(); _nameText.text = ""; _nameText.fontSize = 3; _nameText.color = Color.white; _nameText.alignment = TextAnchor.MiddleCenter; _nameText.raycastTarget = false; if (_font != null) _nameText.font = _font; var outline = nameObj.AddComponent(); outline.effectColor = Color.black; outline.effectDistance = new Vector2(0.3f, -0.3f); } #endregion } }