感谢楼下的牛逼回复更正一下,我表示我也是才知道。。
其实不需要实例化也能查找,你依然直接用GetComponentsInChildren<>(true),对传true即可。。。这样搞还很麻烦。。。唯一关注是能否把Missing的脚本序列化找出来??
使用 GetComponentsInChildren<>(true) 可以直接把Project视图里的子对象找出来!!!!
return;
代码是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
[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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
[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的文本信息读出来。
1 2 3 |
File.ReadAllText("xxx/xxx.prefab") |
2.prefab文本序列化的结构,如下图所示,看到!u!111了吗 111 是一组id .它是有意义的(它表示Animation),标着着这个组件是个啥东西。 具体是什么含义大家可以去这里查 http://docs.unity3d.com/Manual/ClassIDReference.html
3.自定义脚本
如果我想查一下看看prefab有没有绑定我自己写的脚本怎么办呢?如下图所 ,guid这一栏 就写的是你的脚本的guid了。
然后在脚本对应的mate文件里就记录这这个脚本的guid ,如果这两个id匹配,那么就说明这个prefab里挂着这个脚本了。
最后就交给正则表达式做第一步的匹配吧。 这样的话第一步就可以筛选掉一大批prefab了。 如果还需要进行验证在进一步的Instance来检查吧。。
- 本文固定链接: https://www.xuanyusong.com/archives/3727
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
如何才能查找到隐藏物体身上的组件呢?我现在遇到隐藏物体没法获取到的问题
有个小问题。
第38行,Debug.Log(transfomr.parent.name);应该是Debug.Log(transfomr.name);
感谢~
最近一直在看这个问题,试验了YAML方式,或直接Destroy的方式,很曲折,没行通。最后接收了您的建议采用文件流的方式,搞定了,贴一下网址,http://blog.csdn.net/lihuozhiling0101/article/details/52605328 第一次评论您的博客,谢谢您一直给予的帮助,谢谢。
删除丢失脚本的第二个方法也并不可行,他只会删除例如— !u!110这一列, 而他的组件信息这一组并不会删除
先把prefab 序列化的方式改成text 这一步具体怎么操作 我没看懂
Editor Setting里能改
其实不需要实例化也能查找,你依然直接用GetComponentsInChildren(true),对传true即可。。。这样搞还很麻烦。。。唯一关注是能否把Missing的脚本序列化找出来??
牛逼!!
你太牛逼了。。 我试了一下,, 空的脚本也可以找出来
MonoBehaviour[] gos = go.transform.GetComponentsInChildren(true);
for(int i =0; i < gos.Length; i++)
{
if(gos[i] == null)
{
Debug.Log("error");
}
}
你太牛逼了。。 我试了一下,, 空的脚本也可以找出来
MonoBehaviour[] gos = go.transform.GetComponentsInChildren(true);
for(int i =0; i < gos.Length; i )
{
if(gos[i] == null)
{
Debug.Log("error");
}
}
这个可以用来查找吧。。如果是删除的话,还是要实例化吧
删除的话最好实例化。。
……错了。。。不用实例化。。、。。。。。。。
首先你可能直接读取Assets下的某个对象Object o = AssetDatabase.LoadMainAssetAtPath(…);
然后获取你想要的组件后,直接用DestroyImmediate(com,true),对,此处也是传true… 然后记得可以设置一下EditorUtility.SetDirty(o);即可
很好, 我已经更正在博客中了
用这种方法不能去掉component吧,在SaveAssets的时候会报错:CheckConsistency: GameObject does not reference component MonoBehaviour. Fixing.
有几个插件可以列出引用的东西就是这么干的
嗯。 这个方法比较好。 找的比较快。。
发现你玩黑科技玩上瘾了啊,哈哈
呵呵。