2016-05-28 9 views
1

Ich lade Ressourcen in Einheit, aber ich weiß nicht, wie Sie sie aus dem Speicher freigeben.Unity-Speicher Problem Ressourcen Bild

Ich habe ein Skript, die Vorschau-Bilder wie diese lädt:

//load the 12 images 
     while (currentPreviewNumber < 12) { 
      Debug.Log (currentPreviewNumber); 
      byte[] tBytes = System.IO.File.ReadAllBytes (Application.persistentDataPath + "/" + currentPreviewNumber + ".jpg"); 
      Texture2D texture = new Texture2D (100, 100); 
      texture.LoadImage (tBytes); 

      sprites [currentPreviewNumber] = Sprite.Create (texture, new Rect (0, 0, mCamera.width, mCamera.height), 
       new Vector2 (0.5f, 0.5f), 
       40); 

      currentPreviewNumber++; 
     } 

aber jedes Mal laufe ich den Code meines Speicherverbrauch verdoppelt. Wie kann ich die Sprites beim zweiten Ausführen aus dem Speicher freigeben?

Antwort

2

Sie können nicht. Manche würden sagen: GC.Collect(), aber das ist hier nicht der Fall. Ihr Code kann optimiert werden, um die Speicherzuweisung zu reduzieren.

. Was die meisten dieser Speicherzuweisung verursacht, ist Sprite.Create. Es weist Speicher so schlecht zu. Die Lösung besteht darin, Ihr Design zu ändern. Verwenden Sie RawImage Array anstelle von Sprite Array und diese unnötige Speicherzuweisung würde weggehen.

. Texture2D texture = new Texture2D(100, 100); reserviert auch Speicher. Da es immer von ist, können Sie es wiederverwenden. Machen Sie es global und rufen Sie einmal am Anfang new Texture2D(100, 100);. Dies spart Speicherzuweisung.

.Verwendung StringBuilderApplication.persistentDataPath + "/" + currentPreviewNumber + ".jpg"

verketten. Application.persistentDataPath reserviert Speicher. Speichern Sie es in einem temporären Wert in der Start()-Funktion, anstatt es wiederholt in der while-Schleife aufzurufen.

Lösung 1:

public RawImage defaultRawImage; 
RawImage[] rawImages; 
Texture2D texture = null; 
int currentPreviewNumber = 0; 
string appPath; 
System.Text.StringBuilder imagePath; 

void Start() 
{ 
    appPath = Application.persistentDataPath; 

    //Init Texture 2D 
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false); 

    //Init All 12 Raw Images 
    rawImages = new RawImage[12]; 
    for (int i = 0; i < rawImages.Length; i++) 
    { 
     rawImages[i] = Instantiate(defaultRawImage) as RawImage; 
    } 

    //Init String Builder 
    imagePath = new System.Text.StringBuilder(300); 
} 

void loadPreviewOptimized() 
{ 
    while (currentPreviewNumber < 12) 
    { 
     //Debug.Log(currentPreviewNumber); 
     imagePath.Capacity = 0; 
     imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg"); 

     //Read File 
     byte[] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString()); 
     texture.LoadImage(tBytes); 

     rawImages[currentPreviewNumber].texture = texture; 
     currentPreviewNumber++; 
    } 
} 

byte[] tBytes = System.IO.File.ReadAllBytes(imagePath.ToString()); Der Code weist Speicher Bytes zurückzukehren. Um es loszuwerden, make tBytes eine globale Variable, dann Speicher nur einmal zuweisen. Unten ist ein vollständiger Code, wenn Sie die Speicherzuweisung mit Datei beenden möchten. ReadAllBytes.

Lösung 2:

public RawImage defaultRawImage; 
RawImage[] rawImages; 
Texture2D texture = null; 
int currentPreviewNumber = 0; 
string appPath; 
System.Text.StringBuilder imagePath; 
byte[] tBytes; 

void Start() 
{ 
    appPath = Application.persistentDataPath; 

    //Init Texture 2D 
    texture = new Texture2D(100, 100, TextureFormat.RGB24, false); 

    //Init All 12 Raw Images 
    rawImages = new RawImage[12]; 
    for (int i = 0; i < rawImages.Length; i++) 
    { 
     rawImages[i] = Instantiate(defaultRawImage) as RawImage; 
    } 

    //Init String Builder 
    imagePath = new System.Text.StringBuilder(300); 
    tBytes = new byte[90000]; 
} 


void loadPreviewOptimized() 
{ 
    while (currentPreviewNumber < 12) 
    { 
     //Debug.Log(currentPreviewNumber); 

     //Reset Capacity before Reading 
     imagePath.Capacity = 0; 
     imagePath.Append(appPath).Append("/").Append(currentPreviewNumber).Append(".jpg"); 

     //Read File 
     using (System.IO.FileStream myfile = System.IO.File.Open(imagePath.ToString(), System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite)) 
     { 
      //Check if array size is enough before writing 
      if (tBytes.Length >= myfile.Length) 
      { 
       //OK (Write file to tBytes array) 
       myfile.Read(tBytes, 0, (int)myfile.Length); 
       texture.LoadImage(tBytes); 
      } 
      else 
      { 
       //NOT OK (Resize array size) 
       tBytes = new byte[myfile.Length]; 

       //Write file to tBytes array 
       myfile.Read(tBytes, 0, (int)myfile.Length); 
       texture.LoadImage(tBytes); 
      } 

      rawImages[currentPreviewNumber].texture = texture; 
      currentPreviewNumber++; 
     } 
    } 
} 

Der Speicher ist es jetzt 10.0kb ordnet was in Ordnung ist. Wenn Sie dies optimieren möchten, anstatt eine Zeichenfolge mit StringBuilder in der while-Schleife zu generieren, tun Sie dies einmal in der Start-Funktion und speichern Sie diese Zeichenfolgen in Zeichenfolgenarrays, die später in der while-Schleife mit index wiederverwendet werden können Der aktuelle Code ist in Ordnung.