C# 在Unity中卸载未使用的纹理
我交换了一些精灵对象,取而代之的是没有纹理的网格,因为它们应该占用更少的内存 但是,在检查我的档案器时,即使在交换之后,使用的纹理内存也是一样的 所以我决定强制卸载这些纹理,但事情进展得不太顺利。 我使用这段代码的目的是根据它们所在的游戏对象的名称查找所有纹理(因为我刚刚通过inspector在场景中拖动了精灵,它们的名称匹配。我知道要查找哪些GO-s,因为它们只包含一个网格过滤器),然后手动卸载它们C# 在Unity中卸载未使用的纹理,c#,performance,unity3d,optimization,C#,Performance,Unity3d,Optimization,我交换了一些精灵对象,取而代之的是没有纹理的网格,因为它们应该占用更少的内存 但是,在检查我的档案器时,即使在交换之后,使用的纹理内存也是一样的 所以我决定强制卸载这些纹理,但事情进展得不太顺利。 我使用这段代码的目的是根据它们所在的游戏对象的名称查找所有纹理(因为我刚刚通过inspector在场景中拖动了精灵,它们的名称匹配。我知道要查找哪些GO-s,因为它们只包含一个网格过滤器),然后手动卸载它们 using System; using System.Collections; using S
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);
}
}
}
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
使用UnityEditor;
使用UnityEngine;
公共类:单行为
{
私有TextureContainer swappedTextures=新TextureContainer();
私有IEnumerator Start()
{
RemoveSwappedTextures();
var disloader=Resources.disloadUnusedAssets();
而(!disloader.isDone)
{
收益返回空;
}
}
私有void RemoveSwappedTextures()
{
//获取所有具有网格过滤器的场景对象。
/*
*注意:我将精灵替换为生成的网格。
*但是,使用的纹理内存没有减少,所以我打赌它们仍然加载。
*我用作精灵的纹理与资源本身的名称相同
*只是在现场拖来拖去的。
*/
变量场景对象=
UnityEngine.Object.FindObjectSoftType()
。其中(g=>g.GetComponent()!=null);
//我们已经重新绘制了游戏对象。
//现在按名称获取使用过的纹理:
foreach(场景对象中的变量项)
{
//得到一切,甚至是资产
var strToFind=GetOriginalName(item.name);
swappedTextures.Append(
Resources.FindObjectsOfTypeAll()文件
.Where(t=>t.name.Equals(strToFind)
));
}
foreach(在交换的文本中卸载var text2)
{
//销毁加载的纹理。
立即销毁(text2Unload);
}
swappedTextures=null;
}
私有字符串GetOriginalName(字符串名称)
{
/*
*通过“unity填充名称”获取原始资产名称。
*原因:假设我有一个名为纹理的“backGr”。
*如果我把它复制粘贴到所有地方,unity就成了他们的名字
*“backGr(1)”、“backGr(2)”等。
*所以我搜索直到第一个空格和之前的任何内容
*是纹理的原始名称。
*/
字符串str=“”;
字符c;int i=0;
for(c=name[i];i
我想它没有达到我想要的效果是因为使用的纹理内存是一样的,并且使用的总内存比以前更高
所以,除非Unity在场景中纹理较少的情况下使用更多的纹理内存是正常的,否则我想我在某个地方搞砸了
问题是,如何使这一点发挥作用?如果我走错了路,按名称卸载纹理的最佳实践是什么