Understanding Source's Physics Constraints
(January 22, 2018)
One of the major selling points of the Source engine are its physics. Source makes prime use of the Havok physics engine in realistically simulating props and objects, most notably in Half-Life 2's Ravenholm chapter, where physics traps are common, and the player's newly-acquired Gravity Gun becomes a vital part of their arsenal.
In particular, those physics traps are built using a class of entities known as physics constraints. Physics constraints allow props and other entities to be attached to one another and simulate each other in a variety of interesting and realistic ways. Some of them (such as the pulley constraint) are analogous to the classical simple machines, while others (like the "keep upright" constraint) modify physical properties of the entity in question.
A bit of background is required to understand the mechanics behind Source's physics engine.
VPhysics and QPhysics
Source actually has two different physics systems at play: the familiar VPhysics system, which is added by the Havok engine, and QPhysics, which is what players and ground NPCs use. QPhysics are a much simpler, legacy system originally implemented in Quake, because real-time physics calculations involving players and NPCs would be too costly at runtime. (This is why moving NPCs with the Physgun in Garry's Mod is so wonky and limited.) You don't need to worry about QPhysics much; just know that QPhysics objects can't be constrained with the entities discussed in this guide.
Props, ragdolls, vehicles, and flying NPCs such as helicopters use VPhysics instead. VPhysics objects can be rotated any which way and shoved around realistically by way of forces. The two major forces that Source's Havok simulates are linear force (where objects are pushed, pulled, and shoved against one another) and rotational force (also called torque). The simulation is mostly concerned with the defined weight of objects, the rate at which they move, and the resulting calculations of forces when those objects collide with others.
Understanding physics constraints
A few things are true about nearly all of the physics constraints listed below:
- The objects don't need to touch or be anywhere near one another when defined as attached.
- If only one object is specified, the constraint entity itself becomes the second entity.
- All constraints are breakable through player-created forces. Setting the force and torque limits to
0will make the constraint unbreakable, however. The I/O system can still be used to detach the two objects from one another.
- Any constraint can be assigned to a
phys_constraintsystem, which accounts for all constraints assigned to it in physics calculations, rather than solving for each separately. If you encounter any jiggling between entities in a large system of constraints, place a
phys_constraintsystemin the world and assign each constraint to it using the
constraintsystemor "Constraint System Manager" keyvalue.
Summarizing the physics constraints
Listed below are all of the physics constraints available in Source, in increasing order of complexity.
The most basic physics constraint,
phys_constraint attaches two entities to each other rigidly. The entities will move with one another, but the distance between them cannot change. (This is equivalent to the Weld tool in Garry's Mod.)
The ragdoll constraint will act as a "pin" and keep a ragdoll attached to another object, much like the normal
phys_constraint. Restrictions on how far the ragdoll can rotate along each axis can also be set.
The length constraint is like
phys_constraint, but with a specifiable amount of give between the entities. If the "Keep Rigid" spawnflag is set, the entities will be stuck the same distance apart, though they'll be able to rotate around their origins, unlike
phys_constraint. (This is equivalent to the Rope tool in Garry's Mod.)
The ball socket constraint creates an elbow joint for the two specified entities to swivel around. This joint allows for a full 360° range of movement, as it has no physical presence. There's no way to restrict the range of movement around this entity.
phys_ballsocket is different than most other physics constraints in that the entities are attached to it, rather than attached to each other. (This is equivalent to the Ball Socket tool in Garry's Mod.)
The slide constraint restricts entities to move along a single axis. Friction can be set so the object resists movement on that axis slightly. (This is equivalent to the Slider tool in Garry's Mod.)
The hinge constraint restricts entities to rotate along a single axis. The entities constrained won't be able to move around unless the constraint is broken. Friction can be set so that the constraint resists movement slightly, in the same way that a rusty door hinge might have more resistance than a new one. (This is equivalent to the Axis tool in Garry's Mod.)
A great example of
phys_hinge in action is with Ravenholm's spinning blade traps. A
phys_motor was used to apply torque to the blade traps, which spin on one single axis with enough force to chop oncoming zombies in half.
The spring constraint will stretch and deform with the forces placed upon it. This constraint has many options, though the big three are the Spring Axis keyvalue, which determines where the other end of the spring is, the Spring Length keyvalue, which determines the normal (at rest) length of the spring, and the Spring Constant keyvalue, which determines its stiffness.
In this sample map, yanking down on the box and letting go will cause it to shoot back up, as if it's attached to a spring being stretched before recoiling. (This is equivalent to the Garry's Mod Elastic tool with the "Stretch Only" setting disabled.)
It's best to imagine the pulley constraint as a rope through two points. The first point is the origin of the
phys_pulleyconstraint entity itself, and the second point is defined in Hammer as a blue helper ball. The rope is constrained through these two points, and the objects attached will pull one another, much like two ends of a pulley.
In these pictures, you can see the two points on the ground, where the rope takes a sharp bend. When one
func_physbox is pulled, the other one is pulled with it, and the rope is fed through the two points. (This rope is visualized using the Pulley tool in Garry's Mod for your convenience. The
phys_pulleyconstraint has no visual presence, like the other physics constraints.)
A special constraint,
phys_keepupright tries to keep the specified entity facing a particular direction. This constraint can't break, but it can be turned on and off with the I/O system. (This is equivalent to the "Keep Upright" option in the context menu for any props you might happen to spawn.)
The former Source SDK featured a demonstration map for each physics constraint; for convenience, these maps are supplied below in a separate download. They're worth a look if you're curious as to how to set one up, or would like to see them in action for yourself.