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

如何在Unity中同步Spawner主协程与FloorModule子协程?

Unity3D 地板模块协程同步问题

我正在开发Unity3D项目,需要实现地板逐步展开效果。已编写FloorModule.cs脚本,通过协程逐步生成地砖;要求每个地板模块完成展开后再启动下一个,因此创建了Spawner.cs脚本,但无法实现主循环(Spawner.cs)与预制体子循环(FloorModule.cs)的协程同步。同时使用References.cs类修改变量值。


原脚本代码

FloorModule.cs

public class FloorModule : MonoBehaviour
{
    public float zSpacer = 0f;

    public int instPrefabCount;
    public Transform spawnPoint;
    public int lenght = 15;
    public int width = 5;

    public GameObject floorTiles;

    void Start()
    {
        spawnPoint = GetComponent<Transform>();

        StartCoroutine(FwFloorDelay(spawnPoint));
    }

    public IEnumerator FwFloorDelay(Transform origin)
    {
        for (int l = 0; l < lenght; l++)
        {
            float xAngle = 90;
            float yPos = 0;
            float zPos = 0 + l;

            for (int w = 0; w < width; w++)
            {
                int xSelection = Random.Range(0, 6);
                GameObject xFloor = Instantiate(floorTiles, origin);

                TileStatusNames(xFloor, l, w);

                // defining positiona and angles
                float xPos = w + (zSpacer * w);
                xFloor.transform.localEulerAngles = new Vector3(xAngle, 0, 0);
                xFloor.transform.localPosition = new Vector3(xPos, yPos, zPos);

                yield return new WaitForSeconds(.05f);

            }
        }
    }
}

Spawner.cs

public class Spawner : MonoBehaviour
{
    public GameObject FloorModPrefab;
    public References[] referenceScript;

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

    IEnumerator SpawnModules()
    {
        for (int i = 0; i < referenceScript.Length; i++)
        {
            referenceScript[i].instance =
                Instantiate(FloorModPrefab, referenceScript[i].ref_spawnPoint.position, referenceScript[i].ref_spawnPoint.rotation);

            referenceScript[i].ref_instFloorModCount = i + 1;
            referenceScript[i].Setup();
            yield return new WaitForSeconds(5f);
        }
    }
}

References.cs

[Serializable]
public class References
{
    FloorModule prefabObjScript;
    public GameObject instance; 

    public int ref_instFloorModCount;
    public Transform ref_spawnPoint;
    public int ref_Width = 5;
    public int ref_Lenght = 15;

    public void Setup()
    {
        // Get references to the components.
        prefabObjScript = instance.GetComponent<FloorModule>();

        // Set the player numbers to be consistent across the scripts.
        prefabObjScript.instPrefabCount = ref_instFloorModCount;
        prefabObjScript.spawnPoint = ref_spawnPoint;
        prefabObjScript.width = ref_Width;
        prefabObjScript.lenght = ref_Lenght;
    }
}

解决方法

核心问题是Spawner的协程无法精准等待FloorModule内部的展开逻辑完成,以下是修改方案:

1. 修改FloorModule.cs

取消自动启动协程,改为外部控制启动时机,并提供可被外部等待的协程入口:

public class FloorModule : MonoBehaviour
{
    public float zSpacer = 0f;

    public int instPrefabCount;
    public Transform spawnPoint;
    public int length = 15; // 修正拼写错误
    public int width = 5;

    public GameObject floorTiles;

    // 移除自动启动协程的Start方法,改为外部调用
    // void Start() { ... }

    // 对外提供的展开入口,返回协程供外部等待
    public IEnumerator StartFloorExpansion()
    {
        spawnPoint = GetComponent<Transform>();
        yield return StartCoroutine(FwFloorDelay(spawnPoint));
    }

    public IEnumerator FwFloorDelay(Transform origin)
    {
        for (int l = 0; l < length; l++)
        {
            float xAngle = 90;
            float yPos = 0;
            float zPos = 0 + l;

            for (int w = 0; w < width; w++)
            {
                int xSelection = Random.Range(0, 6);
                GameObject xFloor = Instantiate(floorTiles, origin);

                TileStatusNames(xFloor, l, w);

                float xPos = w + (zSpacer * w);
                xFloor.transform.localEulerAngles = new Vector3(xAngle, 0, 0);
                xFloor.transform.localPosition = new Vector3(xPos, yPos, zPos);

                yield return new WaitForSeconds(.05f);
            }
        }
    }

    // 补全缺失的TileStatusNames方法(根据你的逻辑实现)
    private void TileStatusNames(GameObject tile, int l, int w)
    {
        // 你的状态命名逻辑
    }
}

2. 修改References.cs

公开FloorModule引用,并提供启动展开的方法:

[Serializable]
public class References
{
    public FloorModule prefabObjScript; // 改为公开,方便外部获取
    public GameObject instance; 

    public int ref_instFloorModCount;
    public Transform ref_spawnPoint;
    public int ref_Width = 5;
    public int ref_Length = 15; // 修正拼写错误

    public void Setup()
    {
        prefabObjScript = instance.GetComponent<FloorModule>();

        prefabObjScript.instPrefabCount = ref_instFloorModCount;
        prefabObjScript.spawnPoint = ref_spawnPoint;
        prefabObjScript.width = ref_Width;
        prefabObjScript.length = ref_Length;
    }

    // 提供启动模块展开的方法,返回协程供Spawner等待
    public IEnumerator StartModuleExpansion()
    {
        yield return prefabObjScript.StartFloorExpansion();
    }
}

3. 修改Spawner.cs

替换固定等待时间,改为等待当前模块展开协程完成:

public class Spawner : MonoBehaviour
{
    public GameObject FloorModPrefab;
    public References[] referenceScript;

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

    IEnumerator SpawnModules()
    {
        for (int i = 0; i < referenceScript.Length; i++)
        {
            referenceScript[i].instance =
                Instantiate(FloorModPrefab, referenceScript[i].ref_spawnPoint.position, referenceScript[i].ref_spawnPoint.rotation);

            referenceScript[i].ref_instFloorModCount = i + 1;
            referenceScript[i].Setup();
            
            // 等待当前模块完全展开后,再生成下一个模块
            yield return StartCoroutine(referenceScript[i].StartModuleExpansion());
        }
    }
}

关键说明

  • 取消FloorModule自动启动协程,改为由Spawner控制启动时机,确保模块生成后才开始展开
  • 通过yield return StartCoroutine(...)让Spawner的主协程等待每个模块的展开协程完成,实现精准同步
  • 修正了原代码中的拼写错误(lenght改为length),避免潜在逻辑bug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:50:27