【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)

文章目录

  • 先看本次实现的最终效果
  • 前言
  • 把敌人和炮塔全部配置成预制体
  • 炮塔商店
  • 打开商店
  • 放置炮塔
  • 升级炮塔
  • 出售
  • 显示炮塔攻击范围
  • 显示玩家金额和血量
  • 关闭升级面板和商店功能
  • 源码
  • 完结

先看本次实现的最终效果

前言

本期紧接着上一篇,本期主要内容是实现商店、购买、出售、升级等功能。

把敌人和炮塔全部配置成预制体

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第1张图片

炮塔商店

新增TurretSettings

[CreateAssetMenu(fileName = "炮塔商店设置", menuName = "数据/炮塔商店设置")]
public class TurretSettings : ScriptableObject
{
    [SerializeField]
    public GameObject turretPrefab; // 炮塔预制体
    [SerializeField]
    public int turretShopCost; // 炮塔商店价格
    [SerializeField]
    public Sprite turretShopSprite; // 炮塔商店显示的图标
}

配置不同炮塔参数
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第2张图片

绘制商店UI
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第3张图片

新增TurretCard,渲染商品数据,如果前面有绘制价格文本,还可以渲染价格文本,这里我就偷懒不弄了

public class TurretCard : MonoBehaviour
{
    [SerializeField]
    private Image turretImage; // 炮塔图片
    [SerializeField]
    // private TextMeshProUGUI turretCost; // 炮塔价格文本

    public void SetupTurretButton(TurretSettings turretSettings)
    {
        turretImage.sprite = turretSettings.turretShopSprite; // 设置炮塔图片
        // turretCost.text = turretSettings.turretShopCost.ToString(); // 设置炮塔价格文本
    }
}

挂载脚本,并配置

【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第4张图片

新增TurretShopManager,商店管理器

public class TurretShopManager : MonoBehaviour
{
    [SerializeField]
    private GameObject turretCardPrefab; // 炮塔卡片预制体
    [SerializeField]
    private Transform turretPanelContainer; // 放置炮塔卡片的容器

    [Header("炮塔商店配置")]
    [SerializeField]
    private TurretSettings[] turrets; // 可用炮塔设置数组

    private void Start()
    {
        // 在开始时生成炮塔卡片
        for (int i = 0; i < turrets.Length; i++)
        {
            CreateTurretCard(turrets[i]);
        }
    }

    private void CreateTurretCard(TurretSettings turretSettings)
    {
        // 创建炮塔卡片实例
        GameObject newInstance = Instantiate(turretCardPrefab, turretPanelContainer);
        // 设置炮塔卡片实例的比例为默认值
        newInstance.transform.localScale = Vector3.one;
        // 获取炮塔卡片组件,并设置炮塔信息
        TurretCard cardButton = newInstance.GetComponent<TurretCard>();
        cardButton.SetupTurretButton(turretSettings);
    }
}

挂载脚本把那个配置参数
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第5张图片

效果
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第6张图片

打开商店

新增Node ,放置节点

public class Node : MonoBehaviour
{
    public static Action<Node> OnNodeSelected; // 当节点被选中时的事件

    public Turret Turret { get; set; } // 节点上的炮塔

    public void SetTurret(Turret turret)
    {
        Turret = turret; // 设置节点上的炮塔
    }

    public bool IsEmpty()
    {
        return Turret == null; // 判断节点是否为空(没有炮塔)
    }

    public void SelectTurret()
    {
        OnNodeSelected?.Invoke(this); // 触发节点被选中事件
    }
}

挂载并配置点击事件
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第7张图片

新增UI管理器

public class UIManager : MonoBehaviour
{
    [SerializeField, Header("炮塔商店面板")]
    private GameObject turretShopPanel;

    private Node _currentNodeSelected; // 当前选中的节点

    private void NodeSelected(Node nodeSelected)
    {
        _currentNodeSelected = nodeSelected; // 更新当前选中的节点

        if (_currentNodeSelected.IsEmpty())
        {
            turretShopPanel.SetActive(true); // 显示炮塔商店面板
        }
    }

    private void OnEnable()
    {
        Node.OnNodeSelected += NodeSelected; // 注册节点被选中事件的回调方法
    }

    private void OnDisable()
    {
        Node.OnNodeSelected -= NodeSelected; // 取消注册节点被选中事件的回调方法
    }
}

挂载并配置参数
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第8张图片
效果,点击打开商店
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第9张图片

放置炮塔

修改TurretCard

public static Action<TurretSettings> OnPlaceTurret;// 放置炮塔时的事件
public TurretSettings TurretLoaded { get; set; }// 载入的炮塔设置信息

TurretLoaded = turretSettings;

// 放置炮塔的方法
public void PlaceTurret()
{
	// 检查玩家金币是否足够购买炮塔
    if (CurrencySystem.Instance.TotalCoins >= TurretLoaded.turretShopCost)
    {
    	// 扣除对应金币
        CurrencySystem.Instance.RemoveCoins(TurretLoaded.turretShopCost);
        UIManager.Instance.CloseTurretShopPanel();
        // 触发放置炮塔事件,传递炮塔设置信息
        OnPlaceTurret?.Invoke(TurretLoaded);
    }
}

修改UIManager

public void CloseTurretShopPanel()
{
    turretShopPanel.SetActive(false);
}

修改TurretShopManager

private Node _currentNodeSelected;// 当前选中的节点

// 当节点被选中时的回调方法
private void NodeSelected(Node nodeSelected)
{
    _currentNodeSelected = nodeSelected;
}

// 放置炮塔的方法,接受传入的炮塔设置信息
private void PlaceTurret(TurretSettings turretLoaded)
{
    if (_currentNodeSelected != null)
    {
        GameObject turretInstance = Instantiate(turretLoaded.turretPrefab);
        turretInstance.transform.localPosition = _currentNodeSelected.transform.position;
        turretInstance.transform.parent = _currentNodeSelected.transform;
        Turret turretPlaced = turretInstance.GetComponent<Turret>();
        // 在当前节点上设置放置的炮塔
        _currentNodeSelected.SetTurret(turretPlaced);
    }
}

private void OnEnable()
{
    Node.OnNodeSelected += NodeSelected;
    TurretCard.OnPlaceTurret += PlaceTurret;
}

private void OnDisable()
{
    Node.OnNodeSelected -= NodeSelected;
    TurretCard.OnPlaceTurret -= PlaceTurret;
}

配置点击事件
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第10张图片
效果

升级炮塔

绘制升级UI面板
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第11张图片

修改UIManager,开启升级面板

[SerializeField] private GameObject nodeUIPanel;
[SerializeField] private TextMeshProUGUI upgradeText;
[SerializeField] private TextMeshProUGUI sellText;

private void ShowNodeUI()
{
    nodeUIPanel.SetActive(true);
}

private void NodeSelected(Node nodeSelected)
{
    _currentNodeSelected = nodeSelected; // 更新当前选中的节点

    if (_currentNodeSelected.IsEmpty())
    {
        //。。。
    }
    else
    {
        ShowNodeUI();
    }
}

配置
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第12张图片

修改Turret

public TurretUpgrade TurretUpgrade {get;set;}

TurretUpgrade = GetComponent<TurretUpgrade>();

修改UIManager

private void ShowNodeUI()
{
    nodeUIPanel.SetActive(true);
    UpdateUpgradeText();
}

//升级
public void UpgradeTurret()
{
    _currentNodeSelected.Turret.TurretUpgrade.UpgradeTurret();
    UpdateUpgradeText();
}

private void UpdateUpgradeText()
{
    upgradeText.text = _currentNodeSelected.Turret.TurretUpgrade.UpgradeCost.ToString();
}

配置点击事件
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第13张图片
显示等级
修改TurretUpgrade

public int Level { get; set; }

Level = 1;

private void UpdateUpgrade()
{
    CurrencySystem.Instance.RemoveCoins(UpgradeCost);//扣除金额
    UpgradeCost += upgradeCostIncremental;//加下次升级金额
    Level++;
}

修改UIManager

[SerializeField]private TextMeshProUGUI turretLevelText;

private void ShowNodeUI()
{
    //。。。
    UpdateTurretLevel();
}

//升级
public void UpgradeTurret()
{
    //。。。
    UpdateTurretLevel();
}

private void UpdateTurretLevel(){
    turretLevelText.text = $"等级 {_currentNodeSelected.Turret.TurretUpgrade.Level}";
}

配置等级文本参数
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第14张图片
效果
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第15张图片

出售

修改TurretUpgrade

[Header("出售折扣")]
[Range(0, 1)]
[SerializeField] private float sellPert;
public float SellPerc { get; set; }

SellPerc = sellPert;

//计算出售价格
public int GetSellValue()
{
    int sellValue = Mathf.RoundToInt(UpgradeCost * SellPerc);
    return sellValue;
}

修改UIManager

private void ShowNodeUI()
{
    //。。。
    UpdateSellValue();
}

//升级
public void UpgradeTurret()
{
    //。。。
    UpdateSellValue();
}

private void UpdateSellValue()
{
    int sellAmount = _currentNodeSelected.Turret.TurretUpgrade.GetSellValue();
    sellText.text = sellAmount.ToString();
}

//出售
public void SellTurret()
{
    _currentNodeSelected.SellTurret();
    _currentNodeSelected = null;
    nodeUIPanel.SetActive(false);
}

修改Node

public static Action OnTurretSold;

public void SellTurret()
{
    if (!IsEmpty())
    {
        CurrencySystem.Instance.AddCoins(Turret.TurretUpgrade.GetSellValue());
        Destroy(Turret.gameObject);
        Turret = null;
        OnTurretSold?.Invoke();
    }
}

修改TurretShopManager

private void TurretSold()
{
    _currentNodeSelected = null;
}

private void OnEnable()
{
    Node.OnNodeSelected += NodeSelected;
    TurretCard.OnPlaceTurret += PlaceTurret;
    Node.OnTurretSold += TurretSold;
}

private void OnDisable()
{
    Node.OnNodeSelected -= NodeSelected;
    TurretCard.OnPlaceTurret -= PlaceTurret;
    Node.OnTurretSold -= TurretSold;
}

配置出售点击事件
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第16张图片
配置各个炮塔的出售折扣,比如这里我配置0.5,则只能卖一半的钱
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第17张图片
效果
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第18张图片

显示炮塔攻击范围

修改Node

[SerializeField] private GameObject attackRangeSprite;//攻击范围显示
private float _rangesize;
private Vector3 _rangeOriginalsize;

private void Start()
{
    _rangesize = attackRangeSprite.GetComponent<SpriteRenderer>().bounds.size.y;
    _rangeOriginalsize = attackRangeSprite.transform.localScale;
}

private void ShowTurretInfo()
{
    attackRangeSprite.SetActive(true);
    attackRangeSprite.transform.localScale = _rangeOriginalsize * Turret.attackRange / (_rangesize / 2);
}

public void SelectTurret()
{
    OnNodeSelected?.Invoke(this); // 触发节点被选中事件
    if (!IsEmpty())
    {
        ShowTurretInfo();
    }
}

public void SellTurret()
{
    if (!IsEmpty())
    {
        //。。。
        attackRangeSprite.SetActive(false);
    }
}

配置参数
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第19张图片
效果

显示玩家金额和血量

修改UIManager

[SerializeField] private TextMeshProUGUI totalCoinsText;
[SerializeField] private TextMeshProUGUI lifesText;
private void Update()
{
    totalCoinsText.text = "金币:" + CurrencySystem.Instance.TotalCoins.ToString();
    lifesText.text = "生命:" + LevelManager.Instance.TotalLives.ToString();
}

配置
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第20张图片
效果

关闭升级面板和商店功能

修改Node

public void CloseAttackRangeSprite(){
	attackRangeSprite.SetActive(false);
}

修改UIManager

public void CloseNodeUIPanel(){
	currentNodeSelected.CloseAttackRangeSprite();
	nodeUIPanel.SetActive(false);
}

配置
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第21张图片

效果
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第22张图片

关闭商店
【用unity实现100个游戏之15】开发一个类保卫萝卜的Unity2D塔防游戏4(附项目源码)_第23张图片

源码

见本项目最后一节

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

你可能感兴趣的:(#,制作100个游戏,unity,游戏,游戏引擎)