Multiplayer Tank Game Course heal zone fill bar issue

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!

Here is a new video showcasing the bizzare behavior at the wall and the mountain on the left side too:

I am moving the tank by pressing up and right in a way to rotate it

If it is aligned one way, wall is above mountain, fill bar appears above ground
if aligned other way, wall is below mountain, fill bar goes behind ground.

is this something about sorting layers? if so how is it affected by the keys and tank alignment?

It was an issue with the order in layers. I still do not know how the tank’s orientation/movement triggered it but setting the wall order in layer to 1, and healpad fill bar to 2, while keeping ground and environment to 0 fixed it.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms