using System.Collections.Generic; using UnityEngine; namespace TPSBR.UI { public class UIHitDamageIndicator : UIWidget { // PRIVATE MEMBERS [SerializeField] private UIHitDamageIndicatorItem _hitItem; [SerializeField] private UIHitDamageIndicatorItem _critItem; [SerializeField] private UIHitDamageIndicatorItem _fatalItem; private List _activeItems = new List(); private List _inactiveItems = new List(); private List _activeCritItems = new List(); private List _inactiveCritItems = new List(); private List _activeFatalItems = new List(); private List _inactiveFatalItems = new List(); private RectTransform _canvasRectTransform; private Canvas _canvas; private List _pendingHits = new List(16); // PUBLIC METHODS public void HitPerformed(HitData hitData) { for (int i = 0; i < _pendingHits.Count; i++) { var pending = _pendingHits[i]; // Try to merge hit data if (pending.Target == hitData.Target && pending.Target != null) { pending.Amount += hitData.Amount; pending.IsFatal |= hitData.IsFatal; pending.IsCritical |= hitData.IsCritical; _pendingHits[i] = pending; return; } } _pendingHits.Add(hitData); } // UIWidget INTERFACE protected override void OnInitialize() { _hitItem.SetActive(false); _critItem.SetActive(false); _fatalItem.SetActive(false); _canvas = GetComponentInParent(); _canvasRectTransform = _canvas.transform as RectTransform; } protected override void OnHidden() { _pendingHits.Clear(); } // MONOBEHAVIOUR private void Update() { for (int i = 0; i < _pendingHits.Count; i++) { ProcessHit(_pendingHits[i]); } _pendingHits.Clear(); } private void LateUpdate() { UpdateActiveItems(_activeItems, _inactiveItems); UpdateActiveItems(_activeCritItems, _inactiveCritItems); UpdateActiveItems(_activeFatalItems, _inactiveFatalItems); } // PRIVATE METHODS private void ProcessHit(HitData hitData) { var activeItems = hitData.IsFatal == true ? _activeFatalItems : (hitData.IsCritical == true ? _activeCritItems : _activeItems); var inactiveItems = hitData.IsFatal == true ? _inactiveFatalItems : (hitData.IsCritical == true ? _inactiveCritItems : _inactiveItems); var hitItem = inactiveItems.PopLast(); if (hitItem == null) { hitItem = Instantiate(hitData.IsFatal == true ? _fatalItem : (hitData.IsCritical == true ? _critItem : _hitItem)); hitItem.transform.SetParent(_hitItem.transform.parent); } activeItems.Add(hitItem); var hitPosition = hitData.Position; if (hitData.Target != null) { hitPosition = hitData.Target.HitPivot.position; } hitItem.Activate(hitData.Amount, hitPosition); hitItem.SetActive(true); hitItem.transform.SetAsLastSibling(); } private void UpdateActiveItems(List activeItems, List inactiveItems) { for (int i = activeItems.Count; i --> 0;) { var item = activeItems[i]; if (item.IsFinished == true) { item.SetActive(false); activeItems.RemoveBySwap(i); inactiveItems.Add(item); continue; } item.transform.position = GetUIPosition(item.WorldPosition); } } private Vector3 GetUIPosition(Vector3 worldPosition) { var screenPoint = Context.Camera.Camera.WorldToScreenPoint(worldPosition); RectTransformUtility.ScreenPointToLocalPointInRectangle(_canvasRectTransform, screenPoint, _canvas.worldCamera, out Vector2 screenPosition); return _canvasRectTransform.TransformPoint(screenPosition); } } }