news | about | forums | links | mods | tools | tutorials | contact

Unreal Physics 101 - author: [Pfhoenix] [mod exemplar]
The purpose of this tutorial is to 'enlighten' those who are new to the Unreal Engine to how physics for objects work. This tutorial is not intended to be a "how to" for any particular problem, but instead strives to explain the physics types, how they operate, and how they are generally used.
Step 1 : Know your enumerations
The Actor class houses the all important enumeration (for those who aren't familiar with enumerations, I can at best refer you to Tim Sweeney's UnrealScript Language Reference document, an excellent source for general information on the UnrealScript language) : EPhysics, which is defined as such :

var(Movement) const enum EPhysics { PHYS_None, PHYS_Walking, PHYS_Falling,
PHYS_Swimming,
PHYS_Flying,
PHYS_Rotating,
PHYS_Projectile,
PHYS_Rolling,
PHYS_Interpolating,
PHYS_MovingBrush,
PHYS_Spider,
PHYS_Trailer
} Physics;

What this means is that there are 12 Physics 'types', though in reality, you really have 11 available to use (we'll get into why this is in a bit). Let's get down to business.
Step 2 : PHYS_Huh?
Let's get PHYS with it.
PHYS_None - as you might guess, this physics type does nothing. Nada. Zip, zilch, the calorie content of celery. With this physics set, your object will not do anything for you. It will sit there until you set it's velocity, and it will do exactly as you say with no fear of native code doing funny things to it.
PHYS_Walking - this physics type is not reserved, per se, but is useless to you unless you have a Pawn subclass, in which it is vital and you pretty much can't use anything else. For Pawns, this physics has a LOT of native code behavior - if the Pawn isn't on solid ground, native code will change the physics to PHYS_Falling automatically. If the Pawn is falling and hits ground (lands), native code will change the physics to PHYS_Walking automatically. This physics type is responsible for the movement and feeling of the players in Unreal / Unreal Tournament. The variables involved with this physics type are : GroundSpeed (the maximum speed the Pawn can move on the ground) and Acceleration (how quickly the Pawn accelerates to GroundSpeed).
PHYS_Falling - though this one was mentioned in conjunction with PHYS_Walking, don't be fooled - if nothing else, this is the most common physics type (other than projectile) among in-game objects. This physics type is responsible for objects being affected by gravity. Native code automatically adjusts the object's velocity in the direction and magnitude of the ZoneGravity vector in the zone that the object is in. Sure, this is a pretty simple thing to do on your own, but with native code doing the work for you, you're far better off (as well as having the benefit of taking the current zone properties into account). Be careful - if you have an object that, in script code, has it's velocity set specifically, even if it's set each Tick(), your object WILL (and this can't be emphasized enough, because it demonstrates the overpowering nature of native code) slowly move with the gravity of the zone it is in.
PHYS_Swimming - another Pawn related physics, though this one is not set by native code. Instead, this physics type is used to simulate swimming behavior and controls for the pawns, simulating bouyancy, among other things. Though it may feel a like flying, swimming physics also takes into account the zone's fluidfriction (all handled in native code), something flying does not.
PHYS_Flying - yet another Pawn related physics type. Flying tells the native code to do pretty much one thing - allow the player to move in any direction, unhindered by gravity. This means the player can move about freely, but still interacts (collides) normally with world objects and level geometry. The variables involved with this physics type are AirSpeed (the speed the Pawn can move through the air) and Acceleration (how quickly the Pawn accelerates to AirSpeed).
PHYS_Rotating - the name is pretty clear, though it's application isn't. Rotating is for objects that, that's right, rotate. This would include inventory items (like weapons on the ground) or level objects (like fans). The speed at with the object rotates is governed by a variable called RotationRate, a rotator.
PHYS_Projectile - this is the other most common physics type (other than falling) among in-game objects. This physics type is responsible for simple movements - straight paths of travel objects, like rockets or bullets. With this physics, the object will move according to it's set Velocity, ignoring gravity. Objects that use this physics type are very easy simulated and predicted (referring to network behavior model). Variables involved with this physics type are AirSpeed and Acceleration (same as flying).
PHYS_Rolling - the red headed step child of the physics types. This, in technical parlance, is seriously b0rk3d. Dead. Ceased to be. No more. An ex-physics type.
PHYS_Interpolating - a physics type that is largely used by native code. It is used when moving Movers between keypoints as well as players between set interpolation points. This physics type is not something you are likely to ever need, unless you are putting together a map fly-through or complex mover for a map.
PHYS_MovingBrush - for Movers specifically, this physics type is responsible for the movement of elevators, platforms, doors.. i.e. any brush that moves around in a map, this physics (powered by native code) makes it work.
PHYS_Spider - if your first impression is to think of things walking on walls and ceilings, you'd be partially right. This physics was intended to allow objects to treat any level geometry surface as the 'ground'. This physics type is rarely used, and even more rarely experimented with.
PHYS_Trailer - a fairly common physics type. Trailer does one very nice thing - tells the object that has the physics type of Trailer to stay with (location wise) the object that owns it. Trailer is the easiest way to make sure that one object is always at the location (or a nearby offset) of it's owner, and because it's handled by native code, you won't see lag in locations in net games. Variables involved with this physics type are bTrailerSameRotation (tells the Trailer'd object's rotation to always be the same as the owner), bTrailerPrePivot (tells the native code to offset the location of the Trailer'd object from the Owner object by a vector, PrePivot), and PrePivot (a vector which is the the offset measured in world coordinates and is treated as an absolute vector offset, not relational to the Owner's rotation).
Step 3 : Physics in Action - Collisions
Now that you have the physics you want, it's important to understand how the Unreal engine detects collisions between objects. Level geometry is referred to as BSP geometry, or Binary Space Partition geometry. Without getting into too much detail, it's sufficed to say that collision with level geometry happens on a per polygon hit detection. Everything else (i.e. all Actor classes) works off of what's called a Collision Cylinder. In the Actor class, you have several key variables :
CollisionHeight - the height, measured in Unreal units, of the collision cylinder as measured from the middle of the actor to the top. This means that in reality, the collision cylinder is really 2 * CollisionHeight - the object's location is CollisionHeight off the ground (or the bottom of the cylinder is CollisionHeight below Location.Z) and the top of the cylinder is at Location.Z + CollisionHeight.
CollisionRadius - the radius of the cylinder
bCollideWorld - whether or not the object will collide with level geometry
bCollideActors - whether or not the object will collide with other actor objects
bBlockActors - whether or not the object will stop a moving Actor when they collide
bBlockPlayers - whether or not the object will stop a moving player when they collide
It is important to note that the collision cylinder does not rotate with the object - it is static and stays perpendicularly upright at all times (greatly simplifies collision detection calculations). Now, when a collision occurs, several functions might get called, depending on variables set.
HitWall(vector HitNormal, Actor HitWall) - if bCollideWorld is on, this event function gets called by the engine, letting the object know the normal to the collision plane between the level polygon and the object (the HitNormal points towards the object), as well as an Actor reference, which would let you know a couple things - if HitWall == Level, you've hit normal level geometry, if it's a Mover, then you've hit a mover.
Landed(vector HitNormal) - if the object physics is PHYS_Falling, this event function gets called by the engine when the object lands on level geometry while falling. HitNormal is the surface normal of the level geometry landed on.
Bump(Actor Other) - if bBlockActors or bBlockPlayers is on, this event function gets called for both objects. This event function gets called by the engine only once - at the initial time of the collision.
Touch(Actor Other) - if bCollideActors is on, this event function gets called by the engine for both objects. This event function gets called every Tick() that the collision still occurs. When collision happens the first time, there is an array of actors, called Touching[], which is a list of other actors touching this one. Other is put into the array if it isn't already there by native code. Touching[] is defined as const, meaning you cannot manually change any values of the array within UScript.
UnTouch(Actor Other) - if bCollideActors is on, this event function gets called by the engine for both objects. This event function is called when colliding objects are no longer colliding (as soon as the collision isn't occuring any more, this even function is called, but only once).
When it comes to event functions being called, be forewarned. Sometimes, the engine will not call both Touch() and Bump() - if both objects are bBlockPlayers, Bump() will be called, Touch() won't. If one object is bCollideActors and the other is bBlockActors, the object being bumped (the bCollideActors object) will get a Bump() event while the other will simply get a Touch() call.
Now you should at least have a good handle on the basics of physics and collision with the Unreal engine. There is a lot you can do with the rather simple tools given. Enjoy what you've learned here and experiment!
suggestions? questions? comments? please send them all to ray@beyondunreal.com

copyright 2001 ray davis. this site and all content belongs to me unless otherwise noted, with the exception of some tutorials. the authors retain the rights to their material, and are hosted here with their express permission. everything else is mine though, so don't steal it. bastards.
privacy