上QQ阅读APP看书,第一时间看更新
2.14 自动创建Prefab
经过前面的步骤,我们会发现Unity提供了可视化工具,在编辑器中甚至不用编写代码便可以自由装配Prefab,快速实现游戏中需要的某些功能。但这种方式也有缺点,当一个Prefab比较复杂时,重新装配或修改Prefab需要较多的工作,比如我们要再创建10个不同的敌人,就需要手动重复前面的步骤10次,工作量很大,也容易出错。
所有在Unity编辑器中的手动操作都可以使用代码完成。这样,只需要编写一次代码,很多重复的工作就省掉了。以Enemy2b的Prefab制作为例,我们将完全使用代码来创建它。
步骤 01 首先,我们要编写一个编辑器脚本,它的作用是在当模型被导入到Unity工程中时自动将这个模型创建为Prefab。在工程目录中创建一个名为Editor的文件夹,在里面创建脚本ProcessModel.cs,保存在Editor中的脚本不能在游戏运行时使用。
步骤 02 编辑脚本ProcessModel.cs,添加using UnityEditor,这样就能使用Unity的编辑器相关API。这里定义的ProcessModel类继承自AssetPostprocessor,它专门用来处理资源导入。OnPostprocessModel方法在导入模型时会被自动调用,其中的参数GameObject即是导入的模型。我们在ProcessModel方法中将Enemy2b.fbx直接制作为一个Prefab,并命名为Enemy2c.Prefab,代码如下:
using UnityEngine; using UnityEditor; class ProcessModel : AssetPostprocessor { void OnPostprocessModel( GameObject input ) { // 只处理名为"Enemy2b"的模型 if (! input.name.Contains("Enemy2b")) return; // 设置导入模型的tag input.tag = "Enemy"; // 查找碰撞模型 foreach (Transform obj in input.GetComponentsInChildren<Transform>()) { if (obj.name.CompareTo("col") == 0) { // 取消碰撞模型的显示 MeshRenderer r = obj.GetComponent<MeshRenderer>(); r.enabled = false; // 添加Mesh碰撞体 obj.gameObject.AddComponent<MeshCollider>(); // 设置碰撞体的tag obj.tag = "Enemy"; } else { obj.gameObject.AddComponent<EnemyRenderer>(); //指定Renderer脚本 } } // 设置刚体 Rigidbody rigid = input.AddComponent<Rigidbody>(); rigid.useGravity = false; rigid.isKinematic = true; // 取得导入模型的相关信息 ModelImporter importer = assetImporter as ModelImporter; // 从工程中将该模型读出来 GameObject tar =(GameObject)AssetDatabase.LoadAssetAtPath(importer.assetPath, typeof(GameObject)); // 将这个模型创建为prefab GameObject prefab = (GameObject)PrefabUtility.CreatePrefab("Assets/Prefabs/Enemy2c.prefab", tar ); // 为prefab添加声音组件 prefab.AddComponent<AudioSource>(); // 获得子弹的prefab GameObject rocket = (GameObject)AssetDatabase.LoadAssetAtPath("Assets/Prefabs/EnemyRocket.prefab", typeof(GameObject)); // 获得爆炸效果的prefab var fx =(GameObject)AssetDatabase.LoadAssetAtPath("Assets/FX/Explosion.prefab", typeof(GameObject)); // 为prefab添加脚本 SuperEnemy enemy=prefab.AddComponent<SuperEnemy>(); // 设置脚本的默认参数 enemy.m_life = 50; enemy.m_point = 50; enemy.m_rocket= rocket.transform; enemy.m_explosionFX = fx.transform; } }
重新导入Enemy2b.fbx, ProcessModel.cs会被调用,并自动创建Enemy2c.Prefab,它的所有功能和设置均与前面手动设置的Prefab相同。