Looking for some more input but this behavior seems odd to me …
Null is null right ? aka in the code below there is no reference left after calling ClearBugged() so the memory should be ready for gc to scoop it up ?
Well not exactly, I had to add array’s to keep track of all my references and then manually destroy them as seen in ClearObjects (), out side the editor there where no issues but test there where minimal, inside editor repeated play/stop will cause memory to “leak” with the ClearBugged() function enabled.
So ether this is a bug or I’m missing something that would explain why the memory does not get cleared ?
Live action: crashing Unity with simple snipit:
using UnityEngine;
using System.Collections;
/* Minimal Bug Report */
/// <summary>
/// Initially we did not keep the array's with references
/// I'm still not convinced I should be but it seems
/// they are the only way to manage the memory ?
/// </summary>
public class MapManager : MonoBehaviour
{
public int seed = 24;
public int worldSize = 2048;
public int mapSize = 512;
public int mapHeight = 1200;
public int mapResolution = 1024;
public int maxLod = 1;
public int pixelError = 1;
public int baseMapDistance = 1000;
public TerrainData[,] mData;
public int mCount;
private GameObject mMaster;
void Start ()
{
mCount = worldSize / mapSize;
StartCoroutine ("InitializeMap");
}
void OnDisable ()
{
//ClearBugged ();
ClearObjects ();
}
void OnDestroy ()
{
//ClearBugged ();
ClearObjects ();
}
private IEnumerator InitializeMap ()
{
//ClearBugged ();
//ClearObjects ();
mData = new TerrainData[mCount, mCount];
mMaster = new GameObject ();
mMaster.name = "Terrain Master";
mMaster.hideFlags = HideFlags.DontSave;
// TODO Note update status
Debug.Log ("=> Base setup complete");
yield return null;
float offset = -(worldSize / 2);
Vector3 position = new Vector3 (offset, 0, offset);
for (int z = 0; z < mCount; z++) {
position.z = offset;
for (int x = 0; x < mCount; x++) {
mData [x, z] = new TerrainData();
mData [x, z].hideFlags = HideFlags.DontSave;
mData [x, z].baseMapResolution = mapResolution;
mData [x, z].alphamapResolution = mapResolution;
mData [x, z].heightmapResolution = mapResolution;
mData [x, z].size = new Vector3 (mapSize, mapHeight, mapSize);
GameObject obj = Terrain.CreateTerrainGameObject (mData [x, z]);
obj.transform.parent = mMaster.transform;
obj.transform.position = position;
obj.name = "Node " + x + "." + z;
obj.hideFlags = HideFlags.DontSave;
//MapData map = mObject [x, z].AddComponent<MapData> ();
//map.SetManager (this);
//map.InitNode ();
Terrain terra = obj.GetComponent<Terrain> ();
terra.basemapDistance = baseMapDistance;
terra.heightmapPixelError = pixelError;
terra.heightmapMaximumLOD = maxLod;
terra.hideFlags = HideFlags.DontSave;
position.z += mapSize;
}
// TODO Note update status
yield return null;
position.x += mapSize;
}
// TODO Note update status
Debug.Log ("=> Tile creation complete");
}
/// <summary>
/// I expect this to work, no references left so ?
/// But even with or without the array's, it will
/// fail to release the memory ...
/// </summary>
private void ClearBugged ()
{
GameObject.DestroyImmediate (mMaster, true);
mMaster = null;
mData = null;
Resources.UnloadUnusedAssets ();
System.GC.Collect ();
}
/// <summary>
/// Clear out generated objects for some reason this
/// does happen within the editor!
/// </summary>
private void ClearObjects ()
{
if (Application.isEditor) {
if (mData != null) {
for (int x = 0; x < mCount; x++) {
for (int y = 0; y < mCount; y++) {
if (mData [x, y] != null) {
DestroyImmediate (mData [x, y]);
mData [x, y] = null;
}
}
}
}
GameObject.DestroyImmediate (mMaster);
mMaster = null;
mData = null;
System.GC.Collect ();
}
}
}
Edit: code now only tracks references to TerrainData for manual destruction.