unity3d 创建塔防金钱农场脚本时出现问题

gywdnpxw  于 2022-11-16  发布在  其他
关注(0)|答案(2)|浏览(165)

我对编码很陌生,所以也许答案很简单。
我正在创建一个塔防游戏,现在我正试图编码一个塔,这增加了一个可串行化的金额后,每一波被击败。
我的想法是控制WaveSpawning的脚本应该调用所有的MoneyPump来执行“GiveMoney()"函数,这个函数位于它们的脚本MoneyPump上。但是静态的东西有一个问题,我找不到解决办法。
请帮忙,谢谢。
WaveSpawning的段:

void Update()
    {
        if(spawningWave){return;} 
        if(GameManager.gameOver){enabled = false; return;}

        maxWavePlayTime -= Time.deltaTime;

        if(enemiesAlive > 0 && maxWavePlayTime >= 0f)
        {
            return;
        }

        if(waveIndex == waves.Length && !spawningWave)
        {
            gameManager.LevelWon();
            this.enabled = false;
            return;
        }

//THE IDEA IS TO CALL HERE THE MONEY PUMPS 1 TIME

        if(Countdown <= 0f )
        {
            Stats.WavesSurvived++;
            waveToDisplay = waveIndex + 1;
            WaveIndexDisplay.text = "Wave " + waveToDisplay.ToString();
            spawningWave = true;
            StartCoroutine(SpawnWave());
            Countdown = WaveCounter;
            maxWavePlayTime = StartmaxWavePlayTime;
            return;
        }

MoneyPumps的简短脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoneyPump : MonoBehaviour
{
    public int moneyEveryRound = 25;
    public static bool giveMoney = false;

    public void GiveMoney()
    {
        Stats.Money += moneyEveryRound;
    }
}

生成炮塔的材料:1.

[System.Serializable]
public class TurretBluePrint
{
    public GameObject prefab;
    public int cost;
    public GameObject upgradedPrefab;
    public int upgradeCost;
    public int SellDivider;
}

1.如果我们点击一个指定的按钮,则调用SelectMoneyPump()函数

public class Shop : MonoBehaviour
{
    public TurretBluePrint LaserBeamer;
    public void SelectMoneyPump()
    {
        Debug.Log("Money Pump Purchased");
        BuildManager.SelectTurretToBuild(MoneyPump);
    }
}
public void SelectTurretToBuild (TurretBluePrint turret)
    {
        turretToBuild = turret; 
        DeselectNode();
    }

1.如果我们现在点击一个节点(基本上只是网格上的一个平铺):

public class Node : MonoBehaviour
{
...
void OnMouseDown()
...
BuildTurret(buildmanager.GetTurretToBuild());
...
}

public class BuildManager : MonoBehaviour
{
...
    public TurretBluePrint GetTurretToBuild()
    {
        return turretToBuild;
    }
...
}

1.炮塔建筑

void BuildTurret(TurretBluePrint blueprint)
{
...
turretBlueprint = blueprint;
GameObject _turret = (GameObject)Instantiate(blueprint.prefab, 
GetBuildPosition(), Quaternion.identity);
...

    }
lskq00tm

lskq00tm1#

如果你想调用GiveMoney方法,你需要把你的MoneyPump示例存储在某个地方。

class WaveSpawning
{
    private List<MoneyPump> moneyPumps;
    ...
    void Update()
    {
        ...
        foreach(var mp in MoneyPump)
            mp.GiveMoney();
        ...
    }
}

因此,当你创建新的MoneyPump示例时,你会把它添加到moneyPumps中。然而,把MoneyPump存储在WaveSpawning中并不是最好的做法,因为这是错误的抽象。我建议在另一个类中处理wave的结尾。

class WavesSystem
{
    // Singleton pattern
    private static _wavesSystem _instance;
    // If you use C# 8 or newer
    private static WavesSystem Instance => _instance ??= new WavesSystem();
    // If you use older version
    private static WaveSystem Instance => _instance ?? (_instance = new WavesSystem())

    private WavesSystem()
    {
    }

    public void BeginWave()
    {
        ...
    }

    public void FinishWave()
    {
        ...
    }
}

请注意,如果您的WavesSystem不需要为MonoBehavior,则可以使用上一个示例,否则请尝试another singleton logic

class WavesSystem : MonoBehavior
{
    public static WavesSystem Instance { get; private set; }
    private void Awake() 
    { 
        // If there is an instance, and it's not me, delete myself.
    
        if (Instance != null && Instance != this)
            Destroy(this); 
        else 
            Instance = this; 
    }
    ...
}

重要提示WavesSystemInstanceAwake之后将不为空,因此不要在另一个Awake方法中访问WavesSystem.Instance,因为这可能会很棘手(有时您的classA会在WavesSytem之前加载,它会正常工作,但当您构建应用程序时,加载顺序可能会改变,这将导致错误)

pbpqsu0x

pbpqsu0x2#

我想这个解决方案比我想象的要难找到。我只是稍微改变了一下概念。MoneyPumps不会在每一波被击败后给予钱,而是在一定的时间后给钱,这更容易编码。

public class MoneyPump : MonoBehaviour
{
    public int moneyEveryRound = 25;
    public int moneyEverySeconds = 20;

    void Start()
    {
        StartCoroutine(GiveMoney());
    }

    IEnumerator GiveMoney()
    {
        yield return new WaitForSeconds(moneyEverySeconds);
        Stats.Money += moneyEveryRound;
        Debug.Log("MoneyGiven: " + moneyEverySeconds);
        StartCoroutine(GiveMoney());
    }
}

相关问题