我已经交换了一些 Sprite 对象,转而使用 Meshes 没有纹理,因为它们占用的内存较少。
然而,当检查我的 Profiler 时,即使在交换之后,使用的纹理内存也完全相同。
所以我决定强行卸载这些纹理,但事情并不顺利。 我对这段代码的意图是通过它们所在的 GameObject 的名称找到所有纹理(因为我只是通过检查员拖动场景中的精灵,他们的名字匹配。我知道哪些GO-s查找只包含 MeshFilter ),然后手动卸载它们。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class DumpUnused : MonoBehaviour
{
private TextureContainer swappedTextures = new TextureContainer();
private IEnumerator Start()
{
RemoveSwappedTextures();
var unloader = Resources.UnloadUnusedAssets();
while (!unloader.isDone)
{
yield return null;
}
}
private void RemoveSwappedTextures()
{
//getting all my scene objects that has a mesh filter.
/*
* NOTE: I swapped my sprites for generated meshes.
* However, the texture memory used didn't decrease so I bet they are still loaded.
* The textures I used as sprites had the same name as the assets themselves as assets were
* just dragged on the scene.
*/
var sceneObjects =
UnityEngine.Object.FindObjectsOfType<GameObject>()
.Where(g => g.GetComponent<MeshFilter>() != null);
//we have the repaced gameobjects.
//now to get the used textures by their names:
foreach (var item in sceneObjects)
{
//getting everything, even assets
var strToFind = GetOriginalName(item.name);
swappedTextures.Append(
Resources.FindObjectsOfTypeAll<Texture2D>()
.Where(t => t.name.Equals(strToFind)
));
}
foreach (var text2Unload in swappedTextures)
{
//destroy the loaded textures.
DestroyImmediate(text2Unload);
}
swappedTextures = null;
}
private string GetOriginalName(string name)
{
/*
* getting the original asset name by the "unity populated name".
* reason: say I have a "backGr" named texture.
* if I copy paste it all over the place, unity makes their name
* "backGr (1)", "backGr (2)" and so on.
* So I search until the first whitespace and anything before that
* is the original name of the texture.
*/
string str = "";
char c;int i = 0;
for (c = name[i]; i < name.Length && c != ' '; i++)
{
str += c;
}
return str;
}
public class TextureContainer : List<Texture2D>
{
//made only for convenience
public void Append(IEnumerable<Texture2D> textures)
{
foreach (var _t in textures)
{
this.Add(_t);
}
}
}
}
我认为它没有做我想要的原因是因为使用的纹理内存完全相同,并且使用的总内存甚至更高比以前更高。
所以,除非在场景中纹理较少的情况下Unity使用更多纹理记忆是正常的,我想我在某处搞砸了。
问题是,如何使这项工作?如果我走错路,按名称卸载纹理的最佳做法是什么?