Alternative implementation for ActionSlotUI Cooldown fill calculation

Howdy,

Thought I’d share an alternative implementation for setting the fill amount using an ICooldown interface:

namespace RPG.Abilities
{
    public interface ICooldown
    {
        float CooldownDuration { get; }
    }
}

The changes to Ability.cs are pretty simple:

index 5c194df..1bc5e5f 100644
--- a/Ability.cs
+++ b/Ability.cs
@@ -5,7 +5,7 @@ using RPG.Inventory;
 namespace RPG.Abilities
 {
     [CreateAssetMenu(menuName = "RPG/Abilities/New Ability")]
-    public class Ability : ActionItem
+    public class Ability : ActionItem, ICooldown
     {
         [Header("Ability")]
         [SerializeField] TargetingStrategy _targetingStrategy;
@@ -13,6 +13,8 @@ namespace RPG.Abilities
         [SerializeField] EffectStrategy[] _effectStrategies;
         [SerializeField] float _cooldown = 0f;
 
+        float ICooldown.CooldownDuration => _cooldown;
+
         public override void Use(GameObject user)
         {
             var data = new AbilityData(user);

Inherit from ICooldown and implement the CooldownDuration field.

Then in ActionSlotUI.cs:

index aac264d..3ef61b6 100644
--- a/ActionSlotUI.cs
+++ b/ActionSlotUI.cs
@@ -20,6 +20,8 @@ namespace GameDevTV.UI.Inventories
 
         // CACHE
         ActionStore store;
+        private CooldownStore _cooldownStore;
+        private ICooldown _cooldown = null;
 
         // LIFECYCLE METHODS
         private void Awake()
@@ -27,6 +29,20 @@ namespace GameDevTV.UI.Inventories
             var player = GameObject.FindGameObjectWithTag("Player");
             store = player.GetComponent<ActionStore>();
             store.storeUpdated += UpdateIcon;
+
+            _cooldownStore = player.GetComponent<CooldownStore>();
+        }
+
+        void Update()
+        {
+            if (_cooldown == null) return;
+
+            var duration = _cooldown.CooldownDuration;
+            if (duration <= 0) return;
+
+            var remaining = _cooldownStore.GetTimeRemaining(_cooldown);
+            var percentage = Mathf.Clamp01(remaining / duration);
+            _cooldownOverlay.fillAmount = percentage;
         }
 
         // PUBLIC
@@ -60,7 +76,9 @@ namespace GameDevTV.UI.Inventories
 
         void UpdateIcon()
         {
-            icon.SetItem(GetItem(), GetNumber());
+            var item = GetItem();
+            icon.SetItem(item, GetNumber());
+            _cooldown = item as ICooldown;
         }
     }
 }

cast the item to ICooldown when the store is updated. If the value isn’t null during Update, calculate the duration as a fraction and set the fill as normal.

One downside of this approach is if the cooldown time is adjusted in the inspector during play mode, the fill animation will become incorrect unless the item is swapped to another slot. To work around this you’d need to either:

  1. move private ICooldown _cooldown to be a local variable within Update and perform the cast every frame, or
  2. switch from using a value type (float) to a reference type, such as using ScriptableObjects as Variables, for the cooldown field.

-robodude666

Well done!

Privacy & Terms