- Home /
Script to break mesh into smaller pieces?
Hi,
I looked at assets such as https://www.assetstore.unity3d.com/en/#!/content/9411 but they are quite expensive, I would like to ask if there is a free or cheaper alternative to be able to spit a mesh into many small pieces/rigidbodies? Any advise would be appreciated.
Answer by Cherno · Jul 13, 2015 at 08:31 PM
Here is a script that will create seperate triangle rigidbodies from the gameObject's mesh and make them explode, for a nice shattering effect. Works great for low-poly object, but might lead to performancy issues with medium-to high poly count objects. I think I found it on the unity wiki.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TriangleExplosion : MonoBehaviour {
public IEnumerator SplitMesh (bool destroy) {
if(GetComponent<MeshFilter>() == null || GetComponent<SkinnedMeshRenderer>() == null) {
yield return null;
}
if(GetComponent<Collider>()) {
GetComponent<Collider>().enabled = false;
}
Mesh M = new Mesh();
if(GetComponent<MeshFilter>()) {
M = GetComponent<MeshFilter>().mesh;
}
else if(GetComponent<SkinnedMeshRenderer>()) {
M = GetComponent<SkinnedMeshRenderer>().sharedMesh;
}
Material[] materials = new Material[0];
if(GetComponent<MeshRenderer>()) {
materials = GetComponent<MeshRenderer>().materials;
}
else if(GetComponent<SkinnedMeshRenderer>()) {
materials = GetComponent<SkinnedMeshRenderer>().materials;
}
Vector3[] verts = M.vertices;
Vector3[] normals = M.normals;
Vector2[] uvs = M.uv;
for (int submesh = 0; submesh < M.subMeshCount; submesh++) {
int[] indices = M.GetTriangles(submesh);
for (int i = 0; i < indices.Length; i += 3) {
Vector3[] newVerts = new Vector3[3];
Vector3[] newNormals = new Vector3[3];
Vector2[] newUvs = new Vector2[3];
for (int n = 0; n < 3; n++) {
int index = indices[i + n];
newVerts[n] = verts[index];
newUvs[n] = uvs[index];
newNormals[n] = normals[index];
}
Mesh mesh = new Mesh();
mesh.vertices = newVerts;
mesh.normals = newNormals;
mesh.uv = newUvs;
mesh.triangles = new int[] { 0, 1, 2, 2, 1, 0 };
GameObject GO = new GameObject("Triangle " + (i / 3));
GO.layer = LayerMask.NameToLayer("Particle");
GO.transform.position = transform.position;
GO.transform.rotation = transform.rotation;
GO.AddComponent<MeshRenderer>().material = materials[submesh];
GO.AddComponent<MeshFilter>().mesh = mesh;
GO.AddComponent<BoxCollider>();
Vector3 explosionPos = new Vector3(transform.position.x + Random.Range(-0.5f, 0.5f), transform.position.y + Random.Range(0f, 0.5f), transform.position.z + Random.Range(-0.5f, 0.5f));
GO.AddComponent<Rigidbody>().AddExplosionForce(Random.Range(300,500), explosionPos, 5);
Destroy(GO, 5 + Random.Range(0.0f, 5.0f));
}
}
GetComponent<Renderer>().enabled = false;
yield return new WaitForSeconds(1.0f);
if(destroy == true) {
Destroy(gameObject);
}
}
}
You can use it like this:
gameObject.AddComponent<TriangleExplosion>();
StartCoroutine(gameObject.GetComponent<TriangleExplosion().SplitMesh(true));
Very cool, thanks! is there a way to control the mesh splitting complexity in this script? I am trying to figure it out if yes or not, but looks very nice.
No, there isn't. You'd have to create that functionality yourself. Take a look at the $$anonymous$$esh class on the Unity Scripting API. The alternative is to create a prefab for each model that consist of several pieces, and instantiate that one when the explosion should occur.
How to $$anonymous$$ake an Object Shatter Into Smaller Fragments in Unity
Wow, this is awesome. Very easy to understand and with amazing result.
Hi,
When i add the above code, i am getting the following error . Could you pls help?
'A game object can only be in one layer. The layer needs to be in the range [0...31] UnityEngine.GameObject:set_layer(Int32) c__Iterator0:$$anonymous$$oveNext() (at Assets/Scripts/TriangleExplosion.cs:64)"
Answers are for answers to the original question, not for answering to a comment, let alone to bump an old thread. Please use the comment function.
You have to substitute your own layer name if you don't have a layer named "Particles".
GO.layer = Layer$$anonymous$$ask.NameToLayer("YourLayerName");
This script increases the scale of your objects, a small, yet noticeable amount. Looks like you would have to offset that and reduce the scale before you broke it apart.
Your answer
![](https://koobas.hobune.stream/wayback/20220611231144im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Simple Fracture ( Destruction ) 1 Answer
2D vs 3D mesh deformation. 0 Answers
Destroy Child Object(s) OnValidate? 6 Answers
Nvidia Techonology in Unity 3 Answers
How to split 3D array in to two - Breaking voxelized objects. 0 Answers