等待函数完成执行,然后再停止启动方法

时间:2019-03-18 19:45:25

标签: c# unity3d game-engine game-development

嗨,我正在研究使用随机地形的游戏,我想在该地形上生成对象。为此,我创建了所谓的Surface Populator脚本。

这是脚本:

public SurfaceSpawnerData spawnerData;

private float randomX;
private float randomZ;
private Renderer r;

void Start()
{
    r = GetComponent<Renderer>();
    for (int i = 0; i < spawnerData.spawnableObjects.Length; i++)
    {
        spawnerData.spawnableObjects[i].currentObjects = 0;
    }
    spawnerData.SpawnedObjects.Clear();

    SpawnObjects();
}

void Update()
{

}

void SpawnObjects()
{
    RaycastHit hit;

    for (int i = 0; i < spawnerData.spawnableObjects.Length; i++)
    {
        int currentObjects = spawnerData.spawnableObjects[i].currentObjects;
        int numOfObjects = spawnerData.spawnableObjects[i].numberOfObjects;

        if (currentObjects != numOfObjects)
        {
            if (Physics.Raycast(new Vector3(randomX, r.bounds.max.y + 5f, randomZ), -Vector3.up, out hit))
            {
                randomX = Random.Range(r.bounds.min.x, r.bounds.max.x);
                randomZ = Random.Range(r.bounds.min.z, r.bounds.max.z);

                if (hit.point.y >= spawnerData.spawnableObjects[i].spawnerStartHeight && hit.point.y <= spawnerData.spawnableObjects[i].spawnerEndHeight)
                {
                    spawnerData.SpawnedObjects.Add(Instantiate(spawnerData.spawnableObjects[i].spawnablePrefab, hit.point, Quaternion.identity));
                    spawnerData.spawnableObjects[i].currentObjects += 1;
                }
            }
        }
    }
}

脚本还从可编写脚本的对象中获取数据:

[CreateAssetMenu]
public class SurfaceSpawnerData : ScriptableObject
{
    public SpawnableObjects[] spawnableObjects;
    public List<GameObject> SpawnedObjects; 

    [System.Serializable]
    public class SpawnableObjects
    {
        public GameObject spawnablePrefab;
        public float spawnerStartHeight = 2f;
        public float spawnerEndHeight;
        public int currentObjects;
        public int numberOfObjects;
    }
}

当将此脚本放入update方法中时,该脚本当前可以很好地工作,但是由于其对性能的影响,我不想这样做。因此,我想知道是否有一种方法可以停止Unity start方法的退出,直到我的SpawnObjects()函数停止运行为止。如果这是不可能的,如果您对如何仅运行一次而不使用更新功能有任何其他想法,请通知我。

我对使用C#作为一种语言还是比较陌生的,如果我错过了一个简单的解决方法,我感到抱歉。任何帮助,将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:2)

由于SpawnObjects是同步方法,Start直到SpawnObjects完成后才会返回。

据我了解,您的问题是,Physics中的任何内容在初始化期间(AwakeOnEnableStart)不可用,而仅在物理块(请参阅ExecutionOrder),例如例如FixedUpdateUpdate


所以回答您的问题:您可以使用CoroutineWaitForFixedUpdate来进行实例化:

void Start()
{
    r = GetComponent<Renderer>();
    for (int i = 0; i < spawnerData.spawnableObjects.Length; i++)
    {
        spawnerData.spawnableObjects[i].currentObjects = 0;
    }
    spawnerData.SpawnedObjects.Clear();

    StartCoroutine(DoInstantiate());
}

private IEnumerator DoInstantiate()
{
    // wait until Physics are initialized
    yield return new WaitForFixedUpdate();

    SpawnObjects();
}

或在ScriptReference/Coroutine中可以看到,您可以通过直接将Start设置为例行程序来简化此过程喜欢

IEnumerator Start()
{
    r = GetComponent<Renderer>();
    for (int i = 0; i < spawnerData.spawnableObjects.Length; i++)
    {
        spawnerData.spawnableObjects[i].currentObjects = 0;
    }
    spawnerData.SpawnedObjects.Clear();

    // wait until Physics are initialized
    yield return new WaitForFixedUpdate();

    SpawnObjects();
}