這是最近做項目時發現的一個內存管理機制上的一個缺陷,但是我並不知道這究竟是不是一個bug,因爲他可以造成內存泄漏,但是卻能避開野指針,容我細細道來吧。(完整demo演示地址:http://www.demodashi.com/demo/11529.html)
第一步,我先創建一個類TestObj,類TestObj在生成時會申請一大塊內存,並且類TestObj中有一個公開方法dddd(原諒我的隨便)如下:
using UnityEngine;
using System.Collections;
public class TestObj : MonoBehaviour {
public Texture2D tx2d = null;
public int xxx = 112;
public dui aa;
// Use this for initialization
void Awake () {
tx2d = new Texture2D(2048, 1536, TextureFormat.ARGB32, false, true);
aa = new dui();
}
// Update is called once per frame
void Update () {
}
public void dddd()
{
}
}
第二步,我們需要一個生成TestObj的測試類,這個測試類如下:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class MemeryTesr : MonoBehaviour {
List<GameObject> m_objList = new List<GameObject>();
static List<UnityEngine.Events.UnityAction> m_texList = new List<UnityEngine.Events.UnityAction>();
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void CreateObj()
{
GameObject obj = new GameObject("new obj");
TestObj t2d = obj.AddComponent<TestObj>();
m_objList.Add(obj);
m_texList.Add(t2d.dddd);
}
public void DestroyObj()
{
if (m_objList.Count > 0)
{
Destroy(m_objList[m_objList.Count - 1]);
m_objList.RemoveAt(m_objList.Count - 1);
}
Resources.UnloadUnusedAssets();
}
public void jumpScene()
{
SceneManager.LoadScene("load");
}
}
我們先生成一大堆對象,如下圖:
將對象都刪除,並且跳轉場景:
我們會發現,雖然我們已經Destroy了全部的TestObj附着的GameObject,但是內存中卻還會一直駐留着大量沒有清理的內存。
其實原因在於我每次新創建的TestObj都把其中的方法dddd放進了static List<UnityEngine.Events.UnityAction> m_texList = new List<UnityEngine.Events.UnityAction>();
而這個是一個靜態成員,會一直存在於遊戲的整個過程,只要它沒有被銷燬,則TestObj都會存在於內存中,這雖然能解決新手程序員常寫出來的野指針問題,但是卻實在是造成內存泄漏。