Vender
Lección 13 de 18 del curso Juego de Unity: defensa de torres de Coddy.
Al vender una torre, se recupera la mitad de lo que costó, incluidas las mejoras, así que mover una defensa cuesta algo, pero no todo. La torre mantiene un total acumulado del dinero que se ha gastado en ella: su precio cuando se construyó, más el precio de cada mejora a medida que se paga. El reembolso es la mitad de ese total, y una división entera lo redondea hacia abajo. Un alquiler de bicicletas mantiene el mismo tipo de total:
public void ExtendRide(int extraHours)
{
paid += extraHours * pricePerHour;
}
public int Deposit => paid / 4;Al venderla, la torre se destruye y el campo tower de la plataforma sigue apuntando a ella. El operador == de Unity trata un objeto destruido como null, así que desde el siguiente fotograma pad.tower == null es true, y la plataforma vuelve a estar libre sin código adicional. El panel es otra cuestión: sigue mostrando la torre vendida, y al hacer clic en Upgrade se accedería a un objeto destruido y se lanzaría una MissingReferenceException. Al vender, no se selecciona nada, lo que oculta el panel.
Desafío
Intermedio- En
Tower, conserva unintprivadospent: elcostde la torre, establecido enStart, más el precio de cada mejora cuando se compra. Añadepublic int SellValue => spent / 2;. - En
BuildManager, muestraSell 25, el valor de venta de la torre seleccionada, en unTMP_TextserializadosellLabelcada vez que se rellene el panel. - Escribe
public void SellSelected(), que será llamado por el botón Sell: devuelve el valor de venta a través de GameManager, destruye la torre y no selecciona nada.
Pulsa Play, luego construye, mejora y vende algunas torres y, después, pulsa Check.
Pruébalo tú mismo
using UnityEngine;
using UnityEngine.EventSystems;
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 Button upgradeButton;
[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 || EventSystem.current.IsPointerOverGameObject())
{
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;
if (level < data.maxLevel)
{
towerStatsText.text = "Damage " + data.DamageAt(level) + " > " + data.DamageAt(level + 1)
+ "\nRange " + data.RangeAt(level) + " > " + data.RangeAt(level + 1);
upgradeLabel.text = "Upgrade " + data.UpgradeCost(level);
upgradeButton.interactable = true;
}
else
{
towerStatsText.text = "Damage " + data.DamageAt(level) + "\nRange " + data.RangeAt(level);
upgradeLabel.text = "Max level";
upgradeButton.interactable = false;
}
}
public void UpgradeSelected()
{
if (selected.Level >= selected.data.maxLevel)
{
return;
}
if (game.TrySpend(selected.data.UpgradeCost(selected.Level)))
{
selected.Upgrade();
ShowPanel();
}
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.