Menu
CoddyTech

Melhoria

Lição 12 de 18 do curso Jogo de Unity: Defesa de Torres da Coddy.

Ao clicar em uma torre, abre-se um painel com seu nível e um botão de aprimoramento. Cada nível aumenta o dano e o alcance da torre, e cada aprimoramento custa mais que o anterior. Os níveis seguem uma regra, então o asset contém a regra em vez de uma lista de números: os atributos no nível 1, o que cada nível acrescenta e o preço de um aprimoramento. Os métodos no ScriptableObject calculam o restante, para que todo script que consultar obtenha a mesma resposta. Uma plantação de um jogo de fazenda:

public int YieldAt(int level)
{
    return baseYield + yieldPerLevel * (level - 1);
}

A torre mantém apenas seu próprio level, e o painel mostra os números do próximo nível ao lado dos atuais, para que o jogador veja o que o dinheiro compra. Um clique em uma torre atinge uma de suas partes, a base ou o topo, que são filhas da torre, então hit.collider.GetComponentInParent<Tower>() encontra a torre à qual pertencem: ele verifica o objeto atingido e, em seguida, seus objetos-pai.

O painel é uma interface sobre a visualização 3D, e um clique no botão de aprimoramento também é um pressionamento do mouse que o BuildManager detecta. Seu raio atravessa o botão até o chão atrás dele, e o BuildManager fecha o painel antes que o botão seja solto. EventSystem.current.IsPointerOverGameObject() é true enquanto o ponteiro está sobre a interface, então o BuildManager retorna imediatamente e deixa esses cliques para os botões.

challenge icon

Desafio

Médio
  1. Em TowerData, adicione os ints públicos maxLevel, upgradeCost e damagePerLevel, e o float público rangePerLevel. Adicione int DamageAt(int level) e float RangeAt(int level): no nível 1, o dano e o alcance são os do próprio asset, e cada nível acima dele acrescenta o valor por nível. Adicione int UpgradeCost(int level), o preço para subir a partir desse nível: upgradeCost multiplicado pelo nível.
  2. Em Tower, mantenha um int privado level que começa em 1, legível como public int Level => level;. Atire com DamageAt(level) e mire em alvos dentro de RangeAt(level). Adicione public void Upgrade(), que incrementa o nível em 1.
  3. Em BuildManager, clicar em uma torre a seleciona, e clicar em qualquer outra coisa não seleciona nada (clicar em uma plataforma livre ainda constrói nela). O towerPanel serializado aparece somente enquanto uma torre estiver selecionada, com Arrow level 1 em towerNameText, Damage 2 > 3 e Range 4.5 > 5 em duas linhas em towerStatsText, e Upgrade 40 em upgradeLabel. Em maxLevel, os atributos mostram apenas os valores atuais, o rótulo diz Max level e upgradeButton não é interativo.
  4. Escreva public void UpgradeSelected(), que é chamado pelo botão Upgrade: abaixo do nível máximo, quando o GameManager puder pagar a melhoria, aprimore a torre e atualize o painel. Em Update, ignore cliques sobre a interface.

Pressione Play, construa uma torre, clique nela e aprimore-a; em seguida, Check.

Experimente você mesmo

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);

    private Tower chosen;

    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]);
    }

    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) && 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);
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Jogo de Unity: Defesa de Torres