/// <summary> /// 判断是否可创建临时材质 /// </summary> /// <param name="mom"></param> /// <returns></returns> public static bool _OkToCreateDummyTextureBakeResult(MeshBakerCommon mom) { List <GameObject> objsToMesh = mom.GetObjectsToCombine(); if (objsToMesh.Count == 0) { return(false); } return(true); }
/// <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> /// 保存网格资源至 Asset 中 /// </summary> public static void SaveMeshsToAssetDatabase(MeshBakerCommon mom, string folderPath, string newFileNameBase) { if (mom is MeshCombinerEntrance) { MeshCombinerEntrance mb = (MeshCombinerEntrance)mom; string newFilename = newFileNameBase + ".asset"; string ap = AssetDatabase.GetAssetPath(((MeshCombineHandler)mb.meshCombiner).GetMesh()); if (ap == null || ap.Equals("")) { Debug.Log("保存网格资源 " + newFilename); AssetDatabase.CreateAsset(((MeshCombineHandler)mb.meshCombiner).GetMesh(), newFilename); } else { Debug.Log("Mesh is an asset at " + ap); } } //else if (mom is MB3_MultiMeshBaker) //{ // MB3_MultiMeshBaker mmb = (MB3_MultiMeshBaker)mom; // List<MB3_MultiMeshCombiner.CombinedMesh> combiners = ((MB3_MultiMeshCombiner)mmb.meshCombiner).meshCombiners; // for (int i = 0; i < combiners.Count; i++) // { // string newFilename = newFileNameBase + i + ".asset"; // Mesh mesh = combiners[i].combinedMesh.GetMesh(); // string ap = AssetDatabase.GetAssetPath(mesh); // if (ap == null || ap.Equals("")) // { // Debug.Log("Saving mesh asset to " + newFilename); // AssetDatabase.CreateAsset(mesh, newFilename); // } // else // { // Debug.Log("Mesh is an asset at " + ap); // } // } //} else { Debug.LogError("Argument was not a MeshCombineEntrance or an MultiMeshBaker."); } }
/// <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); }
public static bool BakeIntoCombined(MeshBakerCommon mom, out bool createdDummyTextureBakeResults) { SerializedObject so = null; return(BakeIntoCombined(mom, out createdDummyTextureBakeResults, ref so)); }
public static bool bake(MeshBakerCommon mom) { SerializedObject so = null; return(bake(mom, ref so)); }
private void DrawGUI(SerializedObject meshBaker, MeshBakerCommon target, System.Type editorWindowType) { if (meshBaker == null) { return; } meshBaker.Update(); //说明窗口 showInstructions = EditorGUILayout.Foldout(showInstructions, "说明:"); if (showInstructions) { EditorGUILayout.HelpBox("1. Bake combined material(s).\n\n" + "2. If necessary set the 'Texture Bake Results' field.\n\n" + "3. Add scene objects or prefabs to combine or check 'Same As Texture Baker'. For best results these should use the same shader as result material.\n\n" + "4. Select options and 'Bake'.\n\n" + "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" + "7. (optional) Disable renderers in source objects.", UnityEditor.MessageType.None); EditorGUILayout.Separator(); } MeshBakerCommon momm = (MeshBakerCommon)target; //已合并材质资源 EditorGUILayout.PropertyField(textureBakeResults, gc_textureBakeResultsGUIContent); if (textureBakeResults.objectReferenceValue != null) { showContainsReport = EditorGUILayout.Foldout(showContainsReport, "Shaders & Materials Contained"); if (showContainsReport) { EditorGUILayout.HelpBox(((TextureBakeResults)textureBakeResults.objectReferenceValue).GetDescription(), MessageType.Info); } } EditorGUILayout.BeginVertical(editorStyles.editorBoxBackgroundStyle); //参与网格合并物体列表 EditorGUILayout.LabelField("合并物体列表", EditorStyles.whiteBoldLabel); if (momm.GetTextureBaker() != null) { EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent); } else { useObjsToMeshFromTexBaker.boolValue = false; momm.useObjsToMeshFromTexBaker = false; GUI.enabled = false; EditorGUILayout.PropertyField(useObjsToMeshFromTexBaker, gc_useTextureBakerObjsGUIContent); GUI.enabled = true; } //与参与材质合并物体不同 if (!momm.useObjsToMeshFromTexBaker) { //添加工具 if (GUILayout.Button(gc_openToolsWindowLabelContent)) { IMeshCombinerEditorWindow mmWin = (IMeshCombinerEditorWindow)EditorWindow.GetWindow(editorWindowType); mmWin.target = (MeshBakerRoot)target; } object[] objs = EditorMethods.DropZone("Drag & Drop Renderers Or Parents Here To Add Objects To Be Combined", 300, 50); EditorMethods.AddDroppedObjects(objs, momm); EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true); EditorGUILayout.Separator(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Select Objects In Scene")) { Selection.objects = momm.GetObjectsToCombine().ToArray(); if (momm.GetObjectsToCombine().Count > 0) { SceneView.lastActiveSceneView.pivot = momm.GetObjectsToCombine()[0].transform.position; } } if (GUILayout.Button(gc_SortAlongAxis)) { MeshBakerRoot.ZSortObjects sorter = new MeshBakerRoot.ZSortObjects(); sorter.sortAxis = sortOrderAxis.vector3Value; sorter.SortByDistanceAlongAxis(momm.GetObjectsToCombine()); } EditorGUILayout.PropertyField(sortOrderAxis, GUIContent.none); EditorGUILayout.EndHorizontal(); } else { GUI.enabled = false; EditorGUILayout.PropertyField(objsToMesh, gc_objectsToCombineGUIContent, true); GUI.enabled = true; } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.LabelField("输出:", EditorStyles.boldLabel); EditorGUILayout.PropertyField(outputOptions, gc_outputOptoinsGUIContent); //输出方式设置 if (momm.meshCombiner.outputOption == OutputOptions.bakeIntoSceneObject) { momm.meshCombiner.resultSceneObject = (GameObject)EditorGUILayout.ObjectField("合并后游戏物体", momm.meshCombiner.resultSceneObject, typeof(GameObject), true); if (momm is MeshCombinerEntrance) { string l = "Mesh"; Mesh m = (Mesh)mesh.objectReferenceValue; if (m != null) { l += " (" + m.GetInstanceID() + ")"; } Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true); if (nm != m) { Undo.RecordObject(momm, "Assign Mesh"); ((MeshCombineHandler)momm.meshCombiner).SetMesh(nm); mesh.objectReferenceValue = nm; } } } //合并为预制体 else if (momm.meshCombiner.outputOption == OutputOptions.bakeIntoPrefab) { momm.resultPrefab = (GameObject)EditorGUILayout.ObjectField( gc_combinedMeshPrefabGUIContent, momm.resultPrefab, typeof(GameObject), true); if (momm is MeshCombinerEntrance) { string l = "Mesh"; Mesh m = (Mesh)mesh.objectReferenceValue; if (m != null) { l += " (" + m.GetInstanceID() + ")"; } Mesh nm = (Mesh)EditorGUILayout.ObjectField(new GUIContent(l), m, typeof(Mesh), true); if (nm != m) { Undo.RecordObject(momm, "Assign Mesh"); ((MeshCombineHandler)momm.meshCombiner).SetMesh(nm); mesh.objectReferenceValue = nm; } } } //合并磁盘中文件 else if (momm.meshCombiner.outputOption == OutputOptions.bakeMeshAssetsInPlace) { EditorGUILayout.HelpBox("Try the BatchPrefabBaker component. " + "It makes preparing a batch of prefabs for static/ dynamic batching much easier.", MessageType.Info); if (GUILayout.Button("Choose Folder For Bake In Place Meshes")) { string newFolder = EditorUtility.SaveFolderPanel("Folder For Bake In Place Meshes", Application.dataPath, ""); if (!newFolder.Contains(Application.dataPath)) { Debug.LogWarning("The chosen folder must be in your assets folder."); } momm.bakeAssetsInPlaceFolderPath = "Assets" + newFolder.Replace(Application.dataPath, ""); } EditorGUILayout.LabelField("Folder For Meshes: " + momm.bakeAssetsInPlaceFolderPath); } //if (momm is MB3_MultiMeshBaker) //{ // ////MB3_MultiMeshCombiner mmc = (MB3_MultiMeshCombiner)momm.meshCombiner; // ////mmc.maxVertsInMesh = EditorGUILayout.IntField("Max Verts In Mesh", mmc.maxVertsInMesh); //} //----------------------------------- EditorGUILayout.Space(); EditorGUILayout.LabelField("网格合并设置:", EditorStyles.boldLabel); bool settingsEnabled = true; //------------- Mesh Baker Settings is a bit tricky because it is an interface. UnityEngine.Object obj = settingsHolder.objectReferenceValue; //通用合并网格设置 // Don't use a PropertyField because we may not be able to use the assigned object. // It may not implement requried interface. obj = EditorGUILayout.ObjectField(gc_Settings, obj, typeof(UnityEngine.Object), true); //通用设置为空,使用下方设置 if (obj == null) { settingsEnabled = true; settingsHolder.objectReferenceValue = null; if (meshBakerSettingsExternal != null) { meshBakerSettingsExternal.OnDisable(); meshBakerSettingsExternal = null; } } else if (obj is GameObject) { // Check to see if there is a component on this game object that implements MB_IMeshBakerSettingsHolder IMeshCombinerSettingHolder itf = (IMeshCombinerSettingHolder)((GameObject)obj).GetComponent(typeof(IMeshCombinerSettingHolder)); if (itf != null) { settingsEnabled = false; Component settingsHolderComponent = (Component)itf; if (settingsHolder.objectReferenceValue != settingsHolderComponent) { settingsHolder.objectReferenceValue = settingsHolderComponent; meshBakerSettingsExternal = new MeshCombineSettingEditor(); meshBakerSettingsExternal.OnEnable(itf.GetMeshBakerSettingsAsSerializedProperty()); } } else { settingsEnabled = true; settingsHolder = null; if (meshBakerSettingsExternal != null) { meshBakerSettingsExternal.OnDisable(); meshBakerSettingsExternal = null; } } } else if (obj is IMeshCombinerSettingHolder) { settingsEnabled = false; if (settingsHolder.objectReferenceValue != obj) { settingsHolder.objectReferenceValue = obj; meshBakerSettingsExternal = new MeshCombineSettingEditor(); meshBakerSettingsExternal.OnEnable(((IMeshCombinerSettingHolder)obj).GetMeshBakerSettingsAsSerializedProperty()); } } else { Debug.LogError("Object was not a Mesh Baker Settings object."); } EditorGUILayout.Space(); if (settingsHolder.objectReferenceValue == null) { // Use the meshCombiner settings meshBakerSettingsThis.DrawGUI(momm.meshCombiner, settingsEnabled); } else { if (meshBakerSettingsExternal == null) { meshBakerSettingsExternal = new MeshCombineSettingEditor(); meshBakerSettingsExternal.OnEnable(((IMeshCombinerSettingHolder)obj).GetMeshBakerSettingsAsSerializedProperty()); } var set = settingsHolder.objectReferenceValue; var settings = (IMeshCombinerSettingHolder)settingsHolder.objectReferenceValue; meshBakerSettingsExternal.DrawGUI(settings.GetMeshBakerSettings(), settingsEnabled); } Color oldColor = GUI.backgroundColor; GUI.backgroundColor = buttonColor; if (GUILayout.Button("合并")) { bake(momm, ref meshBaker); } GUI.backgroundColor = oldColor; string enableRenderersLabel; bool disableRendererInSource = false; if (momm.GetObjectsToCombine().Count > 0) { Renderer r = MeshBakerUtility.GetRenderer(momm.GetObjectsToCombine()[0]); if (r != null && r.enabled) { disableRendererInSource = true; } } if (disableRendererInSource) { enableRenderersLabel = "隐藏源游戏物体"; } else { enableRenderersLabel = "显示源游戏物体"; } if (GUILayout.Button(enableRenderersLabel)) { momm.EnableDisableSourceObjectRenderers(!disableRendererInSource); } meshBaker.ApplyModifiedProperties(); meshBaker.SetIsDifferentCacheDirty(); }