Verkaufen
Lektion 19 von 25 im Kurs Unity-Spiel: Tower Defense von Coddy.
Beim Verkauf eines Turms erhältst du die Hälfte seiner Kosten zurück, einschließlich der Upgrades. Eine Verteidigung zu versetzen kostet also etwas, aber nicht alles. Der Turm führt eine laufende Summe des für ihn ausgegebenen Geldes: seinen Preis beim Bau plus den Preis jedes Upgrades, sobald es bezahlt wird. Die Rückerstattung beträgt die Hälfte dieser Summe, und eine Ganzzahldivision rundet sie ab. Bei einer Fahrradvermietung wird dieselbe Art von Summe geführt:
public void ExtendRide(int extraHours)
{
paid += extraHours * pricePerHour;
}
public int Deposit => paid / 4;Beim Verkauf wird der Turm zerstört, und das Feld tower des Pads verweist weiterhin auf ihn. Unity behandelt ein zerstörtes Objekt mit == als null, daher ist ab dem nächsten Frame pad.tower == null wahr und das Pad ist ohne zusätzlichen Code wieder frei. Beim Panel ist das anders: Es zeigt weiterhin den verkauften Turm an, und ein Klick auf Upgrade würde ein zerstörtes Objekt erreichen und eine MissingReferenceException auslösen. Beim Verkauf wird nichts ausgewählt, wodurch das Panel ausgeblendet wird.
Aufgabe
MittelVerkaufe einen Turm für die Hälfte seiner Kosten.
- Behalte in
Towerprivate int spent;bei:data.costinStartsowie den Preis jedes Upgrades inUpgrade(). Fügepublic int SellValue => spent / 2;hinzu. - Zeige in
BuildManagerbeim Füllen des PanelsSell 25(den Verkaufserlös) in einem serialisierten TMP_TextsellLabelan. - Schreibe
public void SellSelected(): Erstatte den Verkaufserlös, zerstöre den Turm und wähle nichts aus.
Drücke „Spielen“, baue dann einen Turm, verbessere ihn und verkaufe ihn. Drücke anschließend „Prüfen“.
Probier es selbst
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();
}
}
}
Alle Lektionen in Unity-Spiel: Tower Defense
Übe selbstständig: Unity-Playground