/// <summary> /// Bakes a combined mesh. /// </summary> /// <param name="mom"></param> /// <param name="so">This is needed to work around a Unity bug where UnpackPrefabInstance corrupts /// a SerializedObject. Only needed for bake into prefab.</param> public static bool bake(MeshBakerCommon mom, ref SerializedObject so) { bool createdDummyTextureBakeResults = false; bool success = false; try { if (mom.meshCombiner.outputOption == OutputOptions.bakeIntoSceneObject || mom.meshCombiner.outputOption == OutputOptions.bakeIntoPrefab) { success = MeshCombinerEditorFunctions.BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so); } else { //bake meshes in place if (mom is MeshCombinerEntrance) { ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust; if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.prefabOnly, new EditorMethods(), vl)) { return(false); } List <GameObject> objsToMesh = mom.GetObjectsToCombine(); ////success = MB3_BakeInPlace.BakeMeshesInPlace((MeshCombineHandler)((MeshCombinerEntrance)mom).meshCombiner, objsToMesh, mom.bakeAssetsInPlaceFolderPath, mom.clearBuffersAfterBake, updateProgressBar); } else { //多网格合并无法 Bake In Place Debug.LogError("Multi-mesh Baker components cannot be used for Bake In Place. Use an ordinary Mesh Baker object instead."); } } mom.meshCombiner.CheckIntegrity(); } catch (Exception e) { Debug.LogError(e); } finally { if (createdDummyTextureBakeResults && mom.textureBakeResults != null) { MeshBakerUtility.Destroy(mom.textureBakeResults); mom.textureBakeResults = null; } EditorUtility.ClearProgressBar(); } return(success); }
/// <summary> /// 构建预制体 /// </summary> /// <param name="mom"></param> /// <param name="so"></param> public static void RebuildPrefab(MeshBakerCommon mom, ref SerializedObject so) { GameObject prefabRoot = mom.resultPrefab; GameObject rootGO = (GameObject)PrefabUtility.InstantiatePrefab(prefabRoot); SceneBakerUtilityInEditor.UnpackPrefabInstance(rootGO, ref so); //remove all renderer childeren of rootGO Renderer[] rs = rootGO.GetComponentsInChildren <Renderer>(); for (int i = 0; i < rs.Length; i++) { if (rs[i] != null && rs[i].transform.parent == rootGO.transform) { MeshBakerUtility.Destroy(rs[i].gameObject); } } if (mom is MeshCombinerEntrance) { MeshCombinerEntrance entrance = (MeshCombinerEntrance)mom; MeshCombineHandler mbs = (MeshCombineHandler)entrance.meshCombiner; MeshCombineHandler.BuildPrefabHierarchy(mbs, rootGO, mbs.GetMesh()); } ////else if (mom is MB3_MultiMeshBaker) ////{ //// MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom; //// MB3_MultiMeshCombiner mbs = (MB3_MultiMeshCombiner)mmb.meshCombiner; //// for (int i = 0; i < mbs.meshCombiners.Count; i++) //// { //// MB3_MeshCombinerSingle.BuildPrefabHierarchy(mbs.meshCombiners[i].combinedMesh, rootGO, mbs.meshCombiners[i].combinedMesh.GetMesh(), true); //// } ////} else { Debug.LogError("MeshCombiner合并器类型错误"); } //保存预制体 string prefabPth = AssetDatabase.GetAssetPath(prefabRoot); SceneBakerUtilityInEditor.ReplacePrefab(rootGO, prefabPth, ReplacePrefabOption.connectToPrefab); if (mom.meshCombiner.renderType != RendererType.skinnedMeshRenderer) { // For Skinned meshes, leave the prefab instance in the scene so source game objects can moved into the prefab. UnityEditor.Editor.DestroyImmediate(rootGO); } }
/// <summary> /// 创建图集 /// </summary> public static void CreateAtlases(List <GameObject> GameObjectsToCombine, bool saveAtlasesAsAssets = false) { try { combineData.ResultAtlasesAndRects = null; combineData.saveAtlasesAsAssets = saveAtlasesAsAssets; //--- 1、合并前检测 if (!ValidateCombineGameObject(GameObjectsToCombine)) { return; } //材质验证 if (combineData.DoMultiMaterial) { if (!_ValidateResultMaterials(GameObjectsToCombine, combineData.ResultMaterials)) { return; } } else { if (!ValidateSingleResultMaterial(GameObjectsToCombine, combineData.ResultMaterial)) { return; } } ////--- 2、初始化存储合并结果的数据结构 int numResults = 1; if (combineData.DoMultiMaterial) { numResults = combineData.ResultMaterials.Length; } combineData.ResultAtlasesAndRects = new AtlasesAndRects[numResults]; for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++) { combineData.ResultAtlasesAndRects[i] = new AtlasesAndRects(); } //--- 3、开始合并材质(单个,多个) for (int i = 0; i < combineData.ResultAtlasesAndRects.Length; i++) { Material resultMat; List <Material> sourceMats; if (combineData.DoMultiMaterial) { sourceMats = combineData.ResultMaterials[i].sourceMaterials; resultMat = combineData.ResultMaterials[i].combinedMaterial; combineData.fixOutOfBoundsUVs = combineData.ResultMaterials[i].considerMeshUVs; } else { resultMat = combineData.ResultMaterial; sourceMats = null; //为空则为全部合并 } CombineTexturesIntoAtlases(combineData.ResultAtlasesAndRects[i], resultMat, GameObjectsToCombine, sourceMats, null); } //--- 4、TextureBakeResults 保存合并结果 //unpackMat2RectMap(textureBakeResults); //textureBakeResults.doMultiMaterial = _doMultiMaterial; //if (_doMultiMaterial) //{ // textureBakeResults.resultMaterials = resultMaterials; //} //else //{ // MultiMaterial[] resMats = new MultiMaterial[1]; // resMats[0] = new MultiMaterial(); // resMats[0].combinedMaterial = _resultMaterial; // resMats[0].considerMeshUVs = _fixOutOfBoundsUVs; // resMats[0].sourceMaterials = new List<Material>(); // for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++) // { // resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material); // } // textureBakeResults.resultMaterials = resMats; //} ////--- 5、传递合并结果到 MeshCombiner //MeshBakerCommon[] mb = GetComponentsInChildren<MeshBakerCommon>(); //for (int i = 0; i < mb.Length; i++) //{ // mb[i].textureBakeResults = textureBakeResults; //} //coroutineResult.isFinished = true; ////--- 6、合并材质结束回调 //if (coroutineResult.success && onBuiltAtlasesSuccess != null) //{ // onBuiltAtlasesSuccess(); //} //if (!coroutineResult.success && onBuiltAtlasesFail != null) //{ // onBuiltAtlasesFail(); //} } catch (Exception e) { Debug.LogError(e); } finally { if (saveAtlasesAsAssets) { //Atlases were saved to project so we don't need these ones if (combineData.ResultAtlasesAndRects != null) { for (int j = 0; j < combineData.ResultAtlasesAndRects.Length; j++) { AtlasesAndRects mAndA = combineData.ResultAtlasesAndRects[j]; if (mAndA != null && mAndA.atlases != null) { for (int i = 0; i < mAndA.atlases.Length; i++) { if (mAndA.atlases[i] != null) { //if (editorMethods != null) //{ // editorMethods.Destroy(mAndA.atlases[i]); //} //else //{ MeshBakerUtility.Destroy(mAndA.atlases[i]); //} } } } } } } } }
/// <summary> /// Bakes a combined mesh. /// 如果是从Inspector代码中调用的,则传入该组件的SerializedObject /// 对于“烘焙到预制”可能会损坏SerializedObject。这是必需的 /// </summary> public static bool BakeIntoCombined(MeshBakerCommon mom, out bool createdDummyTextureBakeResults, ref SerializedObject so) { OutputOptions prefabOrSceneObject = mom.meshCombiner.outputOption; createdDummyTextureBakeResults = false; if (prefabOrSceneObject != OutputOptions.bakeIntoPrefab && prefabOrSceneObject != OutputOptions.bakeIntoSceneObject) { Debug.LogError("Paramater prefabOrSceneObject must be bakeIntoPrefab or bakeIntoSceneObject"); return(false); } //从父物体获得 贴图合并组件及其贴图合并结果 Asset TextureCombineEntrance tb = mom.GetComponentInParent <TextureCombineEntrance>(); if (mom.textureBakeResults == null && tb != null) { mom.textureBakeResults = tb.textureBakeResults; } //贴图合并结果为空时,则创建 if (mom.textureBakeResults == null) { if (_OkToCreateDummyTextureBakeResult(mom)) { createdDummyTextureBakeResults = true; List <GameObject> gos = mom.GetObjectsToCombine(); if (mom.GetNumObjectsInCombined() > 0) { if (mom.clearBuffersAfterBake) { mom.ClearMesh(); } else { Debug.LogError("'Texture Bake Result' must be set to add more objects to a combined mesh that " + "already contains objects. Try enabling 'clear buffers after bake'"); return(false); } } mom.textureBakeResults = TextureBakeResults.CreateForMaterialsOnRenderer( gos.ToArray(), mom.meshCombiner.GetMaterialsOnTargetRenderer()); Debug.Log("'Texture Bake Result' was not set. " + "Creating a temporary one. Each material will be mapped to a separate submesh."); } } //合并检测 ValidationLevel vl = Application.isPlaying ? ValidationLevel.quick : ValidationLevel.robust; if (!MeshBakerRoot.DoCombinedValidate(mom, ObjsToCombineTypes.sceneObjOnly, new EditorMethods(), vl)) { return(false); } //检测空预制体资源是否已创建 if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab && mom.resultPrefab == null) { Debug.LogError("Need to set the Combined Mesh Prefab field. " + "Create a prefab asset, drag an empty game object into it, and drag it to the 'Combined Mesh Prefab' field."); return(false); } if (mom.meshCombiner.resultSceneObject != null && (SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.modelPrefab || SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject) == PrefabType.prefab)) { Debug.LogWarning("Result Game Object was a project asset not a scene object instance. Clearing this field."); mom.meshCombiner.resultSceneObject = null; } mom.ClearMesh(); //合并 if (mom.AddDeleteGameObjects(mom.GetObjectsToCombine().ToArray(), null, false)) { mom.Apply(UnwrapUV2); if (createdDummyTextureBakeResults) { //临时合并的贴图 Debug.Log(String.Format("Successfully baked {0} meshes each material is mapped to its own submesh.", mom.GetObjectsToCombine().Count)); } else { Debug.Log(String.Format("Successfully baked {0} meshes", mom.GetObjectsToCombine().Count)); } if (prefabOrSceneObject == OutputOptions.bakeIntoSceneObject) { PrefabType pt = SceneBakerUtilityInEditor.GetPrefabType(mom.meshCombiner.resultSceneObject); if (pt == PrefabType.prefab || pt == PrefabType.modelPrefab) { Debug.LogError("Combined Mesh Object is a prefab asset. " + "If output option bakeIntoSceneObject then this must be an instance in the scene."); return(false); } } else if (prefabOrSceneObject == OutputOptions.bakeIntoPrefab) { string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab); if (prefabPth == null || prefabPth.Length == 0) { Debug.LogError("无法保存,合并游戏物体并非磁盘上的资源。"); return(false); } string baseName = Path.GetFileNameWithoutExtension(prefabPth); string folderPath = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7); string newFilename = folderPath + baseName + "-mesh"; //保存网格资源 SaveMeshsToAssetDatabase(mom, folderPath, newFilename); if (mom.meshCombiner.renderType == RendererType.skinnedMeshRenderer) { Debug.LogWarning("Render type is skinned mesh renderer. " + "Can't create prefab until all bones have been added to the combined mesh object " + mom.resultPrefab + " Add the bones then drag the combined mesh object to the prefab."); } //构建 Prefab RebuildPrefab(mom, ref so); MeshBakerUtility.Destroy(mom.meshCombiner.resultSceneObject); } else { Debug.LogError("合并输出类型出错"); return(false); } } else { //加入合并失败 if (mom.clearBuffersAfterBake) { mom.meshCombiner.ClearBuffers(); } if (createdDummyTextureBakeResults) { MeshBakerUtility.Destroy(mom.textureBakeResults); } return(false); } //清除缓存数据 if (mom.clearBuffersAfterBake) { mom.meshCombiner.ClearBuffers(); } //临时Texture if (createdDummyTextureBakeResults) { MeshBakerUtility.Destroy(mom.textureBakeResults); } return(true); }