Search Unity

Physics of Glass

Discussion in 'Scripting' started by Kreeach, Jul 28, 2006.

  1. Kreeach

    Kreeach

    Joined:
    Jul 28, 2006
    Posts:
    6
    I posted earlier about glass, but I need the object to shatter like glass, not just look like it.
     
  2. Morgan

    Morgan

    Joined:
    May 21, 2006
    Posts:
    1,223
    I've made ice shatter when struck, using particles. It's not a photo-realistic illusion, but it's fun. I plan to use it for glass shattering also, but it's kind of a "safety glass" effect, not big flat shards.

    If you want glass to shatter into flat shards, and do so in a way that responds to how it was hit, then I think you'd have to use the mesh-programming interface and invent a method :)
     
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    One possible solution would be to make two objects, the unshattered version (a single mesh) and the shattered version (a bunch of separate meshes). If you make the separate pieces all in one file, they will be automatically parented to an empty object when imported. Then, when the glass is hit by an object, destroy the unshattered version and instantiate the empty (which has the pieces attached as children) in its place. The physics system should take care of the rest.

    Maybe you could also fake it by destroying the unshattered version and instantiating a particle system in its place, with the particles looking like pieces of glass, but I haven't played with the particle system enough to know whether you could make that look convincing. (I could in Blender, dunno about Unity yet.)

    --Eric
     
  4. drJones

    drJones

    Joined:
    Oct 19, 2005
    Posts:
    1,351
    i'm in need of breakable glass as well and that's essentially the method i'll be trying (doing something else ATM). i've done other instantiate scripts with replacement objects it works well but have not played with the particle system yet - i think that'll be the key to making it look good.
     
  5. Morgan

    Morgan

    Joined:
    May 21, 2006
    Posts:
    1,223
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    OK, so even though my game doesn't have any breaking stuff (so far!), I was thinking about it, so I decided to take a break (er, so to speak) and see how much I could push Unity. I whipped up a little doodad where you have a vase that rolls off a platform and goes smash, as you can see here...

    [edit: pics were changed ages ago]

    ...Or, perhaps, lots of vases. Hmm, why am I reminded of the phrase "bull in a china shop" here? ;) No slowdown there either, though you will get some eventually if you keep it up.

    So it more or less works. What I kind of liked best was when the pieces were mesh colliders, but then they don't collide with each other (which actually wasn't that big a deal), but more importantly there's a brief lag when they're instantiated, which ruins the effect. So I ended up using box colliders, which wasn't that bad, though I had to reduce the size of the colliders so they didn't interfere too much with each other, or else the pieces go SPROING! everywhere when instantiated. Perhaps reducing the complexity of the meshes would get rid of the lag, but even the intact vase lags a bit when instantiated (that's got a mesh collider). Of course you don't normally want mesh colliders on objects like that, but it's so cool how they roll around realistically. Love that physics engine!

    I'm attaching the project if anyone feels like poking around with it for some reason. (Click play and then click to make a vase appear. Click lots of times for fun.) It definitely needs work, but I was just playing around. For one thing, the pieces ought to inherit the angular velocity of the intact vase, but I didn't look into how to do that. Also sometimes the vase generates two collisions at once, and then you get that SPROING! effect as several objects attempt to occupy the same space at the same time. ;)

    Making pieces out of a whole is trivial with Blender; I just used boolean operations between the vase and a cube several times, and it even keeps UV coordinates correct on the pieces (as long as you give the object you're cutting with some sort of UV mapping as well, doesn't matter what). You just have to watch out because boolean operations are still kinda buggy and sometimes generate non-manifold meshes (you can tell by testing a piece with the decimate function...it will say so if it won't work, so undo and move things around a bit and try again). Unity does not much like non-manifold meshes. Bizarre things happen. ;)

    So, yep, breaking glass can certainly be done, and using the technique on something like a window would be easier anyway. The shards in that case could be more easily handled with box colliders so they'd work better. Probably the ideal thing would be to combine that with a particle effect (for the little sparkly bits) at the same time.

    --Eric
     

    Attached Files:

  7. hsparra

    hsparra

    Joined:
    Jul 12, 2005
    Posts:
    750
    Nice example! Thank you for sharing. Would you have a problem putting it up on the Wiki, or having someone put it up on the Wiki. What is great about it is that it is focused on doing only one thing and is therefore easy to follow what is going on. There is not a bunch of extraneous, though cool, things also going on.
     
  8. Morgan

    Morgan

    Joined:
    May 21, 2006
    Posts:
    1,223
    Smashing!
     
  9. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Thanks...my only hesitation would be that it's kind of buggy, as I mentioned (the pieces should inherit angular velocity from the vase, sometimes a collision generates two sets of pieces at once). If someone wants to fix that up, I'd say go for it. If no one does, I'll get back to it eventually.

    --Eric
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    ...OK, this was kind of bugging me all day, so I fixed it just now (I'm a perfectionist sometimes :roll:). The VaseBreak.js script should go like this:

    Code (csharp):
    1.  
    2. var brokenVase : Transform;
    3. var radius = 2.0;           // The radius of the explosion that makes the vase shatter instead of just falling apart
    4. var power = 10.0;           // The power of the explosion (later on this will be multiplied by the velocity,
    5.                             // so the vase shatters more if it falls farther)
    6. var fragility = 12;         // This is for the relative velocity when the vase hits...
    7.                             // bigger numbers for fragility make the vase harder to break
    8. private var numberOfCollisions = 1; // A count for the number of objects a vase hits at once...
    9.                                     // we only want 1 or else you might get multiple shattered vases at once
    10.  
    11. // We want relative velocity info; otherwise this could be written as "function OnCollisionEnter(collision) {"
    12. // and it would be a bit faster
    13. function OnCollisionEnter(collision : Collision) {
    14.  
    15.     // If the vase isn't going fast enough to break or a collision has already been processed, then don't do anything
    16.     if (collision.relativeVelocity.magnitude < fragility || numberOfCollisions != 1) {return;}
    17.     else {
    18.         // Get rid of the vase and substitute the broken vase in its place,
    19.         // and increment numberOfCollisions to make sure we only do this stuff once
    20.         Destroy (gameObject);
    21.         var clonedVase = Instantiate(brokenVase, transform.position, transform.rotation);
    22.         numberOfCollisions ++;
    23.        
    24.         // Get the velocity from the vase and apply it to the pieces of the broken vase
    25.         // I figure the velocity would be reduced some by the impact if the vase was really shattering and not faked,
    26.         // so multiply by .6...looks more or less right anyway, leaving it at 1 doesn't really
    27.         var vaseVelocity = rigidbody.velocity;
    28.         for (var child in clonedVase) {
    29.             child.rigidbody.velocity = vaseVelocity*.6;
    30.         }
    31.        
    32.         // Do the explosion force thing on nearby objects--the vase shards--in an attempt to simulate a properly breaking vase
    33.         var explosionPos = transform.position;
    34.         var colliders : Collider[] = Physics.OverlapSphere (explosionPos, radius);
    35.                
    36.         for (var hit in colliders) {
    37.             if (!hit)
    38.                 continue;
    39.                
    40.             if (hit.rigidbody) {
    41.                 hit.rigidbody.AddExplosionForce(power*collision.relativeVelocity.magnitude, explosionPos, radius, 2.0);
    42.             }
    43.         }
    44.     }
    45. }
    46.  
    That's better. :) The only remaining problem is that one or two of the box colliders of the pieces overlap a little, so sometimes the shattering is rather more violent than it should be. That would be easily fixed by fiddling with the colliders, or you could just pretend that some of the vases are filled with nitroglycerin. ;) And someone tell me if I'm doing something stupid in that code...entirely likely....

    I'll see about putting it on the wiki. Mostly just a matter of changing the variable names to be more generic, since you could use this with various sorts of objects, not just vases....

    --Eric
     
  11. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Some small hints for improvement.

    Use GetComponentsInChildren(Rogidbody) instead of overlap sphere for applying the force. You can also use it instead of your iterating through children.

    Another thing is that you might want to use a capsule collider or a capsule collider and a box collider to represent the unbroken vase. I tried it and couldnt really see a difference in collision behaviour. And it makes the whole thing run a lot faster. I am not so sure if multiplying the force with collision.relativeVelocity.magnitude looks better, might try without that.
     
  12. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    I actually thought of that, but didn't quite get the syntax for using GetComponentsInChildren. Anyone want to give me a hint?

    If I was doing this "for real" in a game I would definitely do that. I was just playing around with the mesh colliders to see how they worked. :)

    (And can I say how flippin' awesome it is to get a reply from the lead developer, or is that too fanboyish? ;) )

    --Eric
     
  13. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    Code (csharp):
    1.  
    2. var brokenVase : Transform;
    3. var radius = 2.0;
    4. var power = 20.0;
    5.  
    6. function OnCollisionEnter(collision : Collision) {
    7.  
    8.     // If the vase isn't going fast enough to break, then don't do anything
    9.     if (collision.relativeVelocity.magnitude < 12) {return;}
    10.     else {
    11.         // Get rid of the vase and substitute the broken vase in its place
    12.         Destroy (gameObject);
    13.         var instance = Instantiate(brokenVase, transform.position, transform.rotation);
    14.         var bodies = instance.GetComponentsInChildren(Rigidbody);
    15.         // Do the explosion force thing on nearby objects--the vase shards--in a somewhat lame attempt to simulate a properly breaking vase
    16.         var explosionPos = transform.position;
    17.        
    18.         for (var hit in bodies) {
    19.                 hit.AddExplosionForce(power, explosionPos, radius, 3.0);
    20.                 hit.velocity = rigidbody.velocity;
    21.                 hit.angularVelocity = rigidbody.angularVelocity;
    22.             }
    23.         }
    24.     }
    25.  
    26.  
    This is how i used GetComponentsIn children when playing with your sample.
     
  14. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Aha! I didn't know about the "instance" thing for GetComponentsInChildren...that makes sense now, thanks. :)

    --Eric
     
  15. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    instance is just arbitrary, you can call GetComponentInChildren or GetComponent on any game object, component, script.