DinoFracture Engine, an asset for adding to Unity fracture effect easier to any meshes is very nice product.
https://assetstore.unity.com/packages/tools/physics/dinofracture-a-dynamic-fracture-library-26599
It can generate fractures runtime and editor. But if you try to make fracture in editor (not play mode), you have to make specific scene and attach PreFracturedGeometory component, and press "Create Fractures" button.
In my case there are lots of meshes have to make fractures, so I made a script for Dino Fracture, to generate fractures without the clicking works in the scene.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEditor;
using DinoFracture;
using DinoFracture.Editor;
public class PreFractureInAssetFolder: PreFracturedGeometryEditor
{
private const string PrefabFolderPath = "Assets/{your prefab folder path}";
private const string MeshFolderPath = "Assets/{your mesh folder path}";
private const string ExportFolderName = "PreFractured";
private const string InsideMaterialPath = "Assets/{your inside material path}.mat";
private const string StandardFractureTemplatePath = "Assets/DinoFracture/Plugin/Prefabs/StandardFracturePiece.prefab";
[MenuItem("Tools/DinoFracture/PreFractureInAssetFolder")]
public static void PreFracture()
{
//filter paths you want generate fractures
string[] allPath = AssetDatabase.GetAllAssetPaths();
var prefabPathList = allPath.Where(p => p.Contains(PrefabFolderPath))
.Where(p2 => !p2.Contains(ExportFolderName)).ToList();
var objectCount = prefabPathList.Count;
for (var index = 0; index < objectCount; index++)
{
var prefabPath = prefabPathList[index];
var contentsRoot = PrefabUtility.LoadPrefabContents(prefabPath);
if (contentsRoot.GetComponent<MeshFilter>() == false)
{
Debug.Log("contentsRoot " + contentsRoot.name +"doesnt has meshfilter");
objectCount--;
continue;
}
MakeFractureMeshes(contentsRoot, prefabPath, objectCount);
}
}
private static void MakeFractureMeshes(GameObject contentsRoot, string prefabPath, int objectCount)
{
List<Tuple<Mesh, string>> meshAssetList = new List<Tuple<Mesh, string>>();
List<Tuple<GameObject, string, string>> prefabAssetList = new List<Tuple<GameObject, string, string>>();
var standardFractureTemplate = AssetDatabase.LoadAssetAtPath<GameObject>(StandardFractureTemplatePath);
var insideMaterial = AssetDatabase.LoadAssetAtPath<Material>(InsideMaterialPath);
var geom = contentsRoot.AddComponent<PreFracturedGeometry>();
geom.FractureTemplate = standardFractureTemplate;
geom.InsideMaterial = insideMaterial;
//set parametors as you want
geom.NumFracturePieces = 4;
geom.NumIterations = 2;
geom.NumGenerations = 2;
geom.UVScale = FractureUVScale.EntireMesh;
geom.GenerateFractureMeshes(
(g) =>
{
g.GeneratedPieces.SetActive(true);
//generate meshes
string meshSaveFolderPath = Path.Combine(MeshFolderPath, ExportFolderName, geom.gameObject.name);
for (int i = 0; i < geom.GeneratedPieces.transform.childCount; i++)
{
var pieceTransform = geom.GeneratedPieces.transform.GetChild(i);
//in my case mesh collider is much CPU usage so replase to BoxCollider
var meshCollider = pieceTransform.GetComponent<MeshCollider>();
GameObject.DestroyImmediate(meshCollider);
var boxCollider = pieceTransform.gameObject.AddComponent<BoxCollider>();
boxCollider.enabled = false;
var rigidbody = pieceTransform.GetComponent<Rigidbody>();
rigidbody.isKinematic = true;
MeshFilter mf = geom.GeneratedPieces.transform.GetChild(i).GetComponent<MeshFilter>();
if (mf != null && mf.sharedMesh != null)
{
meshAssetList.Add(new Tuple<Mesh, string>(mf.sharedMesh, meshSaveFolderPath));
}
}
//save prefabs
var prefabSaveFolderPath = Path.Combine(Path.GetDirectoryName(prefabPath), ExportFolderName);
prefabAssetList.Add(new Tuple<GameObject, string, string>(g.GeneratedPieces, prefabSaveFolderPath,
contentsRoot.name + ".prefab"));
if (prefabAssetList.Count >= objectCount)
{
SaveProcess(meshAssetList, prefabAssetList);
}
});
}
private static void SaveProcess(List<Tuple<Mesh, string>> meshAssetList, List<Tuple<GameObject, string, string>> prefabAssetList)
{
Debug.Log("save process");
//stop Asset import Postprocess
AssetDatabase.StartAssetEditing();
//save mesh
foreach (var meshAsset in meshAssetList)
{
DirectoryInfo dir = new DirectoryInfo(meshAsset.Item2);
if (!dir.Exists)
{
dir.Create();
}
else
{
// delete old meshes
foreach (FileInfo file in dir.GetFiles())
{
file.Delete();
}
}
string assetPath = Path.Combine(meshAsset.Item2, String.Format("{0}.asset", Guid.NewGuid().ToString("B")));
AssetDatabase.CreateAsset(meshAsset.Item1, assetPath);
}
//save prefab
foreach (var prefabAsset in prefabAssetList)
{
DirectoryInfo dir = new DirectoryInfo(prefabAsset.Item2);
if (!dir.Exists)
{
dir.Create();
}
PrefabUtility.SaveAsPrefabAsset(prefabAsset.Item1, Path.Combine(prefabAsset.Item2, prefabAsset.Item3 ));
GameObject.DestroyImmediate(prefabAsset.Item1);
}
meshAssetList.Clear();
prefabAssetList.Clear();
AssetDatabase.StopAssetEditing();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
Top comments (0)