for循环内存过载
Memory overload on for loop
我正在制作一个对象生成脚本,在该脚本的开头调用生成函数,其中有一个 for 循环,每次迭代都会创建一个对象。它首先为它选择一个随机的 X 位置,然后检查它是否在另一个预制件坐标的范围内,这样它们就不会生成得太近或更糟,彼此之间。如果它与另一个预制件在同一坐标中,它将 return 0 并且 Z 轴也是如此。它还会选择一个随机的 Y 轴旋转,因此它不会全部面向同一方向。在此之后它生成预制件并设置它的坐标和旋转,之后它检查 X 或 Z 轴中的坐标是否为 0,如果这两个坐标中的任何一个为 0 它返回一次迭代并销毁最后一个要生成的对象所以它不会泛滥。这非常有效,但是当你想将它设置为生成太多对象时,它会淹没 RAM,因为没有地方可以生成更多对象。我尝试找到最高的 X 位置和最高的 Z 位置并将它们相乘,并将它们都设置为正数,然后将它们除以预制件之间的 space 但这不起作用,因为它将它设置为真的高数。你会如何解决这个问题?
脚本:
using UnityEngine;
using System.Collections;
public class PrefabSpawner : MonoBehaviour {
public int amountOfPrefabs;
public int maxAmountOfPrefabs;
private int currentSpawnedPrefab;
public float spaceBetweenPrefabs;
private float positionX;
private float positionZ;
private float maxPositionX;
private float maxPositionZ;
private float multipliedPosXZ;
private bool previousSpawnHadZero;
public GameObject prefab;
private GameObject point1;
private GameObject point2;
private GameObject currentSpawn;
private Vector2[] positions;
void Start () {
currentSpawnedPrefab = 0;
previousSpawnHadZero = false;
point1 = gameObject.transform.GetChild (0).gameObject;
point2 = gameObject.transform.GetChild (1).gameObject;
if (point1.transform.position.x > point2.transform.position.x)
maxPositionX = point1.transform.position.x;
else
maxPositionX = point2.transform.position.x;
if (point1.transform.position.z > point2.transform.position.z)
maxPositionZ = point1.transform.position.z;
else
maxPositionZ = point2.transform.position.z;
multipliedPosXZ = maxPositionX * maxPositionZ;
if (multipliedPosXZ < 0)
multipliedPosXZ += multipliedPosXZ + multipliedPosXZ;
maxAmountOfPrefabs = Mathf.FloorToInt (multipliedPosXZ / spaceBetweenPrefabs);
if (amountOfPrefabs > maxAmountOfPrefabs)
amountOfPrefabs = maxAmountOfPrefabs;
point1.GetComponent<MeshRenderer> ().enabled = false;
point2.GetComponent<MeshRenderer> ().enabled = false;
gameObject.GetComponent<MeshRenderer> ().enabled = false;
positions = new Vector2[amountOfPrefabs];
SpawnPrefabs (amountOfPrefabs);
}
void SpawnPrefabs (int amount) {
for (int i = 0; i < amount; i++) {
if(previousSpawnHadZero)
i -= 1;
currentSpawn = (GameObject)Instantiate (prefab);
positionX = GetRandomPositionX ();
positionZ = GetRandomPositionZ ();
currentSpawn.transform.position = new Vector3 (positionX, this.transform.position.y + currentSpawn.transform.localScale.y, positionZ);
currentSpawnedPrefab += 1;
if (positionX == 0 || positionZ == 0) {
previousSpawnHadZero = true;
currentSpawnedPrefab -= 1;
Destroy (currentSpawn);
}
if (positionX != 0 && positionZ != 0) {
previousSpawnHadZero = false;
positionX = 0;
positionZ = 0;
}
}
}
IEnumerator Pause () {
yield return null;
}
float GetRandomPositionX () {
//Finds a random position for the X axis and then checks it and returns either 0 if the position is taken or the position if not
}
float GetRandomPositionZ () {
//Finds a random position for the Z axis and then checks it and returns either 0 if the position is taken or the position if not
}
bool CheckPositionAvailable (float pos, int axis) {
//Checks if the position is available.
}
}
调试代码确实很长,但问题很明显,并且来自 SpawnPrefabs
函数。当前,当您实例化预制件时,您会检查生成的位置是否为 0
。如果 0
,则在 for
循环中从 i
中减去 1
然后销毁实例化对象,然后从当前循环 1 再次开始 for 循环。
因此 Instantiate
、Destroy
的组合并在 for
循环中再次重复它会导致内存问题。
要做什么:
您必须重新编写整个函数,这也需要修改您的整个代码。除非需要,否则不要在该循环中实例化和销毁对象。
1。在Start()
函数中,创建一个 prefab。
2。通过禁用其 mesh/sprite 渲染器使其在场景中不可见。
3。在for
循环中使用该预制件来检查生成的位置是否有效。如果有效,您现在可以 create/instantiate 循环中的对象。
这可以防止在 if (positionX != 0 && positionZ != 0)
时仅创建对象时在循环中实例化和销毁对象。
我正在制作一个对象生成脚本,在该脚本的开头调用生成函数,其中有一个 for 循环,每次迭代都会创建一个对象。它首先为它选择一个随机的 X 位置,然后检查它是否在另一个预制件坐标的范围内,这样它们就不会生成得太近或更糟,彼此之间。如果它与另一个预制件在同一坐标中,它将 return 0 并且 Z 轴也是如此。它还会选择一个随机的 Y 轴旋转,因此它不会全部面向同一方向。在此之后它生成预制件并设置它的坐标和旋转,之后它检查 X 或 Z 轴中的坐标是否为 0,如果这两个坐标中的任何一个为 0 它返回一次迭代并销毁最后一个要生成的对象所以它不会泛滥。这非常有效,但是当你想将它设置为生成太多对象时,它会淹没 RAM,因为没有地方可以生成更多对象。我尝试找到最高的 X 位置和最高的 Z 位置并将它们相乘,并将它们都设置为正数,然后将它们除以预制件之间的 space 但这不起作用,因为它将它设置为真的高数。你会如何解决这个问题? 脚本:
using UnityEngine;
using System.Collections;
public class PrefabSpawner : MonoBehaviour {
public int amountOfPrefabs;
public int maxAmountOfPrefabs;
private int currentSpawnedPrefab;
public float spaceBetweenPrefabs;
private float positionX;
private float positionZ;
private float maxPositionX;
private float maxPositionZ;
private float multipliedPosXZ;
private bool previousSpawnHadZero;
public GameObject prefab;
private GameObject point1;
private GameObject point2;
private GameObject currentSpawn;
private Vector2[] positions;
void Start () {
currentSpawnedPrefab = 0;
previousSpawnHadZero = false;
point1 = gameObject.transform.GetChild (0).gameObject;
point2 = gameObject.transform.GetChild (1).gameObject;
if (point1.transform.position.x > point2.transform.position.x)
maxPositionX = point1.transform.position.x;
else
maxPositionX = point2.transform.position.x;
if (point1.transform.position.z > point2.transform.position.z)
maxPositionZ = point1.transform.position.z;
else
maxPositionZ = point2.transform.position.z;
multipliedPosXZ = maxPositionX * maxPositionZ;
if (multipliedPosXZ < 0)
multipliedPosXZ += multipliedPosXZ + multipliedPosXZ;
maxAmountOfPrefabs = Mathf.FloorToInt (multipliedPosXZ / spaceBetweenPrefabs);
if (amountOfPrefabs > maxAmountOfPrefabs)
amountOfPrefabs = maxAmountOfPrefabs;
point1.GetComponent<MeshRenderer> ().enabled = false;
point2.GetComponent<MeshRenderer> ().enabled = false;
gameObject.GetComponent<MeshRenderer> ().enabled = false;
positions = new Vector2[amountOfPrefabs];
SpawnPrefabs (amountOfPrefabs);
}
void SpawnPrefabs (int amount) {
for (int i = 0; i < amount; i++) {
if(previousSpawnHadZero)
i -= 1;
currentSpawn = (GameObject)Instantiate (prefab);
positionX = GetRandomPositionX ();
positionZ = GetRandomPositionZ ();
currentSpawn.transform.position = new Vector3 (positionX, this.transform.position.y + currentSpawn.transform.localScale.y, positionZ);
currentSpawnedPrefab += 1;
if (positionX == 0 || positionZ == 0) {
previousSpawnHadZero = true;
currentSpawnedPrefab -= 1;
Destroy (currentSpawn);
}
if (positionX != 0 && positionZ != 0) {
previousSpawnHadZero = false;
positionX = 0;
positionZ = 0;
}
}
}
IEnumerator Pause () {
yield return null;
}
float GetRandomPositionX () {
//Finds a random position for the X axis and then checks it and returns either 0 if the position is taken or the position if not
}
float GetRandomPositionZ () {
//Finds a random position for the Z axis and then checks it and returns either 0 if the position is taken or the position if not
}
bool CheckPositionAvailable (float pos, int axis) {
//Checks if the position is available.
}
}
调试代码确实很长,但问题很明显,并且来自 SpawnPrefabs
函数。当前,当您实例化预制件时,您会检查生成的位置是否为 0
。如果 0
,则在 for
循环中从 i
中减去 1
然后销毁实例化对象,然后从当前循环 1 再次开始 for 循环。
因此 Instantiate
、Destroy
的组合并在 for
循环中再次重复它会导致内存问题。
要做什么:
您必须重新编写整个函数,这也需要修改您的整个代码。除非需要,否则不要在该循环中实例化和销毁对象。
1。在Start()
函数中,创建一个 prefab。
2。通过禁用其 mesh/sprite 渲染器使其在场景中不可见。
3。在for
循环中使用该预制件来检查生成的位置是否有效。如果有效,您现在可以 create/instantiate 循环中的对象。
这可以防止在 if (positionX != 0 && positionZ != 0)
时仅创建对象时在循环中实例化和销毁对象。