最近项目中遇到一个问题,随着游戏内容的增长,物品Icon使用TexurePacker合并到一张图集中已经达到4096*4096了,而通常一个账号中不可能同时拥有所有的物品。这样导致不管有多少个物品,都要把整个Icon图集加载内存中,这样很浪费内存。尝试过物品细分,但不能解决根本问题。
https://github.com/DaVikingCode/UnityRuntimeSpriteSheetsGeneratorGitHub上有一个项目已经解决了这个问题,但他使用到了 Textrue.SetPixels32, Texture.Apply 以及 Sprite.Create 三个接口,但在移动端测试时这三个接口非常耗时。已经影响了游戏的体验感了。通过对他的改进后好了很多。
解决思路大致是:把一个图元先缓存到一个Material中进行采样,在通过GL方式把顶点和纹理拷贝到RenderTexture中。并且把Image组件改成RawImage组件。参考下面的核心代码
public void SetTexture(Texture2D texture, Rect rect)
{
if (material == null)
{
material = new Material(Shader.Find(ShaderName_UIDefault));
}
sampling.SetTexture(MainTex_ID, texture);
if (sampling.SetPass(0))
{
Graphics.SetRenderTarget(mainTexture);
GL.PushMatrix();
GL.LoadOrtho();
GL.Begin(GL.QUADS);
{
Vector3 vertex1 = new Vector3(rect.x, rect.y, 0);
Vector3 vertex2 = new Vector3(rect.x, rect.y + rect.height, 0);
Vector3 vertex3 = new Vector3(rect.x + rect.width, rect.y + rect.height, 0);
Vector3 vertex4 = new Vector3(rect.x + rect.width, rect.y, 0);
GL.TexCoord2(0, 0);
GL.Vertex(vertex1);
GL.TexCoord2(0, 1);
GL.Vertex(vertex2);
GL.TexCoord2(1, 1);
GL.Vertex(vertex3);
GL.TexCoord2(1, 0);
GL.Vertex(vertex4);
}
GL.End();
GL.PopMatrix();
}
material.SetTexture(MainTex_ID, mainTexture);
image.material = material;
}
需要的同学可以到https://github.com/Aifee/UnityRuntimeSpriteSheetsGenerator下载参考一下。还可以把它再次改造一下。可以根据Icon的内容量动态分配RenderTexture的大小。