I am trying to add a cooldown image for my roll ability to my UI but I am having trouble. I have two scripts PlayerControls and RollColldownUI. The roll cool down currently works but I cannot get the Canvas to display the cooldown.
Question 1: Is this the best way to handle an ability cooldown or is there a better way to do it?
Question 2: How can I get the UI cooldown to work by referencing PlayerControls?
Doing cooldowns with just a simple float in a small object above is perfect.
You probably just want to make an API for It and make all the guts private.
Things the API might say are:
reset cooldown (start of level)
set cooldown (eg, spell has been cast)
am I cooled? (eg, can I cast?)
what fraction of cooldown am I? (0 to 1 so you can display a bar)
And then since it is a MonoBehaviour, it should just decrement itself. Don’t splatter code to update it internally all over the place, ESPECIALLY not in UI. UI code should just present stuff, certainly never modify anything.
ALSO: don’t have a bool. Just make it part of your API, perhaps a property that informs external users about the internal state of the timer, for instance:
public bool IsCooling { get { return coolTimer > 0; } }
As to why what you have doesn’t work, it sounds like you probably just have a bug. Time to start debugging!
By debugging you can find out exactly what your program is doing so you can fix it.
Use the above techniques to get the information you need in order to reason about what the problem is.
You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
Cooldown timers, gun bullet intervals, shot spacing, rate of fire:
Thanks, I made some progress. I didn’t understand how to build an API using Unity so I started messing around with the RollCooldownUI.cs. It seems to work except I get a,
NullReferenceException: Object reference not set to an instance of an object
RollCooldownUI.Update, This is happening because my RollCooldownUI is refrencing the PlayerNew Player controls and not the clone that is created when the game is launched. How can I make the RollCooldownUI look at the clone being created?
using MoreMountains.Tools;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[DisallowMultipleComponent]
public class RollCooldownUI : MonoBehaviour
{
public PlayerControl playerControl;
[SerializeField] private Image imageCooldown;
//public TextMeshPro countDownText;
private float waitTime = 3f;
private void Awake()
{
playerControl = GetComponent<PlayerControl>();
}
private void Start()
{
imageCooldown.fillAmount = 0.0f;
}
private void Update()
{
if (playerControl.isPlayerRolling == true)
{
Debug.Log("playerControl Accessed by RollCooldownUI");
imageCooldown.fillAmount = 1;
// reduce image fill
imageCooldown.fillAmount -= 1.0f / waitTime * Time.deltaTime;
}
}
public void ApplyCooldown()
{
imageCooldown.fillAmount = 1f;
//imageCooldown.fillAmount = playerControl.rollCoolDown;
Debug.Log(playerControl.rollCoolDown);
/*
if (playerControl != null)
{
imageCooldown.fillAmount = playerControl.rollCoolDown / playerControl.nextRollFireTime;
Debug.Log(imageCooldown.fillAmount);
}*/
/*
if (playerControl.rollCoolDownTime < 0.0f)
{
Debug.Log("rollCoolDown < 0");
playerControl.isPlayerRolling = false;
imageCooldown.fillAmount = 0.0f;
}
else
{
Debug.Log("rollCoolDown active");
imageCooldown.fillAmount = playerControl.rollCoolDownTime / playerControl.rollCoolDownTime;
}
*/
}
}
Thanks for this. Unfortunately being new to this, I am at a loss on how to reference the clone maybe I set it up incorrectly. The clone is coming from my Game Manager script.
public class GameManager : SingletonMonobehaviour<GameManager>
{
private PlayerDetailsSO playerDetails;
private PlayerControl playerControl;
private Player player;
protected override void Awake()
{
base.Awake();
playerDetails = GameResources.Instance.currentPlayer.playerDetails;
input = new CustomInputs();
InstantiatePlayer();
}
private void InstantiatePlayer()
{
GameObject playerGameObject = Instantiate(playerDetails.playerPrefab);
player = playerGameObject.GetComponent<Player>();
player.Initialize(playerDetails);
}
}
This is using my PlayerDetailsSO script to get the current Player selected.
public class PlayerDetailsSO : ScriptableObject
{
public GameObject playerPrefab;
}
My PlayerControl script references the PlayerDetails but the isPlayerRolling bool is in PlayerControls not PlayerDetailsSO. So I am wondering if I need to move that into PLayerDetailsSO to be able to access the bool. As you can see I am lost.