Advertisement
Guest User

SimpleFracture (Unity3.x)

a guest
Dec 11th, 2011
2,397
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var fractureToPoint = false;
  2. var totalMaxFractures = 3;
  3. var forcePerDivision = 20.0;
  4. var minBreakingForce = 0.0;
  5. var maxFracturesPerCall = 3;
  6. var randomOffset = 0.0;
  7. var minFractureSize : Vector3 = Vector3.zero;
  8. var grain : Vector3 = Vector3.one;
  9. var useCollisionDirection = 0.0;
  10. var fractureAtCenter = false;
  11. var smartJoints = false;
  12. var destroyAllAfterTime = 0.0;
  13. var destroySmallAfterTime = 0.0;
  14. var instantiateOnBreak : GameObject;
  15. var totalMassIfStatic = 1.0;
  16. private var joints : Joint[];
  17. //-------------------------------------------------------------------
  18. function Start () {
  19.     if (rigidbody) {
  20.         temp = new Array();
  21.         for(j in FindObjectsOfType(Joint)) {
  22.             if (j.connectedBody == rigidbody) {
  23.                 temp.Add(j);
  24.                 joints  = temp.ToBuiltin(Joint);
  25.             }
  26.         }
  27.     }
  28. }
  29. //-------------------------------------------------------------------
  30. function OnCollisionEnter (collision : Collision) {
  31.     point=collision.contacts[0].point;
  32.     vec = collision.relativeVelocity*UsedMass(collision);
  33.     FractureAtPoint(point,vec);
  34. }
  35. //-------------------------------------------------------------------
  36. function FractureAtPoint (hit : Vector3, force : Vector3) {
  37.     if (force.magnitude < Mathf.Max(minBreakingForce,forcePerDivision)) {return;}
  38.     iterations =  Mathf.Min(Mathf.RoundToInt(force.magnitude/forcePerDivision),Mathf.Min(maxFracturesPerCall,totalMaxFractures));
  39.     point = transform.worldToLocalMatrix.MultiplyPoint(hit);
  40.     Fracture(point,force,iterations);
  41. }
  42. //-------------------------------------------------------------------
  43. function Fracture (point : Vector3, force : Vector3, iterations : float) {
  44.     if (instantiateOnBreak && force.magnitude >= Mathf.Max(minBreakingForce,forcePerDivision)) {
  45.         Instantiate(instantiateOnBreak,transform.position,transform.rotation);
  46.         instantiateOnBreak = null;
  47.     }
  48.     while (iterations > 0) {
  49.         // if we are smaller than our minimum fracture size in any dimension, no more divisions.
  50.         if (totalMaxFractures == 0 || Vector3.Min(gameObject.GetComponent(MeshFilter).mesh.bounds.size,minFractureSize) != minFractureSize) {
  51.             if (destroySmallAfterTime >= 1) {
  52.                 Destroy(GetComponent(MeshCollider),destroySmallAfterTime-1);
  53.                 Destroy(gameObject,destroySmallAfterTime);
  54.             }
  55.             totalMaxFractures = 0;
  56.             return;
  57.         }
  58.         totalMaxFractures -= 1;
  59.         iterations -= 1;
  60.         // define the splitting plane by the user settings.
  61.         if(fractureAtCenter){point=GetComponent(MeshFilter).mesh.bounds.center;}
  62.         vec = Vector3.Scale(grain,Random.insideUnitSphere).normalized;
  63.         sub = transform.worldToLocalMatrix.MultiplyVector(force.normalized)*useCollisionDirection*Vector3.Dot(transform.worldToLocalMatrix.MultiplyVector(force.normalized),vec);
  64.         plane = Plane(vec-sub,Vector3.Scale(Random.insideUnitSphere,GetComponent(MeshFilter).mesh.bounds.size)*randomOffset+point);
  65.         // create the clone
  66.         newObject = Instantiate(gameObject,transform.position,transform.rotation);
  67.         if (rigidbody) {newObject.rigidbody.velocity = rigidbody.velocity;}
  68.         // arrays of the verts
  69.         var vertsA =  gameObject.GetComponent(MeshFilter).mesh.vertices;
  70.         var vertsB =  newObject.GetComponent(MeshFilter).mesh.vertices;
  71.         average = Vector3.zero;
  72.         for (i in vertsA) {
  73.             average += i;
  74.         }
  75.         average /= gameObject.GetComponent(MeshFilter).mesh.vertexCount;
  76.         average -= plane.GetDistanceToPoint(average)*plane.normal;
  77.         //-------------------------------------------------------------------
  78.         broken = 0;
  79.         // split geometry along plane
  80.         if (fractureToPoint) {
  81.             for (i=0;i<gameObject.GetComponent(MeshFilter).mesh.vertexCount;i++) {
  82.                 if (plane.GetSide(vertsA[i])) {
  83.                     vertsA[i] = average;
  84.                     broken += 1;
  85.                 }
  86.                 else {
  87.                     vertsB[i] = average;
  88.                 }
  89.             }
  90.         }
  91.         else {
  92.             for (i=0;i<gameObject.GetComponent(MeshFilter).mesh.vertexCount;i++) {
  93.                 if (plane.GetSide(vertsA[i])) {
  94.                     vertsA[i] -= plane.GetDistanceToPoint(vertsA[i])*plane.normal;
  95.                     broken += 1;
  96.                 }
  97.                 else {
  98.                     vertsB[i] -= plane.GetDistanceToPoint(vertsB[i])*plane.normal;
  99.                 }
  100.             }
  101.         }
  102.         // IMPORTANT: redo if we have a problem splitting; without this, we will get a lot of non-manifold meshes, convexhull errors and maybe even crash the game.
  103.         if (broken == 0 || broken == gameObject.GetComponent(MeshFilter).mesh.vertexCount) {
  104.             totalMaxFractures += 1;
  105.             iterations += 1;
  106.             Destroy(newObject);
  107.             // this yield is here JUST so that when a large amount of objects are being broken, the screen doesn't freeze for a long time. It allows the screen to refresh before we're finnished, but if you don't, it might slow the script down trying to break a loop of bad planes.
  108.             yield;
  109.         }
  110.         // if all's fine, apply the changes to each mesh
  111.         else {
  112.             gameObject.GetComponent(MeshFilter).mesh.vertices = vertsA;
  113.             newObject.GetComponent(MeshFilter).mesh.vertices = vertsB;
  114.             gameObject.GetComponent(MeshFilter).mesh.RecalculateNormals();
  115.             newObject.GetComponent(MeshFilter).mesh.RecalculateNormals();
  116.             gameObject.GetComponent(MeshFilter).mesh.RecalculateBounds();
  117.             newObject.GetComponent(MeshFilter).mesh.RecalculateBounds();
  118.             if (gameObject.GetComponent(MeshCollider)) {
  119.                 gameObject.GetComponent(MeshCollider).sharedMesh = gameObject.GetComponent(MeshFilter).mesh;
  120.                 newObject.GetComponent(MeshCollider).sharedMesh = newObject.GetComponent(MeshFilter).mesh;
  121.             }
  122.             // if we weren't using a convexhull, the pieces colliders won't work right. It's best for everyone if we just remove them.
  123.             else {
  124.                 Destroy(collider);
  125.                 Destroy(gameObject,1);
  126.             }
  127.             // smartjoints will allow joints to function properly.
  128.             if (smartJoints) {
  129.                 jointsb = GetComponents(Joint);
  130.                 if (jointsb){
  131.                     // Basically, it goes through each joint and sees if the object A or B are closer to the connected body. Whichever is closer keeps the joint.
  132.                     for (i=0;i<jointsb.length;i++){
  133.                         if (jointsb[i].connectedBody != null && plane.GetSide(transform.worldToLocalMatrix.MultiplyPoint(jointsb[i].connectedBody.transform.position))) {
  134.                             if (jointsb[i].gameObject.GetComponent(SimpleFracture).joints) {
  135.                                 // If we're attached to a fracture object and the new object is closer, switch the connected object's joint variable at the correct index.
  136.                                 for (c in jointsb[i].gameObject.GetComponent(SimpleFracture).joints) {
  137.                                     if (c == jointsb[i]) {c = newObject.GetComponents(Joint)[i];}
  138.                                 }
  139.                             }
  140.                             Destroy(jointsb[i]);
  141.                         }
  142.                         else {
  143.                             Destroy(newObject.GetComponents(Joint)[i]);
  144.                         }
  145.                     }
  146.                 }
  147.                 // joints contains all joints this object is attached to. It checks if the joint still exists, and if the new object is closer. If so, changes the connection. It then removes the joint from the joints variable at the correct index.
  148.                 if (joints){
  149.                     for (i=0;i<joints.length;i++){
  150.                         if (joints[i] && plane.GetSide(transform.worldToLocalMatrix.MultiplyPoint(joints[i].transform.position))) {
  151.                             joints[i].connectedBody = newObject.rigidbody;
  152.                             temp = new Array(joints);
  153.                             temp.RemoveAt(i);
  154.                             joints = temp.ToBuiltin(Joint);
  155.                         }
  156.                         else {
  157.                             temp = new Array(joints);
  158.                             temp.RemoveAt(i);
  159.                             newObject.GetComponent("SimpleFracture").joints = temp.ToBuiltin(Joint);
  160.                         }
  161.                     }
  162.                 }
  163.             }
  164.             // if we don't have smartJoints, the code is much shorter. destroy all joints.
  165.             else {
  166.                 if (GetComponent(Joint)) {
  167.                     for (i=0;i<GetComponents(Joint).length;i++){
  168.                         Destroy(GetComponents(Joint)[i]);
  169.                         Destroy(newObject.GetComponents(Joint)[i]);
  170.                     }
  171.                 }
  172.                 if (joints) {
  173.                     for (i=0;i<joints.length;i++){
  174.                         Destroy(joints[i]);
  175.                     }
  176.                     joints = null;
  177.                 }
  178.             }
  179.             // if the script is attached to a static object, make it dynamic. If not, divide the mass up.
  180.             if (!rigidbody) {
  181.                 gameObject.AddComponent(Rigidbody);
  182.                 newObject.AddComponent(Rigidbody);
  183.                 rigidbody.mass = totalMassIfStatic;
  184.                 newObject.rigidbody.mass = totalMassIfStatic;
  185.             }
  186.             gameObject.rigidbody.mass *= 0.5;
  187.             newObject.rigidbody.mass *= 0.5;
  188.             gameObject.rigidbody.centerOfMass = transform.worldToLocalMatrix.MultiplyPoint3x4(gameObject.collider.bounds.center);
  189.             newObject.rigidbody.centerOfMass = transform.worldToLocalMatrix.MultiplyPoint3x4(newObject.collider.bounds.center);
  190.            
  191.             newObject.GetComponent("SimpleFracture").Fracture(point,force,iterations);
  192.            
  193.             if (destroyAllAfterTime >= 1) {
  194.                 Destroy(newObject.GetComponent(MeshCollider),destroyAllAfterTime-1);
  195.                 Destroy(GetComponent(MeshCollider),destroyAllAfterTime-1);
  196.                 Destroy(newObject,destroyAllAfterTime);
  197.                 Destroy(gameObject,destroyAllAfterTime);
  198.             }
  199.             // this yield is here JUST so that when a large amount of objects are being broken, the screen doesn't freeze for a while.
  200.             yield;
  201.         }// if not broken end
  202.     }// while itterations end
  203.     if (totalMaxFractures == 0 || Vector3.Min(gameObject.GetComponent(MeshFilter).mesh.bounds.size,minFractureSize) != minFractureSize) {
  204.         if (destroySmallAfterTime >= 1) {
  205.             Destroy(GetComponent(MeshCollider),destroySmallAfterTime-1);
  206.             Destroy(gameObject,destroySmallAfterTime);
  207.         }
  208.         totalMaxFractures = 0;
  209.     }
  210. }
  211. //--------------------------------------------------------------
  212. function UsedMass (collision : Collision) {
  213.     if (collision.rigidbody) {
  214.         if (rigidbody) {
  215.             if (collision.rigidbody.mass < rigidbody.mass) {
  216.                 return (collision.rigidbody.mass);
  217.             }
  218.             else {
  219.                 return (rigidbody.mass);
  220.             }
  221.         }
  222.         else {
  223.             return (collision.rigidbody.mass);
  224.         }
  225.     }
  226.     else if (rigidbody) {
  227.         return (rigidbody.mass);
  228.     }
  229.     else {return (1);}
  230. }
  231.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement