アップグレード
Coddyの「Unityゲーム:タワーディフェンス」コースのレッスン 18/25。
パネルの「アップグレード」ボタンはUpgradeSelectedを呼び出します。GameManagerのTrySpendを通じて支払うため、所持金が足りなければ何も変わりません。最大レベルでは、もう購入できるものはありません。ステータスには現在の値だけが表示され、ボタンは操作できません。
パネルは3Dビュー上に表示されるUIで、パネル内のボタンをクリックすると、BuildManagerにもマウスの押下として認識されます。レイはボタンを通り抜けて背後の地面に届き、ボタンを離す前にBuildManagerがパネルを閉じてしまいます。ポインターがUI上にある間はEventSystem.current.IsPointerOverGameObject()がtrueになるため、BuildManagerは早期に処理を抜け、ボタンにクリックを任せます。
チャレンジ
中級パネルから選択したタワーをアップグレードします。
public void UpgradeSelected()を記述します。maxLevel未満のとき、game.TrySpend(data.UpgradeCost(level))で支払いができたら、タワーをアップグレードしてパネルを更新します。maxLevelでは、パネルに2行でDamage 4とRange 5.5、さらにMax levelが表示され、シリアライズされたupgradeButtonは操作できません。Updateでは、EventSystem.current.IsPointerOverGameObject()のときに処理を返します。
「プレイ」を押し、タワーを建ててクリックし、2回アップグレードします。パネルに最大レベルと表示されます。その後、「確認」を押します。
自分で試してみよう
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);
}
}
Unityゲーム:タワーディフェンスのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド