首页 >Unity3D频道 >【Unity3D拓展编辑器】 > Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)
2015
11-04

Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)

感谢楼下的牛逼回复更正一下,我表示我也是才知道。。

其实不需要实例化也能查找,你依然直接用GetComponentsInChildren<>(true),对传true即可。。。这样搞还很麻烦。。。唯一关注是能否把Missing的脚本序列化找出来??

使用 GetComponentsInChildren<>(true) 可以直接把Project视图里的子对象找出来!!!!

return;

代码是这样的

	[MenuItem("Assets/Delete")]
	static void delete () 
	{
		GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/GameObject.prefab");

		//删除MeshCollider
		MeshCollider [] meshColliders = prefab.GetComponentsInChildren<MeshCollider>(true);
		foreach(MeshCollider meshCollider in meshColliders){

			GameObject.DestroyImmediate(meshCollider,true);
		}

		//删除空的Animation组件
		Animation [] animations = prefab.GetComponentsInChildren<Animation>(true);
		foreach(Animation animation in animations){
			if(	animation.clip == null){
				GameObject.DestroyImmediate(animation,true);
			}

		}

		//删除missing的脚本组件
		MonoBehaviour [] monoBehaviours = prefab.GetComponentsInChildren<MonoBehaviour>(true);
		foreach(MonoBehaviour monoBehaviour in monoBehaviours){


			if(monoBehaviour == null){
				Debug.Log("有个missing的脚本");
				//GameObject.DestroyImmediate(monoBehaviour,true);

			}
		}

		//遍历Transform的名子, 并且给某个游戏对象添加一个脚本
		Transform [] transforms = prefab.GetComponentsInChildren<Transform>(true);
		foreach(Transform transfomr in transforms){
			if(transfomr.name == "GameObject (1)"){
				Debug.Log(transfomr.parent.name);
				transfomr.gameObject.AddComponent<BoxCollider>();
				return;
			}

		}
		//遍历Transform的名子, 删除某个GameObject节点
		foreach(Transform transfomr in transforms){
			if(transfomr.name == "GameObject (2)"){
				GameObject.DestroyImmediate(transfomr.gameObject,true);
				return;
			}

		}
                EditorUtility.SetDirty(prefab);
	}

 

今天有朋友说不能删除missing的脚本, 我试了一下确实不行。 随后查了一下, 可以用这个方法来删除,

http://answers.unity3d.com/questions/15225/how-do-i-remove-null-components-ie-missingmono-scr.html

 [MenuItem("Edit/Cleanup Missing Scripts")]
 static void CleanupMissingScripts ()
 {
     for(int i = 0; i < Selection.gameObjects.Length; i++)
     {
         var gameObject = Selection.gameObjects[i];
         
         // We must use the GetComponents array to actually detect missing components
         var components = gameObject.GetComponents<Component>();
         
         // Create a serialized object so that we can edit the component list
         var serializedObject = new SerializedObject(gameObject);
         // Find the component list property
         var prop = serializedObject.FindProperty("m_Component");
         
         // Track how many components we've removed
         int r = 0;
         
         // Iterate over all components
         for(int j = 0; j < components.Length; j++)
         {
             // Check if the ref is null
             if(components[j] == null)
             {
                 // If so, remove from the serialized component array
                 prop.DeleteArrayElementAtIndex(j-r);
                 // Increment removed count
                 r++;
             }
         }
         
         // Apply our changes to the game object
         serializedObject.ApplyModifiedProperties();
         //这一行一定要加!!!
         EditorUtility.SetDirty(gameObject);
     }
 }

 

昨天晚上睡觉的时候脑洞打开。因为做项目的时候我们可能要在编辑器上做很多检查工具一类的东西。 这里我说几个典型的例子,比如空的Animation组件、丢失的脚本、没用的meshCollider组件。这些东西我们是不需要的,但是美术可能不会不小心加到prefab里。

以前的做法是 先要把Prefab 实例化 Instance以后  然后  GetComponentsInChildren  把所有的组件都取出来。 在进行遍历删除。 然后还要DestroyImmediate 它。 。那么如果prefab数量比较多的话,那么检查一次时间是很漫长的。

如果你只是想找组件 空脚本 一类的。用如下代码就可以不实例化并且找出来。

 

如果你想不实例化并且修改数据的话,那么可以考虑用下面的方法。

1.先把prefab 序列化的方式改成text 用File就可以把prefab的文本信息读出来。

File.ReadAllText("xxx/xxx.prefab")

 

2.prefab文本序列化的结构,如下图所示,看到!u!111了吗  111 是一组id .它是有意义的(它表示Animation),标着着这个组件是个啥东西。 具体是什么含义大家可以去这里查 http://docs.unity3d.com/Manual/ClassIDReference.html

Snip20151104_2

 

3.自定义脚本

如果我想查一下看看prefab有没有绑定我自己写的脚本怎么办呢?如下图所 ,guid这一栏 就写的是你的脚本的guid了。

Snip20151104_4

 

然后在脚本对应的mate文件里就记录这这个脚本的guid ,如果这两个id匹配,那么就说明这个prefab里挂着这个脚本了。

Snip20151104_5

 

最后就交给正则表达式做第一步的匹配吧。 这样的话第一步就可以筛选掉一大批prefab了。 如果还需要进行验证在进一步的Instance来检查吧。。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)》有 20 条评论

  1. YL说:

    如何才能查找到隐藏物体身上的组件呢?我现在遇到隐藏物体没法获取到的问题

  2. 肚皮说:

    有个小问题。
    第38行,Debug.Log(transfomr.parent.name);应该是Debug.Log(transfomr.name);
    感谢~

  3. 中文说:

    最近一直在看这个问题,试验了YAML方式,或直接Destroy的方式,很曲折,没行通。最后接收了您的建议采用文件流的方式,搞定了,贴一下网址,http://blog.csdn.net/lihuozhiling0101/article/details/52605328 第一次评论您的博客,谢谢您一直给予的帮助,谢谢。

  4. 越大步说:

    删除丢失脚本的第二个方法也并不可行,他只会删除例如— !u!110这一列, 而他的组件信息这一组并不会删除

  5. 啊啊说:

    先把prefab 序列化的方式改成text 这一步具体怎么操作 我没看懂

  6. Chiuan说:

    其实不需要实例化也能查找,你依然直接用GetComponentsInChildren(true),对传true即可。。。这样搞还很麻烦。。。唯一关注是能否把Missing的脚本序列化找出来??

  7. 陌上飞歌(Jackson)说:

    这个可以用来查找吧。。如果是删除的话,还是要实例化吧

  8. c6u2说:

    有几个插件可以列出引用的东西就是这么干的

  9. 秦元培说:

    发现你玩黑科技玩上瘾了啊,哈哈

留下一个回复

你的email不会被公开。 必填项已用 * 标注。