Latest  | Search | Go
Edit this page   |   Attach file 

  Home | Tutorials | Technical Reference | Runtime | API Documentation | BreakableObjects  

Creating Breakable Objects

Tutorial Author:Jeremiah Fulbright
Updated August 5 2005

Note:        For this tutorial, you should have already have an understanding of how to import Models into RE thru the Builder, as well as the creation of Prefabs. This tutorial only covers the creation of Breakable Objects “after” art has already been created and imported.

We will be working with BreakablePot? which is part of the EvalKit Module, but we will be making our own version of the BreakablePot? script, mostly for pointing out sections – Feel free to just follow along.

Folder Structure

The first thing you will notice is the directory structure that is used. This is not a required structure but is possibly the best, but its personal preference.

FolderStructure.jpg

The structure is as follows:

* PotParticles? contains the XML/Scene setup for the effect to show when the Pot is broken. In this case, its just a dust puff – but it can be NetMultiShapeActors? for usage of actual pieces with Physics.

* WholePot? contains the Prefab for the Whole pot, which has had its Pivot Centered and then the Prefab centered to 0,0,0 – This will become your Breakable object in the End (using Convert To)

* PotPiece?# folders each contain the Prefab for each individual piece of the Pot that is broken when damaged, shot, triggered, etc. The pieces are also Pivot centered and 0,0,0 centered

Basic Script Setup

As I mentioned above, we will be naming this BreakablePitcher?, so you need to create a BreakablePitcher?.cs in your EvalKit Scripts folder (or wherever you need it). You can do this via Visual Studio or just copy/paste the BreakablePot?.cs and rename it and then do some editing.

Here is the basic Script:

         /// -----------------------------------------------
         /// PRECACHING & STATIC DATA VALUES
         /// -----------------------------------------------
         /// 
         public static string ClassName = "BreakablePot";
         private static bool HasCached = false;

This is the Precache portion of the Script which is very basic, as you can tell.

   /// <summary>
   /// MEDIA
   /// </summary>
   static private MSound StaticBreakSound = MPrecacher.PrecacheSound(ClassName, "BreakPot.wav", false);
   static private int[] MyParticleSystems = 
      {
         MPrecacher.PrecacheActorPointer(ClassName, "PotParticles.xml"),
      };
   static private int[] PotPieces =
    { 
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece1.xml"),
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece2.xml"), 
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece3.xml"),
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece4.xml"), 
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece5.xml"), 
      MPrecacher.PrecacheActorPointer(ClassName, "PotPiece6.xml")
   };
   static private MVector[] PotPiecesOffsets =
    { 
      new MVector(-0.06079591f,0.180491f,-0.138583f),
      new MVector(-0.05181848f,0.2195758f,0.1360596f),
      new MVector(0.1639841f,0.05911997f,0.08252703f),
      new MVector(0.01162986f,-0.2269091f,-0.01701386f),
      new MVector(-0.2153126f,-0.1845589f,0.07264592f),
      new MVector(0.1189805f,-0.3204344f,-0.1920157f)
   };

This is the Media Section of the Script and this is the where you will define the Particle Effect, the Broken Pieces, and their locations to spawn on Object.

   public BreakablePot(MWorld world)
      : base(world)
   {
      Precache();

      Pieces = PotPieces;
      PiecesOffsets = PotPiecesOffsets;
      BreakSound = StaticBreakSound;
      ParticleSystems = MyParticleSystems;
   }

This is the constructor for the Scripted Breakable object, which does nothing more than set references for the BreakableObject? script. You will need to change the names to match those supplied in Media section

   public static void Precache()
   {
      MPrecacher.Precache(ClassName, HasCached);
      if (!HasCached)
      {
         for (int i = 0; i < PotPieces.Length; i++)
         {
            MActor theActor = MActor.GetFromPointer(PotPieces[i]);
            if (theActor == null || !(theActor is NetMultiShapeActor))
               continue;

            NetMultiShapeActor potPiece = (NetMultiShapeActor)theActor;
            potPiece.SpawnByName = false;
         }
         HasCached = true;
      }
   }

This is the Precache function which is handled like all other Precache functions in that it is used just to make sure the Broken Pieces are cached and ready to go when the time comes.

Note:        The actual functionality for taking damage, breaking, disposing, etc are handled in BreakableObject?.cs.

Script XML References

PitcherPieces.jpg

You will notice it is named PitcherPieces? but this actually can be any name, as you see fit. Since we are using the BreakablePot? prefab for this, you can leave the listed XML files, as is, or change to what your object is setup for (PitcherPieceA?, PitcherPiece1?, etc)

PitcherParticle.jpg

This is where you would need to reference your sound for whatever it is, that you are breaking, as well as the ParticleSystem? reference if you have effects to go with the Breaking. The naming of both of these sections can also be changed, but for sake of ease, they have been left alone.

PitcherOffset.jpg

This will be the 2nd part of the magic that makes this work, which is the Offset references for each piece that breaks off. They are used in the same order as the XML files that you typed in or see listed. This section is named similar to it matching Pieces section, but also can be changed.

Note:        Anytime you use a different name or change names around, you need to make sure to edit the Constructor and the Precache function which both reference the Media variables that you have specified.

Names.jpg

Now the part that will take the most time out of all of it – We need to figure out where each piece needs to spawn when the Object is broken to give it the proper look. This will all be done thru Reality Builder and isn’t too complex once you see what needs to be done.

Note:        There are numerous ways of doing this and feel free to work it however you want, but this is the way I like to do mine.

Reality Builder Mechanics

You should already have each piece imported as a Prefab and saved into its own Folder, so that you can load each piece individually into Reality Builder. Let us go open PotPiece1? which is under EvalKit\Models\BreakablePot\PotPiece1

potpieceeditor.jpg

Now, you will notice that the Prefab has already been converted to a NetMultiShapeActor? and has the Shapes setup on it for Physics. You should do this to your Piece prefabs, if you haven’t already. Your Prefab needs to be Pivot Centered (Modifiers > Center Pivot), and once that is accomplished – You need to move the Prefab to 0,0,0 (XYZ). You can do this by clicking the Prefab and then just typing 0s in the X, Y, Z edit boxes.

This is where it may get confusing for some of you, as you need to determine the proper offset for the current piece you are working on. This is best accomplished by doing File – Merge and finding the Whole object (in this case WholePot?.xml). This will bring in the Unbroken version of the object, in the exact way it is in the XML (The Unbroken object should be Pivot Centered and moved to 0,0,0 also.

Once you have accomplished this, you need to select your Broken Piece and begin moving it around till you get the proper location for it to “break” off of the whole object.

piece-seperated.jpg

piece-inplace.jpg

Once you have the piece in the position you want, you need to make a note of the X, Y, Z for it. This is in relation to 0,0,0 which is what all of your prefabs should be based around position wise. The X, Y, Z value will go into your Script in the Offset section

   static private MVector[] PotPiecesOffsets =
        { 
      new MVector(-0.06079591f,0.180491f,-0.138583f)
   };

Once you have the information noted in your Script, you need to delete the Whole object from your Scene and re-Center the Broken piece, by replacing the X, Y, Z values with 0. You can save right after this and then move on to the next piece.

You need to do this for each piece of your BreakableObject?, in the same exact manner.

The end result should be what is in BreakablePot?.cs (BreakablePitcher?.cs)

   static private MVector[] PotPiecesOffsets =
        { 
      new MVector(-0.06079591f,0.180491f,-0.138583f),
      new MVector(-0.05181848f,0.2195758f,0.1360596f),
      new MVector(0.1639841f,0.05911997f,0.08252703f),
      new MVector(0.01162986f,-0.2269091f,-0.01701386f),
      new MVector(-0.2153126f,-0.1845589f,0.07264592f),
      new MVector(0.1189805f,-0.3204344f,-0.1920157f)
   };

After you have all of your pieces done and the script updated, it is time to convert your Unbroken Object into the Breakable version. After you have saved your script, you need to reload the Scripts in Reality Builder – which can be done via Game > Reload Scripts.

It will take a moment or two, depending on speed of system and other scripts, but once it has finished. You need to select your Unbroken object and then you can either Shift-Right Click and goto Convert to Actor > and pick the BreakablePitcher? script (or whatever name yours is), or pick it from the Dropdown box and then click Change.

The change is instant, but before it is useable, you will need to do one other thing and that is setup the Physics shapes on the Unbroken version of the Object, so the engine will properly handle collision and taking of damage.

converted.jpg

You can save out your Whole object and you are basically finished with the setup needed to make your object breakable. You just need to place it in a Map to test the results. You will need to place the Whole version of your Object via the Prefab Browser for it to be properly imported complete with Physics Shapes.

Note:        BreakableObjects have a BreakThreshold?, as well as AttachedLight? settings which can be used to attach a Light to a Breakable Object (Hanging Lamp)

This concludes this part of the tutorial, but feel free to post in the Forums with questions or changes. There will be some revisions made, as needed, to account for various cases, and also maybe add some suggestions or implementation tips from our Developers.

-- JeremiahFulbright - 05 Aug 2005

Attachment sort Action Size Date Who Comment
FolderStructure.jpg manage 114.1 K 05 Aug 2005 - 07:26 Main.guest  
Names.jpg manage 120.3 K 05 Aug 2005 - 07:27 Main.guest  
piece-inplace.jpg manage 94.7 K 05 Aug 2005 - 07:27 Main.guest  
piece-seperated.jpg manage 98.6 K 05 Aug 2005 - 07:27 Main.guest  
PitcherOffset.jpg manage 61.1 K 05 Aug 2005 - 07:27 Main.guest  
PitcherParticle.jpg manage 57.3 K 05 Aug 2005 - 07:28 Main.guest  
PitcherPieces.jpg manage 59.8 K 05 Aug 2005 - 07:28 Main.guest  
potpiece1editor.jpg manage 159.6 K 05 Aug 2005 - 07:30 Main.guest  
potpieceeditor.jpg manage 159.6 K 05 Aug 2005 - 07:31 Main.guest  

BreakableObjects   Edit | Attach | Ref-By | Printable | Diffs | r1.2 | > | r1.1 | More