Working with instances
Using instances when creating your Portal 2 map can greatly increase your speed and efficiency between prototyping a puzzle and publishing the final product. Stock instances included with the Portal 2 Authoring Tools can be used to create nearly every element of creating a map - from the most basic things like floor buttons, to more complex setups like box spawners, and even non-gameplay elements such as observation rooms.
Contents
What are instances?
Instances are VMF files which are referenced by your map during construction; at compilation the VMF files are combined. An instance VMF can contain anything as simple as a single brush, to an entire puzzle or gameplay element complete with logic entities and Input/Output triggers.
When should I use an instance?
One of the major benefits of using an instance is that any changes you make to the instance VMF is instantly translated to the rest of your maps. If you make a change to the look or operation of your floor button or your door, you do not need to go and change every usage of it in your map, like you would if you had manually created them and/or used a normal Prefab. Instead of creating several copies of the same entities, you can use an instance to build the button or door once, and then reuse it multiple times.
Instances are best used when creating game elements, geometry, complex entity or I/O setups (such as map transitions), or any other grouping of objects that is going to be repeated or reused frequently.
Building an instance from scratch
The map origin (0,0,0) will be used as the origin for the instance. For example, placing the floor level of a button at the origin will allow the button to be easily placed flush against the floor in your map.
Instances can deploy parameters; by placing a func_instance_parms in the instance file certain variables can be changed by the referencing map. Each variable must start with a $ symbol, and then must correspond to the value in another entity within the instance. If your instance requires Input/Output interaction with the referencing map add an func_instance_io_proxy entity with the targetname "proxy". For each Input that the instance will be able to receive, a corresponding Output in the func_instance_io_proxy with the Output "OnProxyRelay" will be required.
For example, if you are building a custom box dropper instance, you can setup a parameter "$box_type" which then corresponds to the box entity's "Cube Type" value, and another parameter "$box_trigger" which corresponds to the entity's relay "targetname" value. When you place this instance in your map, you will have the option to use the func_instance's "Replace" fields to change the type and the targetname of the relay entity that is created. You can then address just the box dropping trigger, rather than any other trigger the instance might contain.
For Parameter Overrides through I/O, proxies allow you to change the values, so you don't need a "$" variable for it.
A note about using func_instance_parms and targetname
If an entity in an instance has it's targetname set to a replaceable parameter field, any I/O in your map must target the entity's final instance collapsed name. During the VBSP process, all of your instances are gathered and collapsed into your map, and the names of any entities within those instances have their names altered. The renaming system works as follows (assuming the "Entity Name Fix Up" is set to "Prefix (default)":
- (value of your map's func_instance "Fix Up Name")-(instance entity's targetname)
Using Input/Output with instances
An instance can accept Input from your map - assuming it has the proper func_instance_io_proxy Outputs setup - quite easily. Using a basic floor button example, you can add any Outputs that the proper func_instance_io_proxy has setup. You can also target one instance from another, for example using a floor button to turn on or turn off a gel flow. Again you will simply select the target entity and it's Input fields will be automatically filled out.
It's also worth noting that you can send inputs to entities within instances directly. When creating the instance, the said entity should have the @ symbol at the start of its name. After placing the instance in your map, you can then send that entity inputs directly. Valve uses this method copiously in their elevator and level transition instances.
Technical
This is a general technical summarization about Instances. It's supposed to give a in-depth overview about their functionality.
Collapsed instances can be identified by the "AutoInstance-#" name, as that is the default name when collapsing an instance.
Paste Special can be very useful to center creatable instances into the center to have a good origin. Just note that offsetting the instance away from the sentence, will override the position.
- Unpacked Instances aren't affected by texture lock.
- The selection box from Instances that use
func_instance_origin
appear buggy. - The order of the
replace
key values, shouldn't matter.
- Adding any
$varname
will automatically create a parameter entry. - Nested instances need "proxy bridges" between each, to appear in the I/O autocomplete.
func_instance_parms
- Additional parameters can be added by just following this pattern
parm<num>
. This will addreplace<num>
. Just that additional ones don't have a description. The order doesn't matter as when the instance gets loaded it will just map gaps to new spots.
func_instance_io_proxy
- Decompilers or when compiled, seem to turn
OnProxyRelay
, giving them a number as a suffix, like OnProxyRelay1, etc. The original value is "OnProxyRelay".
General Advice
Instances are similar to what it is known in other Engines, e. g. Unity or Unreal Engine, as Prefabs or Packages from Roblox.
They're encapsulated presets that can be placed and used. We can compare it to what a prop_button
is. A prop_button
is nothing but an entity with scripts defined in the source of the game. Every new created prop_button looks the same and the user-editor can give events to it.
If the source code of prop_button
would be modified, the modifications would be apply to every prop_button
entity.
Instances have that same concept. It's a pre-defined preset, in this case for Hammer Editor.
General Usage
Instances are used as presets and are a good replacement for any copy-paste like work. As example, if you have non-unique decorations that you place around the map, you can just turn them into an instance. Or if they look similar, you can create an instance as a preset, to then import and collapse, to modify it.
Once the deco is an instance, one would just have to modify that decoration instance, and all decorations based on that instance, would automatically update with the changes that you've made.
Instances have an aesthetic limitation. As example, turning a pure prop_button
into an instance along with a detailed floor, would limit the user-editor from conveniently create I/O for the prop_button that is within the Instance. Similar concept goes for nested Instances, which are Instances that contain other Instances.
This makes Instances have the same aspective as Object-oriented programming (OOP), along with a similar concept of the SOLID Principle, which sort of says: Is that what gets created flexible, or would you end up modifying too much that could of have been simplified?
Performance-wise in Hammer Editor it is also limited. And you should save your map file, when making intensive edits to Instances using the "Edit Instance" button.
Collapse function
Instances can be collapsed, found at the top at "Instancing". This will de-capsulate an Instance, which makes it no longer be an Instance anymore, making it no longer sync the changes from that instance.
This is extremely useful to import "presets" and extract them right into the map. This is very useful, like for pre-defined shapes, to collapse and then texture them, without having to modify the original instance.
Instances are meant to make things easier and simplify the workflow.