using UnityEngine; public class DamageIndicatorHandler : MonoBehaviour, IOwnedComponent { struct DmgIndicatorProperty { public float fontSize; public Color color; } static readonly DmgIndicatorProperty _normalDmgIndicatorProp = new DmgIndicatorProperty { fontSize = 24f, color = new Color(1f, 1f, 1f) }; static readonly DmgIndicatorProperty _criticalDmgIndicatorProp = new DmgIndicatorProperty { fontSize = 32f, color = new Color(1f, 56f / 255f, 0f) }; [SerializeField] Transform spawnPosition; [SerializeField] DamageIndicatorText indicatorPrefab; public Character Owner { get; private set; } Camera mainCamera; Camera uiCamera; RectTransform indicatorRoot; DynamicMonoObjectPool indicatorPool; public void Initialize(Character owner) { Owner = owner; Owner.OnDamaged += OnDamaged; mainCamera = Camera.main; uiCamera = GameObject.FindGameObjectWithTag("UICamera").GetComponent(); indicatorRoot = GameObject.FindGameObjectWithTag("DamageIndicatorRoot").GetComponent(); indicatorPool = new(); indicatorPool.Initialize(InstantiateIndicator, DestroyIndicator, 5); } private DamageIndicatorText InstantiateIndicator() { var indicator = Instantiate(indicatorPrefab, indicatorRoot); indicator.OnComplete += indicatorPool.Return; return indicator; } private void DestroyIndicator(DamageIndicatorText indicator) { if (indicator == null || indicator.gameObject == null) return; Destroy(indicator.gameObject); } private void OnDamaged(Character _, Damage damage) { var indicator = indicatorPool.Get(); if (damage.isCritical) indicator.SetText(FormatString.BigIntString1(damage.value), _criticalDmgIndicatorProp.fontSize, _criticalDmgIndicatorProp.color); else indicator.SetText(FormatString.BigIntString1(damage.value), _normalDmgIndicatorProp.fontSize, _normalDmgIndicatorProp.color); var screenPos = mainCamera.WorldToScreenPoint(spawnPosition.position); RectTransformUtility.ScreenPointToLocalPointInRectangle(indicatorRoot, screenPos, uiCamera, out Vector2 localPos); indicator.transform.localPosition = localPos; indicator.Show(); } private void OnDestroy() { if (Owner == null) return; Owner.OnDamaged -= OnDamaged; indicatorPool.Dispose(); } }