167 lines
5.9 KiB
C#

using UnityEngine;
using UnityEngine.UI;
namespace Streamingle.Contents.BossRaid
{
/// <summary>
/// 유저 HP바. 머리 위 월드스페이스 캔버스로 표시됩니다.
/// </summary>
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>();
_canvas.renderMode = RenderMode.WorldSpace;
_canvas.sortingOrder = 90;
var rt = canvasObj.GetComponent<RectTransform>();
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<RectTransform>();
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<Image>();
frameImg.color = frameColor;
frameImg.raycastTarget = false;
// 배경
var bgObj = new GameObject("BG");
bgObj.transform.SetParent(frameObj.transform, false);
var bgRect = bgObj.AddComponent<RectTransform>();
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<Image>();
bgImg.color = bgColor;
bgImg.raycastTarget = false;
// HP Fill
var fillObj = new GameObject("Fill");
fillObj.transform.SetParent(bgObj.transform, false);
_fillRect = fillObj.AddComponent<RectTransform>();
_fillRect.anchorMin = Vector2.zero;
_fillRect.anchorMax = Vector2.one;
_fillRect.offsetMin = Vector2.zero;
_fillRect.offsetMax = Vector2.zero;
_hpFill = fillObj.AddComponent<Image>();
_hpFill.color = hpColor;
_hpFill.raycastTarget = false;
// 이름 텍스트 (바 위)
var nameObj = new GameObject("Name");
nameObj.transform.SetParent(canvasObj.transform, false);
var nameRect = nameObj.AddComponent<RectTransform>();
nameRect.anchorMin = new Vector2(0f, 0.7f);
nameRect.anchorMax = Vector2.one;
nameRect.offsetMin = Vector2.zero;
nameRect.offsetMax = Vector2.zero;
_nameText = nameObj.AddComponent<Text>();
_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>();
outline.effectColor = Color.black;
outline.effectDistance = new Vector2(0.3f, -0.3f);
}
#endregion
}
}