You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新变量后实例化对象未达预期的Unity技术问题

问题分析与解决

问题背景

我有两个Unity脚本:SpawnManager和Enemy。需求是在SpawnManager的SpawnEnemyWave函数中生成3个敌人:当随机数小于5时,生成1个高移动速度的tough enemy,其余为无移动速度的weak enemy。

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; //确保每波仅1个tough enemy
        } 
        else
        {
            print("Weak");
            Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
        }
    }
}

Enemy 代码

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

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

问题现象

当随机数为0时,日志显示有1个Tough敌人,但所有敌人的speed均为0;预期应为第一个敌人speed=1,其余为0。


问题根源

核心是Unity脚本的执行时机不匹配:

  • Instantiate创建Enemy对象后,该对象的Start方法不会立即执行,而是延迟到当前帧所有同步逻辑执行完毕后才触发。
  • SpawnManager生成第一个Tough敌人后,立刻将toughEnemy设为false。等所有Enemy的Start方法执行时,读取到的toughEnemy已经是false,导致所有敌人的speed都被设为0。

解决方案

方案1:实例化时直接设置敌人属性(推荐)

不需要让Enemy读取SpawnManager的状态,而是在生成时直接给Enemy赋值,逻辑更清晰且避免时机问题:

修改SpawnManager的循环逻辑:

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

    for (int i = 0; i < enemiesToSpawn; i++) 
    {
        bool isTough = (randomNumber < 5) && !hasSpawnedTough;
        GameObject enemy = Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
        Enemy enemyComp = enemy.GetComponent<Enemy>();

        if (isTough)
        {
            print("Tough");
            enemyComp.speed = 1;
            hasSpawnedTough = true;
        } 
        else
        {
            print("Weak");
            enemyComp.speed = 0;
        }
    }
}

简化Enemy脚本:

public float speed;

void Start()
{
    print("Speed " + speed);
}

方案2:传递敌人类型标记

给Enemy添加一个公共标记变量,生成时直接赋值:

SpawnManager修改:

void SpawnEnemyWave(int enemiesToSpawn) 
{
    float randomNumber = Random.Range(0, 10);
    print(randomNumber);
    bool shouldSpawnTough = randomNumber < 5;
    bool spawnedTough = false;

    for (int i = 0; i < enemiesToSpawn; i++) 
    {
        bool isCurrentTough = shouldSpawnTough && !spawnedTough;
        GameObject enemy = Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
        enemy.GetComponent<Enemy>().isTough = isCurrentTough;

        if (isCurrentTough)
        {
            print("Tough");
            spawnedTough = true;
        } 
        else
        {
            print("Weak");
        }
    }
}

Enemy脚本修改:

public bool isTough;
public float speed;

void Start()
{
    speed = isTough ? 1 : 0;
    print("Speed " + speed);
}

方案3:调整脚本执行顺序(不推荐)

在Unity编辑器的Project Settings -> Script Execution Order中,将Enemy的Start执行顺序设为早于SpawnManager。但这种方式依赖Unity的执行顺序规则,后续维护容易出问题,不建议使用。


内容的提问来源于stack exchange,提问作者Heijs7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:50:27