private void BakeMesh() { if (bakeObject == null) { return; } if (animationClips.Any(clip => clip == null) && !bakeOnlyMesh) { return; } // There is a bug in AnimationMode.SampleAnimationClip which crashes // Unity if there is no valid controller attached Animator animator = bakeObject.GetComponent <Animator>(); if (animator != null && animator.runtimeAnimatorController == null && !bakeOnlyMesh) { return; } //Collect information about gameObject List <MeshFilter> tmpFilters = bakeObject.GetComponentsInChildren <MeshFilter>().ToList(); List <SkinnedMeshRenderer> tmpMeshRenderers = new List <SkinnedMeshRenderer>(); for (int i = 0; i < tmpFilters.Count; i++) { MeshFilter filter = tmpFilters[i]; SkinnedMeshRenderer meshRenderer = filter.GetComponent <SkinnedMeshRenderer>(); if (meshRenderer != null) { tmpFilters.RemoveAt(i); tmpMeshRenderers.Add(meshRenderer); i--; } } filters = tmpFilters.ToArray(); basicRenderers = filters.Select(filter => filter.GetComponent <MeshRenderer>()).ToArray(); List <Material> _materials = new List <Material>(); foreach (MeshRenderer renderer in basicRenderers) { foreach (Material mat in renderer.sharedMaterials) { if (!_materials.Contains(mat)) { _materials.Add(mat); } } } materials = _materials.ToArray(); renderers = tmpMeshRenderers.ToArray(); //Temporarily set position to zero to make matrix math easier Vector3 position = bakeObject.transform.position; bakeObject.transform.position = Vector3.zero; Mesh firstFrame = new Mesh(); EditorUtility.DisplayProgressBar("Mesh Animation Baker", "Baking", 0f); //Now bake AnimationMode.StartAnimationMode(); AnimationMode.BeginSampling(); int totalFrame = 0; int BakeClip(AnimationClip animationClip) { int clipFrameCount = bakeOnlyMesh ? 1 : GetFramesCount(animationClip); for (int frame = 0; frame < clipFrameCount; frame++) { EditorUtility.DisplayProgressBar("Mesh Animation Baker", "Baking mesh animations", 1f * (totalFrame + frame) / frameCount); if (!bakeOnlyMesh) { AnimationMode.SampleAnimationClip(bakeObject, animationClip, frame / frameRate); } Mesh bakedMesh = CombineMeshes(bakeObject); if (!bufferReady) { buffer.Expand(VertType.VNT, bakedMesh.vertexCount, frameCount); frameStride = buffer.vertexSize * buffer.vertexCount; bufferReady = true; } for (int j = 0; j < bakedMesh.vertexCount; j++) { int vertStart = j * buffer.vertexSize; int globalVertStart = frameStride * (totalFrame + frame) + vertStart; buffer.data[globalVertStart] = bakedMesh.vertices[j].x; buffer.data[globalVertStart + 1] = bakedMesh.vertices[j].y; buffer.data[globalVertStart + 2] = bakedMesh.vertices[j].z; buffer.data[globalVertStart + 3] = bakedMesh.normals[j].x; buffer.data[globalVertStart + 4] = bakedMesh.normals[j].y; buffer.data[globalVertStart + 5] = bakedMesh.normals[j].z; buffer.data[globalVertStart + 6] = bakedMesh.tangents[j].x; buffer.data[globalVertStart + 7] = bakedMesh.tangents[j].y; buffer.data[globalVertStart + 8] = bakedMesh.tangents[j].z; } if (totalFrame + frame == 0) { firstFrame = bakedMesh; } } return(bakeOnlyMesh ? 1 : GetFramesCount(animationClip)); } if (!bakeOnlyMesh) { foreach (AnimationClip clip in animationClips) { totalFrame += BakeClip(clip); } } else { BakeClip(null); } //Return to original position bakeObject.transform.position = position; string filePath = Path.Combine(Application.dataPath, vertaPath); FileInfo fileInfo = new FileInfo(filePath); if (!Directory.Exists(fileInfo.Directory.FullName)) { Directory.CreateDirectory(fileInfo.Directory.FullName); } filePath += $"/{modelName}.verta"; if (!bakeOnlyMesh) { buffer.SaveToFile(filePath); } if (targetPathObject == null) { filePath = Path.Combine("Assets", meshDataPath); } else { filePath = AssetDatabase.GetAssetPath(targetPathObject); } fileInfo = new FileInfo(filePath); if (!Directory.Exists(fileInfo.Directory.FullName)) { Directory.CreateDirectory(fileInfo.Directory.FullName); } if (debugMeshOutput) { AssetDatabase.CreateAsset(firstFrame, filePath + $"/{modelName}-mesh.asset"); } byte[] bytes = MeshDataAssetEditor.saveMeshToMeshAsset(firstFrame); MeshDataAsset asset = new MeshDataAsset(); asset.bytes = bytes; asset.materials = materials.ToArray(); AssetDatabase.CreateAsset(asset, filePath + $"/{modelName}.asset"); EditorUtility.ClearProgressBar(); AnimationMode.EndSampling(); AnimationMode.StopAnimationMode(); }
private void BakeMesh() { if (bakeObject == null) { return; } if (animationClip == null) { return; } // There is a bug in AnimationMode.SampleAnimationClip which crashes // Unity if there is no valid controller attached Animator animator = bakeObject.GetComponent <Animator>(); if (animator != null && animator.runtimeAnimatorController == null) { return; } //Collect information about gameObject List <MeshFilter> tmpFilters = bakeObject.GetComponentsInChildren <MeshFilter>().ToList(); List <SkinnedMeshRenderer> tmpMeshRenderers = new List <SkinnedMeshRenderer>(); for (int i = 0; i < tmpFilters.Count; i++) { MeshFilter filter = tmpFilters[i]; SkinnedMeshRenderer meshRenderer = filter.GetComponent <SkinnedMeshRenderer>(); if (meshRenderer != null) { tmpFilters.RemoveAt(i); tmpMeshRenderers.Add(meshRenderer); i--; } } filters = tmpFilters.ToArray(); renderers = tmpMeshRenderers.ToArray(); Mesh firstFrame = new Mesh(); EditorUtility.DisplayProgressBar("Mesh Animation Baker", "Baking", 0f); //Now bake AnimationMode.StartAnimationMode(); AnimationMode.BeginSampling(); for (int frame = 0; frame < frameCount; frame++) { EditorUtility.DisplayProgressBar("Mesh Animation Baker", "Baking mesh animations", 1f * frame / frameCount); AnimationMode.SampleAnimationClip(bakeObject, animationClip, frame / frameRate); Mesh bakedMesh = CombineMeshes(bakeObject); if (!bufferReady) { buffer.Expand(VertType.VNT, bakedMesh.vertexCount, frameCount); frameStride = buffer.vertexSize * buffer.vertexCount; bufferReady = true; } for (int i = 0; i < bakedMesh.vertexCount; i++) { int vertStart = i * buffer.vertexSize; int globalVertStart = frameStride * frame + vertStart; buffer.data[globalVertStart] = bakedMesh.vertices[i].x; buffer.data[globalVertStart + 1] = bakedMesh.vertices[i].y; buffer.data[globalVertStart + 2] = bakedMesh.vertices[i].z; buffer.data[globalVertStart + 3] = bakedMesh.normals[i].x; buffer.data[globalVertStart + 4] = bakedMesh.normals[i].y; buffer.data[globalVertStart + 5] = bakedMesh.normals[i].z; buffer.data[globalVertStart + 6] = bakedMesh.tangents[i].x; buffer.data[globalVertStart + 7] = bakedMesh.tangents[i].y; buffer.data[globalVertStart + 8] = bakedMesh.tangents[i].z; } if (frame == 0) { firstFrame = bakedMesh; } } string filePath = Path.Combine(Application.dataPath, vertaPath); FileInfo fileInfo = new FileInfo(filePath); if (!Directory.Exists(fileInfo.Directory.FullName)) { Directory.CreateDirectory(fileInfo.Directory.FullName); } filePath += $"/{modelName}.verta"; buffer.SaveToFile(filePath); filePath = Path.Combine("Assets", meshDataPath); fileInfo = new FileInfo(filePath); if (!Directory.Exists(fileInfo.Directory.FullName)) { Directory.CreateDirectory(fileInfo.Directory.FullName); } filePath += $"/{modelName}.asset"; byte[] bytes = MeshDataAssetEditor.saveMeshToMeshAsset(firstFrame); MeshDataAsset asset = new MeshDataAsset(); asset.bytes = bytes; AssetDatabase.CreateAsset(asset, filePath); EditorUtility.ClearProgressBar(); AnimationMode.EndSampling(); AnimationMode.StopAnimationMode(); }