优质中文开源软件代码项目资源技术共享平台
传播开源的理念,推广开源项目
学习是对自己最棒的投资!与君共勉!

网站首页 > 游戏开发 正文

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

longtao100 2021-09-04 游戏开发 410 ℃ 0 评论

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

其实不需要实例化也能查找,你依然直接用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来检查吧。。


Tags:Unity3D

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

请填写验证码
开源分类
最近发表
开源网标签
开源网归档