【问题标题】:Instantiating an object after updating a variable isn't working as expected更新变量后实例化对象未按预期工作
【发布时间】:2022-12-31 01:53:08
【问题描述】:

假设我有两个脚本:

  • 生成管理器
  • 敌人

SpawnManager 中,我有函数SpawnEnemyWave 应该实例化 3 个敌人,如果随机数生成器低于 5,那么其中一个应该有更高的移动速度,另一个根本不应该移动。

SpawnManager

bool toughEnemy = true;
int waveNumber = 3;
float randomNumber = Random.Range(0, 10);

void Start()
{
    SpawnEnemyWave(waveNumber);
}

void SpawnEnemyWave(int enemiesToSpawn) 
{
    float randomNumber = Random.Range(0, 10);
    print(randomNumber);

    for (int i = 0; i < enemiesToSpawn; i++) 
    {
        if ((randomNumber < 5) && toughEnemy)
        {
            print("Tough");
            Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
            toughEnemy = false; //I make sure there is only one tough enemy per wave
        } 
        else
        {
            print("Weak");
            Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
        }
    }
}

Enemy 中,我正在检查 toughEnemy 变量是否设置为 true 以在实例化之前修改敌人的速度,我将这些 if 语句放在 start 函数中,因为我认为敌人被实例化的时间是叫。

void Start()
{
    spawnManager = GameObject.Find("Spawn Manager").GetComponent<SpawnManager>();

    if (spawnManager.toughEnemy)
    {
        speed = 1;
        print("Speed " + speed);
    }
    else
    {
        speed = 0;
        print("Speed " + speed);
    }
}

问题是,当日志中的随机数为 0 时,我看到了这个......

  • 随机数:0
  • 艰难(for循环中的i为0)
  • 弱(for循环中的i为1)
  • 弱(for循环中的i为2)
  • 速度0
  • 速度0
  • 速度0

而我所期待的是如下所示,因为我在实例化敌人之前首先修改了 SpawnManager 脚本中的变量。

  • 随机数:0
  • 艰难(for循环中的i为0)
  • 速度 1
  • 弱(for循环中的i为1)
  • 速度0
  • 弱(for循环中的i为2)
  • 速度0

我在这里错过了什么?

【问题讨论】:

  • 你为什么还要通过经理填充ToughEnemy?强不强,敌人自己不应该知道吗?只是一个旁...
  • @MakePeaceGreatAgain 你是对的,这更有意义。

标签: c# unity3d variables objectinstantiation


【解决方案1】:

定时。您认为 Start 将在实例化对象时调用,这部分是正确的。但是,它将在下一帧开始时被调用。在当前循环中,您正在设置要实例化的对象,然后将 toughEnemy 设置为 true。下一帧开始时,所有的敌人都认为设置了一个强悍的敌人,你看到的输出是正确的。

如果你想让经理控制敌人,我个人会包含类似 Setup 方法的东西,由经理调用。例如,在 Enemy 脚本中:

public bool isSetup { get; private set; }
public bool isTough { get; private set; }

void Setup(bool tough)
{
    if ( isSetup ) return;
    isSetup = true;
    isTough = tough;
    speed = tough ? 1 : 0;
}

然后,当您在管理器中实例化敌人时,执行如下操作:

for (int i=0; i<enemiesToSpawn; i++)
{
    var enemy = Instantiate( enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation );
    var e = enemy.GetComponent<Enemy> ( );
    if ((randomNumber < 5) && toughEnemy)
    {
        print("Tough");
        toughEnemy = false; //I make sure there is only one tough enemy per wave
        e.Setup(true);
    }
    else
    {
        print("Weak");
        e.Setup(false);
    }
}

这是“框架”的生命周期

请注意,Update 方法处理大约发生在框架生命周期的中间。您在同一个 Update 方法中实例化 3 个对象。 THEN … 帧结束,在下一帧开始时,触发每个新对象的 Start 事件。

【讨论】:

  • 实际上,我在一次实例化后将 toughEnemy 设置为 false,这样其余的敌人就会变弱。
  • 是的,但是,你在你的循环中调用了 3 次Instantiate,在同一帧中。你要求 Unity 创建 3 个新对象,它很乐意这样做,但是,Start 将在下一帧开始时被调用,在你已经将你的管理器 toughEneny 设置为 true 之后。
  • 我现在明白了,点击了一些东西,现在我明白了“问题”。
  • 谢谢你的帮助!你的回答很完美,对我理解这个话题有很大帮助。
【解决方案2】:

我会通过在 Enemy 脚本本身中放置 toughEnemy 标志来做到这一点。然后,我将向 Enemy 添加一个 SetTough() 方法,在 Enemy 实例化后,我将通过 GetComponent() 从 SpawnManager 调用该方法。

【讨论】:

    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 2019-05-28
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 2017-08-14
    相关资源
    最近更新 更多