Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)
http://www.xuanyusong.com/archives/3727
感谢楼下的牛逼回复更正一下,我表示我也是才知道。。
其实不需要实例化也能查找,你依然直接用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
|
[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
|
[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
|
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来检查吧。。