This tutorial applies to UT2003/2004.
The Concept
To make a window that breaks in your map, you need two things. A movable brush that represents the window in its whole state, and an Emitter to spawn in for the shattering glass fragments that spill out when the window gets "Broken".
You will need to understand the basic use of Movers, Triggers and ScriptedTriggers
The Mover
If you don't already have a nice glass material set up, make one now. I suggest reading about Shaders, using Opacity in your shader, and maybe Specularity if you want it to look really nice.
In 2003/2004 movers may only be made with static meshes, so we will use BSP to create our window to start with. Apply your window texture to a thin additive brush that fits as your window. Right click on the additive brush after you create it, and choose Convert -> To Static Mesh. Enter myLevel as your package, and give it whatever name you wish. Now if you look in the static mesh browser, you should see your window mesh.
Back in the edit, click on the Add Mover button to add your window mesh as a movable brush. Move it into place, and set this as the base with Mover -> Key 0. Now right click the mover and choose Mover -> Key 1, then move the window somewhere out of view, preferably completely outside the level, right click it again and choose Mover -> Key 0 (Base). The window should snap back into its base position.
We need to set up some properties in our mover to make it dissapear from view when shot. So open the properties window for the mover.
We will change:
- Object -> InitialState to TriggerOpenTimed
- Mover -> MoveTime to 0
- Mover -> StayOpenTime to however long you want your window to stay broken before respawning. This value is in seconds.
- Mover -> bDamageTriggered to True
- Mover -> DamageThreshold to 1
- Display -> bShadowCast to False or else the window will cast a shadow, and look bad when it breaks.
Now hopefully we have a pane of glass that when shot, moves (In 0 seconds) off the map, giving the illusion that it has been destroyed.
But now we need shattering fragments of glass to complete the illusion.
The Special Effects
This section is a compilation of several different resources on creating breaking glass. Many of them had 90% of the information necessary but none had 100%. So everyone who made a breaking glass tut, your stuff is used in here, thanks, you rock.
The falling shards of glass require you to set up an emitter to produce the shards, and a second custom actor class to spawn them. First: the emitter:
Select "Emitter" from the actor classes (or Network Emitter" to make it playable online), and place it in your level. There are certain things that must be set up correctly for the breaking glass to spawn the way you want it to:
- Advanced -> bDirectional = True. This is necessary to align the shards with the window.
- Advanced -> bNoDelete = FALSE. This is required for the emitter to be spawned when called by the "spawner" actor.
- Emitter ->
- Acceleration -> Acceleration - Z = -950. This simulates normal gravity in allowing the shards to fall.
- Collision -> DampingFactorRange - X Max/Min = .9 / .8 Y Max/Min = .5 Z Max/Min = .3 / .2 (It's important to note that in 2004 range properties windows, Max is first, then Min., even though they are displayed as min/max at the top of the listing.)
- Collision -> UseCollision = True. Else your shards will fall through the floor and keep going. o_O
- General -> MaxParticles = ~2000. This is variable depending on the size of your window and of yuur shards. Once you get more than 5000 or so particles at once, it starts to drag down your average PC, so if your level has 7 breakable windows, don't give them 4000 particles each. If necessary, spawn a fewer number of larger shards to save CPU cycles.
- Local -> RespawnDeadParticles = False. You want a broken window, not a glass fountain.
- Location -> StartLocationRange -> Y Max/Min = +/- half the width of your window. Example, if your window is 512UU wide, Y range is 256 / -256. Same for Z range, Max/Min = +/- half the height of your window.
- Rotation -> UseRotationFrom = PTRS_Actor. This is critical if you wish to have more than one breaking glass in your level, from different angles.
- Spawning -> AutomaticInitialSpawning = False. It is going to be triggered.
- Spawning -> InitialParticlesPerSecond = 50000. This releases all particles in a fraction of a second.
- Spawning -> ParticlesPerSecond = 0. Again, not a fountain.
- Texture -> DrawStyle = PTDS_Transluscent
- Texture -> Texture - Select the shard texture from your texture browser window, then return here and click "Use" to insert it into your texture line.
- Texture -> TextureUSubdivisions & TextureVSubdivisions-> Divide your texture up by shards. For example, if your texture is two shards wide by two shards high, your U and V subdivions are 2 each.
- Time -> LifetimeRange = Set this to whatever. If your window respawns, set it to no more than the "Open Time" of your window mover. Else, set it to whatever you wish, 100000 to stay forever, but remember that particles eat up resources as long as they remain in your level.
- Velocity -> StartVelocityRange - X Max/Min = 200 / -200. Y Max/Min = 100 / -100
At this point, the effect of the emitter should be visible in any 3d views you have open. You can use this to tweak the settings of your emitter to get the look you want.
Once you've created your emitter, align it with your window, and use rotation to point the directional arrow in the desired direction, I recommend an angle somewhat downward and away from the window, to make sure your axis rotation is set up properly.
Now, its time to set it up to be spawned when someone shoots your window. Leave your emitter properties window open for now.
An UnrealScript window will pop open. You can click "Compile Changed" now if you wish, or later when we create the spawner. Either way, close this window.
Now expand the Emitters section and right-click on BreakingGlassEmitter. If it is not visible in your window, simply uncheck the "Placeable Only" box and it will appear. Click on Default Properties, and a properties window will appear similar to the one for your emitter. Open up the Emitters section of your BreakingGlassEmitter, and click the Add button. Now go to the Emitters section of the properties window of your emitter, and copy the full name from the Emitters -> 0 field, "SpriteEmitter'myLevel.SpriteEmitter0" or something similar. Paste it into the corresponding field in your BreakingGlassEmitter and hit Enter. All the properties of your emitter will be copied into this actor subclass.
Now change a few settings:
- Advanced -> bDirectional = True
- Advanced -> bNoDelete = FALSE
Now close all these properties windows and delete your template emitter, it is no longer needed.
Go back to your Actors browser window, right click on Emitter, and click New to create your second custom subclass. Package is still myLevel, Group is completely up to you, Name is whatever, we will use BreakingGlassSpawner for reference.
When the UnrealScript window pops up, type or copy / paste this into the script:
class BreakingGlassSpawner extends Actor placeable; event Trigger(Actor Other, Pawn EventInstigator) {Spawn(class'myLevel.BreakingGlassEmitter',,,Self.Location,Self.Rotation);}
Now compile changed scripts and close your window. In the Actor browser, you should be able to see both your custom subclasses, BreakingGlassEmitter and BreakingGlassSpawner. Right-click on BreakingGlassSpawner, click Default Properties, and check the following settings:
- Advanced -> bDirectional = True
- Advanced -> bNoDelete = True (this is where you must do this)
Now Add your BreakingGlassSpawner actor to the level, and align it with the window where you had placed the emitter previously. Set the Event -> Event of your window mover to something like Window1 or BreakGlass or whatever, then set the Event -> Tag of your BreakingGlassSpawner to match. Save, rebuild, save, give it a go!
(Note: some of the steps taken here are very likely redundant, for example, setting the directional to True for the Emitter AND BOTH actor subclasses, if someone can verify that this will still function with certain steps excluded, feel free to remove them.)
Now the UDN page gives a very vague explanation of creating an actor to spawn this emitter. I followed more of Robo's excellent instructions and instead used a ScriptedTrigger to accomplish this.
The UDN says to make a spawner class but I used a ScriptedTrigger for spawning my emitters. The advantages of using a ScriptedTrigger are that you can spawn your emitter class at the location of ANY ScriptedTrigger without having to have location and rotation data for the emitter class. You can also add a breaking glass sound effect to play within the ScriptedTrigger.
- Add your glass window mover to your map. For its key1, move it away out of the map so it will be hidden when it's shot.
- Expand the "MoverEvents" section and set the following values..
OpeningEvent = breakglass1
- Expand the "Object" section and set its InitialState to "TriggerOpenTimed".
- Add a ScriptedTrigger to your map and move it to be in the same position as your mover. Also rotate it so it's facing the right way for when your glass breaks.
- Open the ScriptedTriggers properties, expand its Events section, and set its tag to "breakglass1".
- Now for the meat. Expand its AIScript" section...
- Add a new event of Action_WAITFOREVENT type, and in its ExternalEvent = breakglass1
- Add a new event of Action_SpawnActor and select your emitter class as the actor to spawn.
- Add a new event of type Action_PLAYSOUND. Set its sound to be a breaking glass sound. We are using this method because it gives you better control over the sound than the mover does.
- Add a new event of type Action_GOTOACTION. Leave its setting at 0
Ok that should do it. Rebuild your map and test it out. When you shoot the mover it should immediatly move out of view, the breaking glass emitter will be spawned, showering broken glass from where the ScriptedTrigger is, and play a breaking glass noise.
This method should work well and it has the added bonus that you can add more breaking glass movers and ScriptedTriggers to have a whole glasshouse of breakable glass windows. Even better they respawn after the time you set in your movers "StayOpenTime' value.
Hopefully that helps you out
It certainly helped me out, and as any good mapper should, im adding what ive learned to the wiki :)
LionsPhil: This is neat, but if a player is standing on the glass (e.g. because you want other players to be able to shoot that player's footing away >=)= ), it will fling them in the direction of the mover's 'broken' position. Is there really no generic "breakable" smesh-based actor (think Half-Life 1's brush-based func_breakable, or DestroyableObjective SM without the objective ties) in UT?
Foxpaw: I believe destroyable Decorations behave in this manner. If not you could easily code such an actor.
Bonehed316: I've got some code for breakable objects which...I could distribute. It doesnt use the old mover hack, but actually a StaticMeshActor which is destroyed (or possibly hidden/collisions disabled). Maybe I'll clean it up for distribution. I used to host a breakable glass script which worked with the mover method, but that has long since been lost.
Messiah: It says in the script extends Actor, but this should be Emitter. Atleast this script doesn't work this way.
VitalOverdose: I cant see anything about replication does this work online?
Guru: I have a major problem!!! The tutorial says click on the breaking glass actor under effects, but i don't have "breaking glass" or "exploding wall" under effects. How do i get a breaking glass actor?