Upgrade
Lesson 18 of 25 in Coddy's Unity Game: Tower Defense course.
The panel's Upgrade button calls UpgradeSelected. It pays through the GameManager's TrySpend, so a short purse changes nothing. At the top level there is nothing left to buy: the stats show the current values only, and the button is not interactable.
The panel is UI over the 3D view, and a click on its button is also a mouse press that the BuildManager sees. Its ray goes through the button to the ground behind it, and the BuildManager would close the panel before the button is released. EventSystem.current.IsPointerOverGameObject() is true while the pointer is over UI, so the BuildManager returns early and leaves those clicks to the buttons.
Challenge
MediumUpgrade the selected tower from its panel.
- Write
public void UpgradeSelected(): belowmaxLevel, whengame.TrySpend(data.UpgradeCost(level))pays, upgrade the tower and refresh the panel. - At
maxLevel, the panel showsDamage 4andRange 5.5on two lines andMax level, and a serializedupgradeButtonis not interactable. - In
Update, return whenEventSystem.current.IsPointerOverGameObject().
Press Play, build a tower, click it and upgrade it twice: the panel shows Max level. Then Check.
Try it yourself
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using TMPro;
public class BuildManager : MonoBehaviour
{
[SerializeField] private GameManager game;
[SerializeField] private Tower[] shop;
[SerializeField] private Button[] shopButtons;
[SerializeField] private Color chosenColor = new Color(1f, 0.85f, 0.3f);
[SerializeField] private GameObject towerPanel;
[SerializeField] private TMP_Text towerNameText;
[SerializeField] private TMP_Text towerStatsText;
[SerializeField] private TMP_Text upgradeLabel;
private Tower chosen;
private Tower selected;
void Start()
{
for (int i = 0; i < shop.Length; i++)
{
Tower prefab = shop[i];
shopButtons[i].GetComponentInChildren<TMP_Text>().text = prefab.data.towerName + "\n" + prefab.data.cost;
shopButtons[i].onClick.AddListener(() => Choose(prefab));
}
Choose(shop[0]);
Select(null);
}
void Choose(Tower prefab)
{
chosen = prefab;
for (int i = 0; i < shop.Length; i++)
{
shopButtons[i].image.color = shop[i] == chosen ? chosenColor : Color.white;
}
}
void Update()
{
if (!Mouse.current.leftButton.wasPressedThisFrame)
{
return;
}
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
if (!Physics.Raycast(ray, out RaycastHit hit))
{
Select(null);
return;
}
Tower tower = hit.collider.GetComponentInParent<Tower>();
if (tower != null)
{
Select(tower);
return;
}
Select(null);
if (hit.collider.TryGetComponent(out BuildPad pad))
{
Build(pad);
}
}
void Build(BuildPad pad)
{
if (pad.tower != null)
{
return;
}
if (!game.TrySpend(chosen.data.cost))
{
Debug.Log("Not enough money");
return;
}
pad.tower = Instantiate(chosen, pad.transform.position, Quaternion.identity);
}
void Select(Tower tower)
{
selected = tower;
towerPanel.SetActive(tower != null);
if (tower != null)
{
ShowPanel();
}
}
void ShowPanel()
{
TowerData data = selected.data;
int level = selected.Level;
towerNameText.text = data.towerName + " level " + level;
towerStatsText.text = "Damage " + data.DamageAt(level) + " > " + data.DamageAt(level + 1)
+ "\nRange " + data.RangeAt(level) + " > " + data.RangeAt(level + 1);
upgradeLabel.text = "Upgrade " + data.UpgradeCost(level);
}
}
All lessons in Unity Game: Tower Defense
Practice on your own: Unity playground