在项目中,场景大小很重要,特别是场景多了以后,除了在场景上做动态的加载,还要及时卸载。
为了可以在更多的安卓手机上可以运行,就需要对于场景加以优化。
1.shader上,尽量使用程序员找的shader,不要找一些效果很好,但是在一些手机上蹦的shader.
在现在的项目中,有一个描边发光的shader,在三星的手机上就很容易蹦,根本是这个shader需要描边的渲染,而三星的手机上显卡不满足就蹦了。使用程序给予的shader的好处是,在技术支持最大的范围的内,做出做好的效果。
2.场景的贴图上,不要使用过多的贴图,贴图过大,就会占用很大的内存。一张贴图,1024*1024,格式ARBG的,有5.7M,加载到就2倍,低于内存本身就小的机型,2个贴图就不让干别的了。目前项目中要求,2张2048*2048就极限了。在格式上安卓选用ETC1,iphone上使用PVR。就达到了低于图片的优化
3.在sence做完了,执行这个代码就可以获得相应的材质球和贴图信息了。
FindTextureName.cs
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
public class Material_Texture_Calculation:MonoBehaviour
{
public class AllInfo
{
private string materialName;
private List<string> names;
private List<float> sizes;
float maxsize;
public AllInfo()
{
maxsize = 0;
materialName = "";
names = new List<string>();
sizes = new List<float>();
}
public string MaterialName
{
get
{
return materialName;
}
set
{
value = materialName;
}
}
public int Length
{
get
{
return names.Count;
}
}
public float MaxSize
{
get
{
return maxsize;
}
}
public List<string> TextureNames
{
get
{
return names;
}
}
public List<float> TextureSizes
{
get
{
return sizes;
}
}
public void Add(string TextureNames,float size)
{
names.Add (TextureNames);
sizes.Add (size);
}
public void Add(string materialname)
{
materialName = materialname;
}
public void sort()
{
if (Length > 0)
{
for(int i=0;i<Length;i++)
{
for(int j=0;j<Length;j++)
{
float tempint;
string tempstr;
tempint = sizes[j];
sizes[j] = sizes[i];
sizes[i] = tempint;
tempstr = names[j];
names[j] = names[i];
names[i] = tempstr;
}
}
maxsize = sizes[0];
}
}
public void Print()
{
UnityEngine.Debug.Log ("Material Name:" + MaterialName);
for (int i=0; i<Length; i++)
{
UnityEngine.Debug.Log(" |Texture Name:" names[i]+ " Texture Size:" +sizes[i] + "kb|");
}
}
}
[MenuItem("Tools/Calualation")]
public static void Calualation()
{
GameObject[] gameObjects = GameObject.FindObjectsOfType<GameObject> ();
List<string> materialnames = new List<string> ();
List<string> pngnames = new List<string> ();
List<AllInfo> calualation = new List<AllInfo> ();
for (int i=0; i<gameObjects.Length; i++)
{
Renderer render = gameObjects[i].GetComponent<Renderer>();
if(null!=render)
{
Material material = render.sharedMaterial;
Material[] materials = render.sharedMaterials;
int count = materials.Length;
for(int j=0;j<count;j++)
{
if(null !=materials[j])
{
if(materialnames.Contains(materials[j].name));
continue;
}
materialnames.Add(materials[j].name);
AllInfo allinfo = new AllInfo();
allinfo.Add (materials[j].name);
Shader shader = materials[j].shader;
if(null != shader)
{
int propertyNum = ShaderUtil.GetPropertyCount(shader);
for(int k=0;k<propertyNum;k++)
{
if(ShaderUtil.GetPropertyType(shader,k)==ShaderUtil.ShaderPropertyType.TexEnv)
{
string textureName = ShaderUtil.GetPropertyName(shader,k);
Texture texture = materials[j].GetTexture(textureName);
if(null != texture)
{
float texturesize = Profiler.GetRuntimeMemorySize(texture)/2048.0f;
string textureRealName = texture.name;
if(!pngnames.Contains(textureRealName))
{
pngnames.Add(textureRealName);
allinfo.Add(textureRealName,texturesize);
}
}
}
}
}
allinfo.sort();
calualation.Add(allinfo);
}
}
}
AddByDescending(calualation);
print (calualation);
PrintToFile(calualation);
UnityEngine.Debug.LogWarnging("Material Number:" + materialnames.Count);
UnityEditor.Debug.LogWarnging("Textures Name:" + pngnames.Count);
PrintResults(materialnames,pngnames);
}
public static void AddByDescending(List<AllInfo> list)
{
int count = list.Count;
for (int i=0; i<count-1; i++)
{
for(int j=i+1;j<count;j++)
{
AllInfo allInfo;
if(list[i].MaxSize<list[j].MaxSize)
{
allInfo = list[i];
list[i] = list[j];
list[j] = allInfo;
}
}
}
}
public static void Print(List<AllInfo> list)
{
for (int i=0; i<list.Count; i++)
{
list[i].Print();
}
}
public static void PrintToFile(List<AllInfo> list)
{
string path = Application.dataPath + "/Calculation.txt";
if (File.Exists (path))
{
File.Delete(path);
}
FileStream filestream = File.Create (path);
StringWriter steamwriter = new StreamWriter(filestream);
int count = list.Count;
for (int i=0; i<count; i++)
{
int length = list[i].Length;
string zhushi = "++++++++++++";
steamwriter.WriteLine(zhushi);
string material = "->|Material Name:" + list[i].MaterialName+"|<-";
steamwriter.WriteLine(material);
for(int j=0;j< length;j++)
{
string name = " |Texture Name:" + list[i].TextureNames[j]+" Texture Szie:" + list[i].TextureSizes[j]+"KB|";
steamwriter.WriteLine(name);
}
}
steamwriter.Flush ();
steamwriter.Close ();
filestream.Close ();
}
public static void PrintResultes(List<string> mlist,List<string> plist)
{
string path = Application.dataPath + "/Calculation.txt";
if (File.Exists (path))
{
StreamWriter streamwriter = new StreamWriter(path,true);
string zhushi1 ="******************";
string str1 = "Material Number: " + mlist.Count;
string zhushi2 = "****************";
string str2 = "Texture Number:" + plist.Count;
string zhushi3 = "*****************";
streamwriter.WriteLine(zhushi1);
streamwriter.WriteLine(str1);
streamwriter.WriteLine(zhushi2);
streamwriter.WriteLine(str2);
streamwriter.WriteLine(zhushi3);
streamwriter.Flush();
streamwriter.Close();
Process.Start(path);
}
}
}
首先要对unity的api了解,获取材质球Render,其次对于有多通道贴图的shader,unity 给予了获取shader属性的方法,对于贴图大小,
Profiler.GetRuntimeMemorySize(texture)/2048.0f;
在其他把重复使用到的材质球和贴图名称剔除。
在Editor文件夹下,同时生成在一个txt文件中,而是不使用unity的debug,方便做历史记录的对比。