在 start 方法停止之前等待函数完成执行
Wait for a function to finish executing before the start method stops
您好,我正在开发使用随机地形的游戏,我想在该地形上生成对象。为此,我创建了所谓的 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;
}
}
这个脚本当前放在更新方法中时工作得很好,但是我不想这样做,因为它会影响性能。因此,我想知道是否有一种方法可以阻止 Unity 启动方法退出,直到我的 SpawnObjects() 函数停止 运行ning。如果这是不可能的,如果您对我如何 运行 这一次不使用更新功能有任何其他想法,请告诉我。
我对 c# 这门语言还比较陌生,如果我错过了一个简单的修复程序,我深表歉意。任何帮助,将不胜感激。谢谢
因为 SpawnObjects
是一个同步方法 Start
无论如何都不会 return 直到 SpawnObjects
完成。
据我了解你的问题是来自 Physics
is not available during initialization (Awake
, OnEnable
, Start
) but only within or after the Physics block (see ExecutionOrder) 的任何问题,例如在像 FixedUpdate
或 Update
.
这样的方法中
所以回答你的问题:你可以使用 Coroutine and WaitForFixedUpdate
来使你的实例化:
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();
}
您好,我正在开发使用随机地形的游戏,我想在该地形上生成对象。为此,我创建了所谓的 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;
}
}
这个脚本当前放在更新方法中时工作得很好,但是我不想这样做,因为它会影响性能。因此,我想知道是否有一种方法可以阻止 Unity 启动方法退出,直到我的 SpawnObjects() 函数停止 运行ning。如果这是不可能的,如果您对我如何 运行 这一次不使用更新功能有任何其他想法,请告诉我。
我对 c# 这门语言还比较陌生,如果我错过了一个简单的修复程序,我深表歉意。任何帮助,将不胜感激。谢谢
因为 SpawnObjects
是一个同步方法 Start
无论如何都不会 return 直到 SpawnObjects
完成。
据我了解你的问题是来自 Physics
is not available during initialization (Awake
, OnEnable
, Start
) but only within or after the Physics block (see ExecutionOrder) 的任何问题,例如在像 FixedUpdate
或 Update
.
所以回答你的问题:你可以使用 Coroutine and WaitForFixedUpdate
来使你的实例化:
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();
}