Hello all, I am following the Unity Multiplayer Developer: Make Online Games Using Unity's NEW NGO Framework | GameDev.tv course and I have an interesting bug which I am unable to figure out how to fix.
The game has the standard asdw or arrow keys that it uses for movement. There is a healing zone in the game, which has a canvas item and a fill bar that gets changed as the healing zone is healing players, showing how much “heal power” is left in it. The script for the healing zone is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using Unity.Netcode;
using UnityEngine;
public class HealingZone : NetworkBehaviour
{
[Header(“References”)]
[SerializeField] private Image healPowerBar;
[Header("Settings")]
// How many times/ticks it can restore health:
[SerializeField] private int maxHealPower = 30;
[SerializeField] private float healCooldown = 60f;
// How frequently (secs) it heals:
[SerializeField] private float healTickRate = 1;
[SerializeField] private int coinsPerTick = 10;
[SerializeField] private int healthPerTick = 10;
private float remainingCooldown;
private float tickTimer; // how long until the next healing should happen
private List<TankPlayer> playersInZone = new List<TankPlayer>();
// Server is in charge of this and will update client's bars accordingly:
private NetworkVariable<int> HealPower = new NetworkVariable<int>();
private void Update()
{
// Gotta check every frame who is still inside the zone,
// how much heal they need, etc.
if (!IsServer) { return; }
if (remainingCooldown > 0f)
{
remainingCooldown -= Time.deltaTime;
if (remainingCooldown <= 0f)
{
HealPower.Value = maxHealPower;
}
else
{
return;
}
}
tickTimer += Time.deltaTime;
// without the 1 / here, changing healtickrate would make it twice as fast
// instead of taking 2 seconds..
if (tickTimer >= 1 / healTickRate)
{
foreach (TankPlayer player in playersInZone)
{
// check if heal power left, player is not full health and has coin to pay
if (HealPower.Value == 0) {break;}
if (player.Health.CurrentHealth.Value == player.Health.MaxHealth) {continue; }
if (player.Wallet.TotalCoins.Value < coinsPerTick) {continue; }
// if it passes these 3 checks, pay up heal the player
player.Wallet.SpendCoins(coinsPerTick);
player.Health.RestoreHealth(healthPerTick);
// Reduce available heal on pad, if zero, start CD
HealPower.Value -= 1;
if (HealPower.Value == 0)
{
remainingCooldown = healCooldown;
}
}
// remainder is better than asking = zero for accuracy
// 1 / healTickRate = how long until we do a tick
tickTimer = tickTimer % (1 / healTickRate);
}
}
public override void OnNetworkSpawn()
{
if (IsClient)
{
HealPower.OnValueChanged += HandleHealPowerChanged;
// When we connect to server not all will be fully charged
// need to do it manually once:
HandleHealPowerChanged(0, HealPower.Value);
}
// And the server should initialize the healpower to maxValue:
if (IsServer)
{
HealPower.Value = maxHealPower;
remainingCooldown = healCooldown;
}
}
public override void OnNetworkDespawn()
{
if (IsClient)
{
HealPower.OnValueChanged -= HandleHealPowerChanged;
}
}
private void HandleHealPowerChanged(int oldHealPower, int newHealPower)
{
// update the fill amount of the UI power bar
healPowerBar.fillAmount = (float) newHealPower / maxHealPower;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (!IsServer) { return; }
// collider and TankPlayer component on different hierarchy levels
if (!other.attachedRigidbody.TryGetComponent<TankPlayer>(
out TankPlayer player)) { return; }
playersInZone.Add(player);
}
private void OnTriggerExit2D(Collider2D other)
{
if (!IsServer) { return; }
// collider and TankPlayer component on different hierarchy levels
if (!other.attachedRigidbody.TryGetComponent<TankPlayer>(
out TankPlayer player)) { return; }
playersInZone.Remove(player);
}
}
Here is a video showcasting the issue:
I did a chatgpt search and made sure that there are no calls to healthpowebar anywhere other than this code above which might be manipulating the visibility or SetActive of the power bar in question. I also placed debug.log codes around to see if the fill bar’s value is being changed by movement and that is not the case either, the fill bar’s value is not affected during movement at all.
Any help would be appreciated!