|
Common Interactives - Prox/Button/Shot Doors
|
I have set up a simple test map consisting of a slab of BSP, a
skylight, a playerstart, a skydome, and a directional light.
I will only be using default editor assets which can be found
in the EditorMeshes and EditorMaterials
packages.
I will be using Movers/Interpactors (the terms are interchangeable)
that are sometimes animated through Matinee. If you need to
learn Matinee, I would recommend Hourences'
Tutorial on them as a starting point.
I added the default mesh cube as a static mesh to the map, converted
it to an interpactor, and then made it very thin. The pivot
is in the center so I will only animate it up and down, or side
to side. A door turning on its hinge requires both a pivot on
one side of it, and some forethought to where the player will
be so as not to squeeze them against a wall.
*Note: Pivots/Origin points on StaticMeshes serve as the 'hinge
points' for interpactors. If you need to create a door, or other
moveable object that revolves, rotates, or swings on an edge,
you'll need to be aware of the mesh's pivot/origin location.
It is impossible to re-assign this pivot permanantly in the
engine. For mesh placement, you can currently temporarily assign
the pivot to a new location, but when you're done, the pivot
will be back at the origin. If you find a mesh that you want
to use as a swinging door, and its pivot is in the center, you
are out of luck. The origin is determined when the mesh is created
in a 3D Modeling application - not in the Unreal Editor.
Proximity/Button/Shot Doors: This kind of door
is turned off by default. It's turned on by using a button,
and then will open either when shot, or when the player is within
a certain radius.
Let's use the 'Cooking' analogy I outlined in the Applications
introduction to set this up:
1) What are we making?
A Door that's initially off. When on,
it will open when the player is in a certain radius, or if the
door is shot.
2) Gather the ingredients:
2 Triggers (Buttons)
1 Trigger (Proximity)
Mover (Door)
2 Movers (buttons)
Matinee
2 Used Events (Buttons)
Trigger Touch Event
(Proximity)
3) Put it together. In the level, I've created two walls and
placed a thin mover between them. I also added a smaller interpactor
for the buttons off to the right, on both sides of the door,
and triggers over them with small radii. I overrode the interpactors'
material with a brighter one. I added a trigger with a large
radius to the center of the door.
|
|
On the kismet side of things, I used the 2 triggers to create
2 Trigger 'Used' events,
and a matinee. I set the MaxTriggerCount on these to 1, and
turned off their aimtointeract. Next, I created a trigger 'Touch'
event based on the trigger in the door. I increased its lateral
radius and set its MaxTriggerCount to 0. Now, it seems like
I need something to hold the touch event at bay until the used
event goes off. So I'll add a gate that's turned off by default.
Finally, I'll add the matinee, keyframe it up, and set it to
'rewindonplay'. As an additional stpe I set the Used events
to set off the matinee since I was in the radius already. I
also added a delay hooked to the reverse of the matinee to close
the door after 2 seconds.
|
|
4) Test it. Go in game and test it out. It worked fine for me.
3) Put it together. We're going to go back to 3 for now, as
we still need to add the damage. If you're setting up a complicated
system like this, it's a good idea to test the various components
as you integrate them. So I select the door, and create a 'TakeDamage'
event from it. I changed the damage threshold to 10, MaxTriggerCount
to 0, and MinDamageAmount to 5. Now, I'll add it into the system
parrallel to the Touch event and think about what will happen.
Well, I see many problems...If I shoot the door while it's opening
the first time, the damage event will fire and re-open the door
in the middle of it opening. Plus, I'm turning on the system
with two switches, but am trying to shut them down after either
one fires. This means that I could get an extra signal going
through that I don't want. So I'll add a gate that autocloses
after 1 signal goes through for each. Also, I added an extra
delay the length of the matinee and then I use that to re-open
the gate that controls the in from the touch or damage event.
|
|
5) Refine it. First, think about the collison and lighting and
get those fixed. Then consider any potential issues. Can the
player 'break' the system as it is? Can the player outrun the
door? Once you've settled the issues, feel free to iterate on
the system.
For example, I'd like the door to stay open if the the player
is in the touch radius and close after the player leaves the
radius. Now, this is going to get pretty complicated.
To begin, we are activating the entire setup with the Used events,
so the gate that controls the 'activation' stays - it's open
by default and closes after the first signal goes through. Now,
we have two ways to open the door - the trigger touch, and the
door take damage. We're going to need to juggle these so they
don't interfere with each other. We also have two ways to turn
off the system. A trigger Untouch, and a delay after shooting
the door open. If we shoot the door open, I want it to close
after 1 second of being open so the matinee duration plus 1
second. Now, we need gates to allow the Used events to activate
the system. So I add three - one for the Take Damage, and two
for the trigger touch - one for the touch, and one for the untouch.
They're closed by default, and opened by the Used events. Since
we need to keep the take damage and touch/untouch events somewhat
seperate, I've added some booleans to keep track of if the door
is considered 'open' or 'closed'. They are set whenever the
door receives a signal to either open or close. Now, the radial
trigger I want to remain the primary event for the door's open/closed
state, so I've basically hooked it directly into the matinee.
If the player leaves the radius while the door is still opening,
I want it to rest open for 1 second - just like the damage -
so I add a 1 sec delay in front of the close command coming
from the untouch. Now, to add in the take damage event, I want
it to detect if the door is open or closed so I add a compare
boolean action. If the door is open already, I don't want it
to do anything so I leave that output empty. If the door is
closed I want it to open, so I add that connection to the matinee
and set variable for open. I then add the delay that's the matinee
time plus 1 second so it remains open for 1 second, and then
fires out and closes the door again. Now, when dealing with
delays, you always need to consider what will happen if the
player tries to set something else off while the system is waiting
under a delay. To prevent breaking the system, I have signals
telling the delays to stop if the player initiates a new command.
If the player re-enters the radius while the shot delay is playing,
I shut off the shot delay, and allow the trigger touch to go
off. The last thing I set was the Matinee to world frame, and
unchecked rewindonplay. The system is in the screenshot below.
|
|
Let's take this sequence even further. I want my door to make
sounds when it opens and closes and I want to control their
timing so I'm going to add PlaySound
actions to the system. One for when the matinee receives a play,
or open, command, and a seperate one for when the matinee receives
a revers, or close, command. I will target the door so the sound
seems to originate from the door.
|
|
I also want to add a visual cue to the buttons we originally
press to activate the system. Since we're turning the system
on, but never allowing the buttons to be active again, perhaps
we're setting up a situation where the buttons break after their
first use. So let's do a few things here... I'll create a new
matinee to control the two buttons. I'll create two groups within
it, each to control one button, and keyframe them so that when
the signal comes in, they'll each move slightly into the wall,
as if they were pressed. Let's also swap the button's material
to a 'deactivated' one after it's pressed. I'll also add an
emitter that sparks out to give the hint that it's broken. We
should probably also add a sound to match the sparks. Finally,
let's add a light around our 'glowing' button that goes out
when it breaks. We'll initiate all this off the Used events
that activate the system. A few issues to keep in mind when
setting this up. First, you'll want to uncheck 'AutoActivate'
on the emitters, otherwise they'll activate when the level starts.
Also, if they don't 'die' by themselves, you will need to add
a delay that loops back into the 'Turn Off' on the toggle that
activates them to get them to stop. Also, the lights I added
were 'PointLightToggleable', as regular pointlights won't accept
toggle commands. Last, I commented the sounds so I could easily
tell what they are, which emitters are referenced, the movers,
and the gates.
|
|
At this point, the system is pretty much where I want it to
be. We have a door activated by a button. It activates the door
opening by damage, or by a radial touch, it shuts down the buttons,
releases spark emitters and a sound for the sparks as well as
turns off lights around the buttons. The door will re-open if
a player gets within the radius, will close when the player
leaves the radius, and will open if the door is shut, and will
close after 1 sec if the player is out of the radius, but will
stay open if the player is in the radius.
6) Adjust it for Single/Multiplayer. As you may have read in
the SinglePlayer/Co-op/MultiPlayer
section, there are many considerations to take into account
for whichever system you're setting this up for. The system
as it stands Needs some examination for each gametype before
we call it done.
SinglePlayer: What can the player directly effect in
Kismet? The Used events, the Touch/Untouch Event, and the Damage
event. By default 'BPlayerOnly' is checked for all of them.
Is this ok? Does the AI need to be able to activate the door
with the Used buttons? Should the radial Touch/Untouch react
to AI/NPCs as well? How about the Damage event? Should it fire
only from damage dealt by the player or from the AI/NPCs as
well? Set the checkboxes appropriately depending on your needs.
If the AI should activate the Used event, you'll need to script
that too.
MultiPlayer: What happens when one player enters the
system? What happens when one player leaves? What happens when
two players are in the system? What happens when one leaves
but one stays? What happens when both leave? These are all good
questions to ask. I can problems with more than one player at
the moment. If one stays and one leaves, the leaving one will
trigger the untouch event and close the door while the other
is still in the 'stay open' radius. We'll need to add a system
to tell the untouch when there are players, and when there are
0 players. I've added the counter system from the SinglePlayer/Co-op/MultiPlayer
section to the Touch/Untouch system and that should take care
of things.
I know the full system below looks pretty scary, but I've collapsed
everything in together pretty tightly to make sure it'll fit
on the website. You can stretch out the connections and loosen
things up yourself which makes it more manageable. Hopefully
one of the lessons learned through this tutorial is that Kismet
can become complicated, but it consists of simple parts that
piece together to form a whole.
|
|
Remember how I indicated in the Introduction that there is no
'right' or 'wrong' way to implement Kismet? The screenshot below
is the exact same system and contains the exact same functionality,
but instead of controlling everything through gates, I've used
toggles to turn on/off events. As long as what you make is efficient,
if it works, it's right.
|
|
|
|
|
|
|