Door creation
In this tutorial, you will learn how to create a functioning brush-based door.
Brush or Point Based?
It is important to know the difference between a "brush-based" and a "point-based" door. For starters, brush-based doors are, obviously, created from a brush that is tied to an entity. You generally have more control over how the door is shaped and how it looks compared to a point-based door. Point-based doors, however, can have functioning opening hardware, such as handles, push bars, and keypads. They are, however, restricted to a select few models that may not be present in more modern titles, such as Portal 2.
Making the Doorway
To create a brush-based door, make a wall with a gap that the player can move through. See dimensions for sizing. To make a gap in the wall, use the Clipping Tool to create a separated section, then make a hole at the bottom of that section. Make sure to put a brush underneath the doorway or there will be a leak.
Creating the Brush Door
To create the actual door, create a brush that fills the hole in the doorway. It is recommended to make the door have a different texture to make it stand out against the wall.
Turning the Brush Into the Door
To turn the brush into a functioning door, select it and press ctrl+T. If you want a door that moves in a specified direction, select func_door then scroll down to the Move Direction property and set the value you want, or select up or down from the small dropdown. For a more traditional style door, select func_door_rotating. To make a func_door_rotating
rotate around a different point than the center, drag the origin helper in the 2D view or the blue sphere in the 3D view to the point you want it to rotate around.
To activate the door, go into the Flags tab and check either the On Touch
, On Use
, or both. To have the door close on its own, go to the keyvalues and scroll down to the Delay Before Reset
value and set it to whatever delay you want. Keep in mind that the door will not start closing if it detects that there is an object blocking it. To make a door close manually instead of from a delay, go to the next section where we will talk about creating an activator for our door.
Making a Button for Your Door
If you want your door to be toggle-able, you need to create a func_button, or other entity that can activate and send an output, and set it to toggle the door open and close state. If you want a func_door_rotating
to move when the player +USE
es on the door, and also be able to open and close multiple times when you use it, you will have to create a button that moves with the door. First, name the door something like door1
. Then create a brush that covers and extends slightly beyond the door and tie it to a func_button
. Set the texture to tools/toolsinvisible
and set the collision to None. Then, set its parent to the name you gave the door. When the door moves, so will it. Scroll down and set its reset time to 0 and also set its speed to 1000. We set the speed this high so it resets immediately. Then, go to the output tab. Create a new output and set it to this:
That should enable the door to be used multiple times.
An alternate way to open and close the door is by using trigger_multiples to automatically open and close the door when you approach it.
Create a brush with the tools/toolstrigger
texture and tie it to a trigger_multiple
. Give it a name and then go to the outputs tab. Set the following outputs:
My Output Target Entity Target Input Parameter Delay Only Once OnStartTouch door1 Open 0.00 No OnEndTouch door1 Close 0.00 No
Keep in mind that there are many ways to open the door, these are just two ways of doing this. For example, in Portal 2 you can open and close them with prop_button and prop_floor_buttons. Almost any entity that is capable of firing an output can open and close doors.
Avoiding Graphical Bugs
When using a func_door
, if it is the same width as the wall and moves into it, it will appear to phase in and out if the textures are different. The best way to avoid this is to scale down the width of the door and also to make a slot in the wall for where the door will slide into. This issue is not always present in func_door_rotating
as it does not completely submerge into the wall, unless specified, so it is not as important in that case but should still be taken into account.
Making Double Doors
When creating linked double doors, it is necessary that they have interconnecting outputs that open and close each other. First, make two doors through the process stated above and name them accordingly (e.g., door1
and door2
). You will then have to choose a different method of opening and closing the doors in tandem based on the activation method you chose.
External Activator (button, trigger)
Add two logic_relay somewhere close to the doors. Name them something similar to door_open
and door_close
. Set the Start Enabled?
property of door_close
to Yes
. Go to the properties of door_open
and set the following outputs:
My Output Target Entity Target Input Parameter Delay Only Once OnTrigger door1 Open 0.00 No OnTrigger door2 Open 0.00 No
Repeat this for door_close
but set the input of the first two to Close
If using a button or similar entity that will toggle the door on every activation, also add these outputs:
My Output Target Entity Target Input Parameter Delay Only Once OnTrigger !self Disable 0.06 No OnTrigger door_close Enable 0.05 No
Repeat this for door_close
, but set the Target Entity of the second to door_open
.
Now, go to your activator and set the outputs:
Toggle (eg. func_button)
My Output Target Entity Target Input Parameter Delay Only Once OnPressed door_open Trigger 0.00 No OnPressed door_close Trigger 0.00 No
On/Off (eg. Trigger_multiple)
My Output Target Entity Target Input Parameter Delay Only Once OnStartTouch door_open Trigger 0.00 No OnEndTouch door_close Trigger 0.00 No
Now, when you trigger door_open
(when enabled), it will open both doors and when you trigger door_close
(when enabled), it will close both doors.
If using a button to toggle the door, here is a diagram to display how the enable and disable outputs work:
Player uses the button to open --> Button triggers open relay --> Open relay opens doors and enables the close relay (but does not fire it) and disables itself
Player uses the button to close --> Button triggers close relay --> Close relay closes doors enables the open relay (but does not fire it) and disables itself
When the player uses the button, it will try to trigger both relays, but because one is disabled it cannot fire and therefore only one relay is triggered.
If using two buttons that are parented to either side of the door, name them something like button_left
and button_right
and make one button, for the sake of this tutorial button_left
activate the relays while the other, in this case button_right
, press button_left
when it is pressed:
The reason why we are using two logic_relay
s to open and close the door instead of using the Toggle
input is simple: if one door gets blocked and prevented from opening, it will default back to the position it was in. This is very problematic because the doors could get desynced and alternate between open and closed. So, to prevent this, we make it so that there are set opening and closing, so that if one door does get blocked it can sync back up with the other by using it a few times.
Flags (Use Opens, Touch Opens)
Add two logic_relay's somewhere near the doors (the location is not important, but it helps for organizational reasons to keep them close) and name them as well (e.g., door1_relay
and door2_relay
). Third, open the properties of the first door, go to the 'Outputs' tab, and add an output similar to the following:
Do this for the other door too, but change the Target Entity to door1
. What these outputs do is open one door when another one is opened (whether that be done via Touch, Toggle, a button, etc.). At this point, you could save and compile to test the doors out if you wanted, but they would only be able to open each other, not close each other. That is where the logic_relay's come in.
Now normally, you would think that you could repeat the process for closing the doors via Outputs (i.e., having one door be closed by the other), but such is not the case. If you try it out for yourself, you will find that the game crashes as soon as you go to close one of the doors. So, to work around this little bug, you need to introduce a logic_relay
for each door. If you've followed the above process so far, you should already have the two relays placed and named. Now, open the properties of the first door and add an output similar to this:
Again, repeat this for the other door, changing the Target Entity to door2_relay
. Next, open the properties for the first relay and add an output like so:
Repeat this for the other relay, changing the Target Entity to door1
. Now save and compile, and you should have a working set of double doors.
To help you understand this concept of Outputs and logic_relay's better, here is a little diagram for the above example:
Player opens door1
-->The opening of door1
triggers door2
to open via the Output of door1
Player opens door2
-->The opening of door2
triggers door1
to open via the Output of door2
Player closes door1
-->The closing of door1
triggers door1_relay
-->The triggering of door1_relay
triggers door2
to close
Player closes door2
-->The closing of door2
triggers door2_relay
-->The triggering of door2_relay
triggers door1
to close