Unreal Engine 4 uses PhysX, a high-performance, multi-threaded physics simulation engine that supports a large number of features and is capable of doing very complex simulations in real time. PhysX was originally part of a video game Middleware package called Novodex, and is now owned and maintained by nVidia. You can use other Physics engines with UE, but this post is specifically addresses using PhysX. You can find links to the documentation and repositories at the end of the article.
The version of PhysX embedded in Unreal does its physics calculations on the CPU by default. As a side note, nVidia also provides a custom version of Unreal that enables some cosmetic physical simulations like particles, cloth, and fluid dynamics to be simulated on the GPU. You can find out more about this custom version right here. (Note that the gpu accelerated versions often work on both AMD and Nvidia GPUs - be sure to check the requirements.)
PhysX can be logically divided into 2 main areas of functionality:
- Simulation: Simulating the world by apply forces and determining contacts.
- Query: Determining the state of the world after simulation.
Let's talk about some basic PhysX terminology. The "world" in PhysX is called a scene. "Bodies" are the things in the world that can be affected by the simulation. Bodies can be held together by different types of "joints" that define if and how they will move relative to each other. A "force" is something that acts on a body and can cause it to move, but isn't itself a body (e.g. forces might be used to simulate wind or gravity).
Every frame, PhysX updates the location and rotation of all bodies in the scene based on their velocity and their interactions with other bodies and forces. Physx determines which bodies are in contact with each other and applies counter depenetration forces. In other words, it makes sure that bodies don't overlap.
PhysX provides a callback mechanism that lets code get notified of collisions. Most of the time, you won't interact directly with these PhysX callbacks, however. UE4 registers for these callbacks automatically and passes the information on to your code. You just need to implement Blueprint events such as
OnHit to get notified of these collisions
Joints are used to connect bodies. Joints are configured using "constraints" and "motors". Constraints define the allowed positions a body may be in in relation to the joint. Motors (or Drives) are also optionally used to generate corrective forces applied to maintain the given configuration. The Drive applies a force as:
force = spring * (targetPosition - position) + damping * (targetVelocity - velocity)
For example, a joint might be configured to simulate a spring, by using a motor to increase the corrective force with the distance to the joint.
Scene Queries: Raycasts and LineTraces
A very important capability is the ability to query the current PhysX scene, after it has been simulated. For example, in UE when you execute a LineTrace, you are generating a raycast query against the underlying PhysX scene. Shooting a gun, selecting the object under the mouse cursor, checking for actors with-in a given range, all require querying the underlying PhysX scene.
Querying is not free, but is often faster than you might think, since PhysX stores all collision geometry inside an optimized hierarchical spatial structure specifically designed for fast querying. In addition, query results can be batched and cached.
Each query is broken done into 3 phases:
- Broad Phase traverses the global scene spatial partitioning structure to find the candidates for mid and narrow phases.
- Mid Phase traverses the triangle mesh and heightfield internal culling structures, to find a smaller subset of the triangles in a mesh reported by the broad phase.
- Narrow Phase performs exact intersection tests (ray test for raycast() queries, and exact sweep shape tests or overlap tests for sweep() and overlap() queries).
Internally, the Physx Scene Query system uses two different acceleration structures, a hierarchical grid and an AABB tree. These acceleration structures must be continually modified in accordance with objects being added or removed, or object AABB updates due to changes in position or geometry.
See below for more on line traces....
Each physics tick, the simulation is run for a certain elapsed time delta. Due to the nature of the underlying simulation, it is better to run each physics tick with the same size time delta. (non-uniform timesteps increase instability). Since our game is running with a variable frame rate, it is often common to break-up the physics-tick into multiple smaller "sub-steps". So every frame, multiple sub-steps of relatively the same size are executed. This in essence chops up the frame delta time into uniform time slices. This can result in a more accurate and stable simulation. Sub-stepping typically comes into play at lower framerates, where we must simulate physics more times per frame because the elapsed time is greater.
Sub-stepping can be turned on in the project specific physics settings. You can also register a c++ callback to be called from the sub-step. You can use this callback to provide custom physics code during each sub-step.
More Sub-Stepping Info
You configure the sub-step in Project Settings:
You can request physics to callback your own custom function during the sub-step withAddCustomPhysics.
Add a custom delegate to your header:
Then bind the delegate in the constructor:
And set the callback during every tick:
UE Physics Source
UE wraps up most of the PhysX api in an abstraction layer. This is located in Engine/Source/Runtime/Engine/Classes/PhysicsEngine. Many of the features in this wrapper are also exposed to blueprints, however certain parts are only accessible with c++.
The underlying PhysX API object model:
There are 3 kinds of bodies in the simulation:
- Dynamic(PxRigidDynamic) - These are the standard rigid bodies, affected by forces and collision.
- Kinematic(PxRigidDynamic) - These are Dynamic bodies that have infinite mass and inertia. If moved with setKinematicTarget they will affect dynamic bodies. These are good for dynamic objects that are moved by your code instead of by the physics simulation. e.g. moving platform. If a body is not simulating physics and is not set to static mobility, it will be kinematic.
- Static(PxRigidStatic)- This is for stuff that doesnt move. e.g. level geometry. If they are moved, the spatial partitioning structure must be rebuilt (unlike Kinematic bodies) which has a cost. In addition, when they are moved they do NOT affect dynamic bodies. This type of body is created in UE when the Mobility type is set to static. Most of the WorldStatic geometry in the scene is typically Static.
Dynamic bodies move, while static bodies haves implicit infinite mass/inertia(they are stationary).
Geometry is attached to rigidbodies and used to generate collisions with the scene. Geometry typically consists of simplified collision shapes such as spheres, cubes, etc... but may also be the actual heightfield or trimesh. PhysX Docs
UE uses a slightly different abstraction names for these rigid bodies, and there are a few settings that affect which underlying PhysX body is used:
If Simulate Physics is on == Dynamic
If Mobilty is Movable == Kinematic
If Mobility is static == Static
If one or both bodies is Dynamic, then collisions occurs.
If both are static then no collision occurs.
If one is kinematic and the other is Kinematic or Static, then you must move the kinematic with Sweep checked in order for collision to occur.
Again - one very common source of confusion surrounding collisions occurs between Kinematic and Kinematic, as well as Kinematic and Static. When moving a Kinematic body, remember to set sweep to true if you want collisions.
Creating Rigid Bodies
A RigidBody is created in PhysX with createRigidDynamic or createRigidStatic. (These are wrapped up in BodyInstance in CreateActor_PhysX_AssumesLocked).
The UE wrapper for these rigid bodies is FBodyInstance.
FBodyInstance::InitBody is responsible for creating the underlying PxRigidActor - either Dynamic or Static.
When your level loads, static and dynamic rigid bodies are created for all the level geometry, skeletal meshes, and static meshes. Upon starting, InitBody may be called hundreds of times.
This is typically done through the PrimitiveComponent in OnCreatePhysicsState.
Moving Rigid Bodies: Sweep, Teleport, CCD
When moving rigid bodies, it is important to consider how we want to handle velocity and collision response. The following Epic blog post does a great job and is worth a read:
Channels, Collisions andTraces
In UE, a collision occurs when objects collide during simulation. Configuring this is another common source of confusion and frustration. See Trace Docs
Typically there are many different types of objects in your game - depending on what type of objects are colliding, you may want them to block, overlap, or ignore. For example, the arrows of a hero should not hit the hero but only hit enemies.
Rather than define these interactions on a per-object level, you can define an ObjectType for each type of object.
e.g. Hero, Enemy, Bullet, Wall
You can specify this object type on each instance or class of a collision object..
In addition to specifying an ObjectType, you can also specify a Collision Response to control how the object reacts to every other object type. Ignore or Overlap or Block.
There are presets defined that store these settings and can be configured in Project Settings.
UE tries to differentiate configuration between "Trace Response" (Querying) and "Object Response"(Physics Simulation) .
Collisions With Objects During Simulation ( Object Response Section )
There are 3 options for handling collisions: ignoring, blocking and overlapping.
- Ignoring does exactly what it sounds like; these objects are completely ignored during collision handling.
- Blocking will cause the simulation to prevent penetration and apply corrective forces to prevent penetration.
You can optionally handle this block in an OnHitEvent.
- Overlapping occurs when bodies are interpenetrating each other. Use this if you need to be notified of the overlap but still want the bodies to penetrate. You can optionally handle the collision in an OnOverlapEvent.
NOTE: Both objects in a collision have these settings which enable/disable generation of these events.
Trace Response To LineTrace Querying (Trace Response Section )
A very similar setup is used to configure LineTraces.
Since you can query the physics scene after each simulation step using LineTraces, you can define whether these traces Ignore, Overlap, or Block.
In this context, the Overlap setting lets the trace pass through and also hit other objects. See Multi Line Trace
Line Traces Types
- LineTraceByChannel - This traces against objects that have a Block setting on a specific Trace Channel
- LineTraceByProfile - Traces for objects that have a specific Profile
- LineTraceForObjects: This applies a filter to trace against specific Types Of Objects
In addition to the regular LineTrace, there is a MultiLineTrace
Multi will return multiple hits for the trace, and the target can be configured to Block or Overlap. In this case, a block will prevent further tests for intersection.
Another useful built-in scene query function is BoxOverlapActors and SphereOverlapActors. Both of these return an array of actors (there are also component versions),
To summarize, the Trace Channels are used to define how an object responds to various types of LineTraces while the Object Collision Response specifies how the physics simulation behaves during integration.
For example, if you only want certain objects to respond to your hero attacks, then you could create a HeroAttack trace channel and use this when you test your attacks. This way, you have granular control over what responds to being attacked.
SetCollisionEnabled allows you to configure whether a given object responds to Physics Collision, Traces, or both.
Because filtering interacting pairs is extremely performance sensitive, PhysX 3.0 introduced the notion of a "filter shader". In Unreal, by default, this shader is built from the query (trace) and sim (physics) information defined in the collision settings.
Complex Vs Simple
Simple Collision are primitives like boxes, spheres, capsules, and convex hulls. Complex Collision is the actual trimesh of the given object. When you're performing scene queries you can specify if you'd like to use simple or complex collision.
Also note that complex collision shapes cannot be simulated.
For a static mesh, Complex collision uses a regular trimesh which is passed into PhysX. This mesh is never updated at runtime and can be used for scene queries as well as static collision. The mesh is cooked offline so that various optimizations are done, for example building a BVH and cleaning up vertices etc...
For a skeletal mesh, the trimesh must be updated every frame to match the skinning and can be fairly expensive. Thus it is recommended to use Simple whenever possible.
Joints ( Constraints )
A joint consists of two bodies and their reference frames(position and orientation) to the joint. Each joint defines a relationship between the these positions and the constraint itself that will be enforced by the PhysX constraint solver.
Joints can be used in many scenarios - door hinges, ragdoll bodies, car wheels are all examples of joints.
The solver attempts to enforce the constraint by applying corrective forces. In addition, the joint can optionally be configured to utilize motors, which are implicitly integrated. Motors are more expensive, but are also more stable.
PhysX includes a variety of different joints, but UE only uses one: PxD6Joint. The D6 joint is by far the most complex of the standard PhysX joints and is highly configurable.
A joint is created in PhysX with a call to
PxD6JointCreate. (All joints in UE are D6 joints)
UE wraps up the PhysX joint in
UE wraps the PhysX PxD6Joint constraint with
A joint defines which axis are locked, limited, or free.
Joint Drives (Motors)
Some PhysX joints may be actuated by a motor or a spring implicitly integrated by the PhysX solver.
If the bodies of the joint are out of compliance with the joint, projection will teleport them to correct positions.
UE also includes support for PhysicsAssets. These enable you to easily create bodies and constraints for a skeleton asset. (Both the skeleton asset and Physic Asset are created by default when importing a skeletal mesh)
The physics asset can be edited using the PHaT Tool. (This tool was significantly updated in 4.18!)
The ragdoll is simply a group of physics bodies tied together with constraints. For example, when a character is killed, he typically stops animating and becomes a ragdoll, crumbling and tumbling to the ground. In Blueprints, you can simply use the SetSimulatePhysics node, and your character will go full ragdoll. PhysX simulates the rigidbody position of the ragdoll, solving for the constraints every frame.
It is frequently useful to refine the default constraints to make your ragdoll more realistic.
Async and Sync
PhysX runs two physics modes: Synchronous and Asynchronous, and Unreal has Scenes for each.
The rates at which rigid bodies dissipate angular and linear momentum are governed by damping rates. In the PhysX SDK two damping rates may be specified for a rigid body:
void PxRigidDynamic::setLinearDamping(PxReal linDamp);
void PxRigidDynamic::setAngularDamping(PxReal angDamp);
With a linear damping value of linDamp a rigid body will experience a damping force each update equal to -linDampvelocity. Similarly, a rigid body with damping rate angDamp will experience a damping torque -angDampangularVelocity. The damping forces and torques always act against the velocity and angular velocity and are applied in a way that ensures that a moving and rotating rigid body will asymptotically approach the rest state in the absence of other forces. Taken from
In addition to simulation using a PxScene, PhysX offers a low-level simulation API called "immediate mode". This provides an API to access a low-level contact generation and constraint solver.
The PhysX include for this is
PxImmediateMode.h. Unreal has wrapped this in
Both the upcoming Niagara and the RigidBody AnimNode use this to provide high-performance simulation outside of the normal PhysX Scene.
Skeletal Controls Docs
PhysX Visual Debugger (PVD)
This is a useful tool nvidia provides for debugging physics. Similar to a graphical frame debugger, PVD lets you visual the underlying PhysX scene on a frame-byframe basis. You can download from https://developer.nvidia.com/physx-visual-debugger After running it, you can connect to it from Unreal by simply typing pvd connect in the console.
Hopefully this has helped give additional information and context on using Physics and Unreal for your game development!
Links & Bibliography
- The UE4 Physics documentation can be found here
- If you're interested in the history of PhysX, you can find more information here.
- The source code for PhysX is free and available for download from GitHub, though you must be a registered nVidia developer to access it (which is also free).
The main nvidia PhysX SDK documentation can be found here
Subscribe to Recursive Blueprints
Get the latest posts delivered right to your inbox