英文:
Synchronize main loop (Spawner.cs) with subloop on Prefab
问题
我正在进行Unity3D项目,地板需要逐渐展开。我创建了一个名为FloorModule.cs的脚本,在其中使用协程逐渐铺设地板瓷砖。每个下一个模块都必须在前一个完成后立即展开。因此,我创建了Spawner.cs来循环生成一个新的FloorModule.cs,就在前一个完成后。
我似乎无法理解如何使用协程来同步主循环(Spawner.cs)与预制物(FloorModule.cs)上的子循环。
以下是示例链接:https://1drv.ms/u/s!AkVZpIE6f1GV4M5Ju7G5zPOrQcCe8w?e=QrghRT
P.S.
在给定的示例中,随着循环的进行,我使用"Reference.cs"类来更改一些变量的值。
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;
void Start()
{
spawnPoint = GetComponent<Transform>();
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(0.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_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;
}
}
我尝试使用协程,但不幸的是,在给定的上下文中,我意识到无法解决这个任务。
英文:
I'm working on Unity3d project where the floor has to unfold gradually. I created a script FloorModule.cs where using coroutine the floor tiles are laying out gradually. Each next module has to unfold right after previous is completed. There for I created Spawner.cs to loop a new FloorModule.cs right after previous one is completed.
I can't seem to get my head around how to use coroutine to synchronize the mainloop (Spawner.cs) with subloop on prefab (FloorModule.cs).
Here is the link to the example
https://1drv.ms/u/s!AkVZpIE6f1GV4M5Ju7G5zPOrQcCe8w?e=QrghRT
P.S.
In given example, as loop goes forward I'm using "Reference.cs" class to change some variable values .
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;
}
}
I tried to use coroutines unfortunately in given context I realize it's impossible for me to resolve this task.
答案1
得分: 1
从另一个协程中可以生成一个协程。
对您的代码的更改
在引用中将public GameObject instance;
更改为public FloorModule instance;
在生成器中将public GameObject FloorModPrefab;
更改为public FloorModule FloorModPrefab;
删除FloorModule
的Start
中的代码。
修改FwFloorDelay
为
public IEnumerator FwFloorDelay(Transform origin = null)
{
if (origin == null)
{
origin = transform;
}
...
}
在SpawnModules
中链接地板延迟协程
IEnumerator SpawnModules()
{
for (int i = 0; i < referenceScript.Length; i++)
{
...
yield return referenceScript[i].instance.FwFloorDelay();
}
}
英文:
You can yield a coroutine from within another coroutine.
Changes to your Code
In References change public GameObject instance;
to public FloorModule instance;
In Spawner change public GameObject FloorModPrefab;
to public FloorModule FloorModPrefab;
Remove the code from Start
of FloorModule
.
Modify FwFloorDelay
to
public IEnumerator FwFloorDelay(Transform origin = null)
{
if (origin == null)
{
origin = transform;
}
...
}
In SpawnModules
, chain the floor delay coroutine
IEnumerator SpawnModules()
{
for (int i = 0; i < referenceScript.Length; i++)
{
...
yield return referenceScript[i].instance.FwFloorDelay();
}
}
答案2
得分: 0
你的目标不应该是同步不同的协程,而是让代码在一个协程中按顺序运行。
例如,你可以将References.Setup()设计为异步操作,然后让它直接调用FloorModel.FwFloorDelay,而不是让FloorModel启动自己独立的协程。
英文:
Your goal should not be to synchronize separate coroutines, but rather to get the code running sequentially in one coroutine.
For example, you could make References.Setup() asynchronous, and then have it invoke FloorModel.FwFloorDelay directly instead of the FloorModel starting its own separate coroutine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论