Unity资源这块,我主要介绍我了解的,贴图格式,材质,shader,音乐,特效等,而这些需要死磕美术和策划。当然如果有个厉害的技术美术这些都跟它沟通就好了,这些是游戏优化中最大的部分,提升内存,CPU和显卡都比较明显,当然问题和标准都有很多,我说一下我这里遇到过并能想起来的,有其他问题可以交流。
1.贴图,网上有好多讲参数的,我这里不详细说了,我这里就说一下给美术的标准。
图片里面能不用A通道就不用,比如全屏的背景之类的,就不要留下描边,而有些需要描边的可以用其他方式实现(如NGUI里面UIPanel的SoftClip虚化边缘,在dc不高的时候用dc换内存)。
另外是图片的宽和高,都能被4或者2整除的最好,压缩格式选择ETC,PVRTC都有提升,如果有自己写的shader,有一些图片就需要在代码里面设置格式用到TextureImporter和AssetImporter类,代码百度有一堆。
Unity在5.3版本把默认格式改为ETC2了,ETC2只有OPENGL3.0支持,它在低端机上会转回不压缩的格式,效率低。所以最好能被4整除,并且不透明的条件下,安卓平台选择下图这个格式效率最高,IOS只支持PVRTC的压缩格式,但是具体格式跟项目来定。
2.shader这块就不多说了,我也在学习当中,项目中一定要找个明白的,有些自己写效率会有问题。如果项目没有,尽量不要乱改,尽量找网上成熟的Shader和系统内置Shader。
3.音乐这块问题不是很多,不是音乐类游戏,对音乐的要求不会太高,公司有音乐类游戏,开始都是WAV的,在手机上撑不住最后也被压缩了,只是压缩比需要控制好,一般游戏推荐MP3或者Ogg,如果音乐格式选不好也会有问题。下面
加载时解压缩(Decompress on load):加载后解压缩声音。使用于较小的压缩声音,以避免运行时解压缩的性能开销。(将使用比在它们在内存中压缩的多10倍或更多内存,因此大文件不要使用这个。)
在内存中压缩(Compressed in memory):保持声音在内存中(压缩的)在播放时解压缩。这有轻微的性能开销(尤其是OGG / Vorbis格式的压缩文件),因此大文件使用这个。
从磁盘流(Stream from disc):直接从磁盘流读取音频数据。这只使用了原始声音占内存大小的很小一部分。使用这个用于很长的音乐。取决于硬件,一般建议1-2线程同时流。
4.特效这块,我们大部分用的是粒子特效,个别用序列帧动画。粒子特效单个的最大粒子数和同屏最大粒子数量一定要控制好,并且尽量整合粒子贴图(如一个粒子四张小图可以整合为一张加载的时候只需要加载一张)。特效都是外包过来的,必然会有特效层级混乱并且有丢失的问题,美术一个一个排查压力大,写工具,下面附上代码。
丢失特效查询:
[MenuItem("Strung/Select Effect Is Missing")]
publicstaticvoidSelectMissing()
{
UnityEngine.Object[] selectObjs =Selection.objects;
FileStream cfs =newFileStream(Application.dataPath + "MissMaterialList.txt",FileMode.Create);
GameObject obj =null;
for (int i = 0; i <selectObjs.Length; i++)
{
obj = selectObjs[i] asGameObject;
ParticleSystemRenderer[] psr =obj.GetComponentsInChildren<ParticleSystemRenderer>();
if (psr.Length > 0)
{
Check(psr, cfs);
}
}
cfs.Close();
}
publicstaticvoid Check(ParticleSystemRenderer[] psrList, FileStream cfs)
{
Transform temp;
StringBuilder sb =newStringBuilder();
string str ="";
for (int i = 0; i <psrList.Length; i++)
{
if (psrList[i].sharedMaterial ==null)
{
temp = psrList[i].transform;
str = temp.name;
while (temp.parent !=null)
{
str += ("-----"+ temp.parent.name);
temp = temp.parent;
}
sb.AppendLine(str);
sb.AppendLine("");
}
}
byte[] myBytes = System.Text.Encoding.UTF8.GetBytes(sb.ToString());
cfs.Write(myBytes, 0,myBytes.Length);
}
特效顺序排列:
[MenuItem("Assets/Effect Change OrderInLayer")]
publicstaticvoid ChangeOrderInLayer()
{
UnityEngine.Object[] selectObjs =Selection.objects;
GameObject obj =null;
int orderNum = 0;
List<ParticleSystemRenderer> psrList = newList<ParticleSystemRenderer>();
for (int i = 0; i <selectObjs.Length; i++)
{
orderNum = -1;
psrList.Clear();
obj = selectObjs[i] asGameObject;
ParticleSystemRenderer[] psrArr =obj.GetComponentsInChildren<ParticleSystemRenderer>();
if (psrArr.Length > 0)
{
psrList = newList<ParticleSystemRenderer>(sortByFudge(psrArr));
for (int j = 0; j <psrList.Count; j++)
{
psrList[j].sortingOrder =orderNum;
orderNum -= 1;
}
}
}
}
publicstaticParticleSystemRenderer[] sortByFudge(ParticleSystemRenderer[] psrArr)
{
ParticleSystemRenderer temp =null;
for (int i = 0; i <psrArr.Length; i++)
{
for (int j = i + 1; j< psrArr.Length; j++)
{
if (psrArr[i].sortingFudge > psrArr[j].sortingFudge)
{
temp = psrArr[j];
psrArr[j] = psrArr[i];
psrArr[i] = temp;
}
}
}
return psrArr;
}