今天碰到一个小问题需要通过脚本来批量将我们工程中的所有例子特效Prefab根节点的粒子发射器给干掉,那么好吧,开始动手吧。
ParticleSystem ps = go.GetComponent<ParticleSystem> ();
if (ps != null) {
if (ps.renderer.sharedMaterial == null) {
Debug.Log (string.Format ("{0} Render Has no Material", go.name));
} else {
var matName = ps.renderer.sharedMaterial.name;
if (matName.StartsWith ("Default-Particle")) {
Debug.Log (string.Format ("Prefab: {0}, Mat: {1}", go.name, matName));
DestroyImmediate (ps, true);
}
}
}
执行一下,发现ParticleSystem组件确实木有了,但是留了一个小尾巴,就是我们在Unity3D Editor中查看被处理的Prefab时,还能在Inspector中看到一个Shader的小尾巴,如图:
这个让我情何以堪啊,你知道的,我有轻微强迫症的,虽然貌似并不会影响程序的功能,但是我要是不知道原因,我岂不是很不爽,好吧,那么就对比一下手动将ParticleSystem组件Remove和通过我们这个脚本Destroy之后的Prefab文件之间究竟有甚么区别呢,这个时候就需要借助一下Unity3D提供的binary2text命令行工具了,Mac OSX上这个命令还在这个位置[Unity3D安装目录]/Unity.app/Contents/Tools/binary2text,通常就是/Applications/Unity/Unity.app/Contents/Tools/binary2text。使用这个工具将两个Prefab文件转成Text文件之后我们就可以使用文件对比工具来进行对比了(对比二进制神马的,真的让人很蛋疼啊,幸好Unity3D还提供了这么个鬼啊),对比就会发现,这个Shader是因为啥而存在的了。
左侧有红色文本显示的是通过脚本Destroy ParticleSystem组件之后生成的Prefab的Text文件,右侧的是手动通过右键Remove Component删除ParticleSystem组件之后生成的Prefab的Text文件,对比之下我们能发现左侧文件中说明了一些问题:
- 第一处红色文本表示多了一个内部资源的引用,看起来很像是Shader;
- 第二处红色文本更是直接说明了问题,左侧表示有两个组件,组件的Id是19935810,刚好与第三处红色文本描述对应;
- 第三处红色文本描述的是一个ParticleSystemRender组件的信息。
这么一看就知道原来还有一个隐藏的ParticleSystemRender组件没有被移除掉,因为这个Render是依附于ParticleSystem才存在的,所以不会在Inspector中单独显示,而是作为ParticleSystem的子组件Render进行显示的。那么我们就再修改一下我们的代码就好了。
ParticleSystem ps = go.GetComponent<ParticleSystem> ();
if (ps != null) {
if (ps.renderer.sharedMaterial == null) {
Debug.Log (string.Format ("{0} Render Has no Material", go.name));
} else {
var matName = ps.renderer.sharedMaterial.name;
if (matName.StartsWith ("Default-Particle")) {
Debug.Log (string.Format ("Prefab: {0}, Mat: {1}", go.name, matName));
DestroyImmediate (ps, true);
}
}
}
ParticleSystemRenderer psr = go.GetComponent<ParticleSystemRenderer> ();
if (psr != null) {
if (psr.sharedMaterial == null) {
Debug.Log (string.Format ("{0} Render Has no Material", go.name));
DestroyImmediate (psr, true);
} else {
var matName = psr.sharedMaterial.name;
if (matName.StartsWith ("Default-Particle")) {
Debug.Log (string.Format ("Prefab: {0}, Mat: {1}", go.name, matName));
DestroyImmediate (psr, true);
}
}
}
也就是需要独立地将这个ParticleSystemRender组件也给DestroyImmediate一下就好了。搞定,洗洗睡了。