今天给大家提供一个自动去掉图片mipmap勾选的小工具的制作方法。
大家对Lod应该都有所了解,其原理是根据摄像机和模型之间不同距离(准确地讲,应该是模型所占摄像机视口的比例,距离越远比例越小,反之越大)而采用不同精细度(网格的顶点数和三角形数量不一样)的网格mesh,距离越远采用精细度越低的网格(即顶点数和三角形数越少的网格),以提高渲染效率。mipmap有些像lod,不同的是,它在贴图上面动了手脚,根据不同距离采用不同精细度(贴图的像素不一样)的贴图。
应用lod和mipmap都可以不同程度上提高渲染效率,但是由于都需要在内存里面放着多个不同精细度的副本,所以,代价是需要消耗更多的内存。
对于UI贴图来说,我们不必应用mipmap,因为一般的UI都是“平铺”在正交摄像机视口的,和摄像机木有距离这一概念,所以我们大可以把UI贴图的mipmap选项去掉,以节省内存。默认情况下导入的贴图是开启mipmap选项的,如果手动一个一个改的话,必然蛋疼,那么,就写脚本批量改吧。
我们优化就是从减少DrawCall开始的,减少DrawCall需要使用批处理技术开始的。mipmap针对的是纹理贴图,大白话就是,一个模型身上会有贴图,当我们对这个贴图使用了MipMap技术之后,那么在游戏运行中这个模型的贴图会根据摄像机距离模型的远近而调整不同的不同质量的贴图显示。
当我们给一个模型贴了一个贴图,当我们没有对这个贴图使用MipMap技术的时候,无论我们摄像机距离模型的位置在哪,这张贴图永远都是显示一样的,这样是完全没有必要的,我们使用这个技术就是为了让当摄像机比较远的时候,你用在精细的贴图我们玩家也看不见,而且还浪费资源,提高了性能瓶颈。
使用MipMap技术之后,会对这个贴图生成八张精度质量不同的贴图,所以内存占用变大了。所以关于这个技术是否使用,根据你的项目而定,什么都是有利有弊的。
mipmap介绍完了,接下来先看代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
public class FindAllTexture {
[MenuItem("CunstomFunction/CancelUIMipMap")]
static void GetTexture()
{
List allTexturePaths = new List();
string textureType = "*.jpg,*.png,*.bmp";
//得到所有图片格式
string[] textureTypeArray = textureType.Split(',');
for(int i = 0; i < textureTypeArray.Length; i++)
{
//string[] texturePath = Directory.GetFiles(Application.dataPath,"(*.jpg|*.bmp)");
string[] texturePath = Directory.GetFiles("Assets/",textureTypeArray[i],SearchOption.AllDirectories);
for(int j = 0; j < texturePath.Length; j++)
{
allTexturePaths.Add(texturePath[j]);
//Debug.Log(texturePath[j]);
}
}
for(int k = 0; k < allTexturePaths.Count; k++)
{
Texture2D tx = new Texture2D(200,200);
tx.LoadImage(getTextureByte(allTexturePaths[k]));
//如果图片不符合规范
if (!(isPower(tx.height)&& isPower(tx.width)))
{
Debug.Log("不符合规范的图片的尺寸为:"+tx.width+"X"+tx.height);
}
TextureImporter textureImporter = TextureImporter.GetAtPath(allTexturePaths[k]) as TextureImporter;
textureImporter.textureType = TextureImporterType.Advanced;
textureImporter.mipmapEnabled = false;
textureImporter.SaveAndReimport();
AssetDatabase.ImportAsset(allTexturePaths[k]);
}
}
///
/// 根据图片路径返回字节流
///
///
///
static byte[] getTextureByte(string texturePath)
{
FileStream file = new FileStream(texturePath, FileMode.Open);
byte[] txByte = new byte[file.Length];
file.Read(txByte, 0, txByte.Length);
file.Close();
return txByte;
}
///
/// 判断图片尺寸是否为2的n次方
///
///
///
static bool isPower(int n)
{
if (n < 1)
return false;
int i = 1;
while (i <= n)
{
if (i == n)
return true;
i <<= 1;
}
return false;
}
}
这个脚本只需要放在Editor目录下,就可以在unity菜单栏中显示一个CustomFunction按钮,然后点击它的子菜单CancelUIMipMap,就会取消掉unity工程中所有图片资源的mipmap。(因为我的路径写的是"Assets/",这个后面会说,自己根据需求改就行)
1.首先写一个功能方法,根据图片的路径返回字节流(加载图片时要用)
///
/// 根据图片路径返回字节流
///
///
///
static byte[] getTextureByte(string texturePath)
{
FileStream file = new FileStream(texturePath, FileMode.Open);
byte[] txByte = new byte[file.Length];
file.Read(txByte, 0, txByte.Length);
file.Close();
return txByte;
}
2.设置要找的图片类型(jpg,png,bmp等等),然后从指定文件夹(是否也查询所有子目录自己选择,我这里参数写的是)查询所有该类型的图片资源路径。
List allTexturePaths = new List();
string textureType = "*.jpg,*.png,*.bmp";
//得到所有图片格式
string[] textureTypeArray = textureType.Split(',');
for(int i = 0; i < textureTypeArray.Length; i++)
{
//string[] texturePath = Directory.GetFiles(Application.dataPath,"(*.jpg|*.bmp)");
string[] texturePath = Directory.GetFiles("Assets/",textureTypeArray[i],SearchOption.AllDirectories);
for(int j = 0; j < texturePath.Length; j++)
{
allTexturePaths.Add(texturePath[j]);
//Debug.Log(texturePath[j]);
}
}
3.接下来遍历这些资源路径,并且创建TextureImporter对象,然后去掉mipmap勾选即可。
注意!!!!!!还要加一行代码:textureImporter.SaveAndReimport();
如果不加这一行,当使用工具去掉所有图片mipmap后,你以为大功告成了,但是当你退出unity后再打开,又会恢复成原来的设置了,这可不行。这行代码相当于更新图片资源的属性(也可以说把图片Apply了一下)
TextureImporter textureImporter = TextureImporter.GetAtPath(allTexturePaths[k]) as TextureImporter;
//textureImporter.textureType = TextureImporterType.Advanced;
textureImporter.mipmapEnabled = false;
textureImporter.SaveAndReimport();
AssetDatabase.ImportAsset(allTexturePaths[k]);
4.因为任务需要,我又加了一个小功能,就是把长宽不是2的n次方的不符合规范的图片找出来。(这个你们把相关代码删掉即可)
Texture2D tx = new Texture2D(200,200);
tx.LoadImage(getTextureByte(allTexturePaths[k]));
//如果图片不符合规范
if (!(isPower(tx.height)&& isPower(tx.width)))
{
Debug.Log("不符合规范的图片的尺寸为:"+tx.width+"X"+tx.height);
}
///
/// 判断图片尺寸是否为2的n次方
///
///
///
static bool isPower(int n)
{
if (n < 1)
return false;
int i = 1;
while (i <= n)
{
if (i == n)
return true;
i <<= 1;
}
return false;
}
对于UI贴图来说,我们不必应用mipmap,因为一般的UI都是“平铺”在正交摄像机视口的,和摄像机木有距离这一概念,所以我们大可以把UI贴图的mipmap选项去掉,以节省内存,手动修改太繁琐并且容易漏掉,所以我觉得写这个小工具很有意义。
还有,这是一个能够查询指定路径所有指定格式的资源并更统一改某个属性的小工具。大家也可以修改个别代码,做成一个其他类型的小工具,只不过制作思想是不变的。
之后我会把小工具导出来,大家也可以直接把工具导入工程直接使用。