for循环中的内存过载

时间:2017-08-22 00:50:57

标签: c# unity3d memory ram

我正在制作一个对象产生的脚本,在该脚本中,在脚本的开头调用产生函数,并且在其中是一个for循环,每次迭代都会创建一个对象。它首先为它选择一个随机的X位置,然后检查它是否在另一个预制坐标的范围内,这样它们就不会产生太近或者更差,一个在彼此之间。如果它与另一个预制件位于相同的坐标中,它将返回0,同样也为Z轴输出。它还会选择随机的Y轴旋转,因此它不会全部朝向相同的方向。在此之后它产生预制件并设置它的坐标和旋转,之后它检查X或Z轴上的坐标是否为0,如果这两个中的任何一个为0,则返回一次迭代,并且生成的最后一个对象被销毁所以它不会泛滥。这很好用,但是当你想把它设置为产生太多的物体时,就会淹没RAM,因为没有地方可以产生更多的物体。我尝试找到最高的X位置和最高的Z位置并将它们相乘,并将它们设置为正,然后将它们除以预制件之间的空间,但这不起作用,因为它将其设置为非常高的数字。你会如何解决这个问题? 脚本:

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.
    }
}

1 个答案:

答案 0 :(得分:2)

代码调试真的很长,但问题清晰可见,来自SpawnPrefabs函数。目前,当您实例化预制件时,检查生成的位置是否为0。如果0,则从1循环中的i中减去for,然后销毁实例化的对象,然后从当前循环-1再次启动for循环。

因此,InstantiateDestroy的组合并在for循环中再次重复它会导致内存问题。

怎么做:

您必须重新编写整个函数,这也需要修改整个代码。除非需要,否则实例化并销毁该循环中的对象。

1 。在Start()功能中,创建一个预制件。

2 。通过禁用其网格/精灵渲染器使其在场景中不可见。

3 。在for循环中使用该预制件来检查生成的位置是否有效。如果它有效,您现在可以在循环中创建/实例化对象。

当您仅在if (positionX != 0 && positionZ != 0)创建对象时,这可以防止在循环中实例化和销毁对象。