UDK Third Person Camera


The following code examples below can be used to create a third person camera in projects made with Unreal Development Kit 3. I used the December 2010 Beta version of UDK when modifying and testing the code. The code originates mainly from 2 different examples from the official UDK Documentation, but with my own modifications.
While the official documentation shows you how to place the camera right behind the character's shoulder, these examples will enable you to easily place it further back, up, and add an angle to look down onto your character. For my own use, I extended the 3 classes UTGame, UTPawn and UTPlayerController.
Look for red comments in the code below for main variables/code segments to change for different results.
UTGame extended class:
class MyGame extends UTGame;
defaultproperties
{
//Points to your custom Pawn class
DefaultPawnClass=class'MyPawn'
//Points to your custom PlayerController class
PlayerControllerClass=class'MyPlayerController'
}
UTPawn extended class:
class MyPawn extends UTPawn;
var int IsoCamAngle; //pitch angle of the camera
//override to make player mesh visible by default
simulated event BecomeViewTarget( PlayerController PC )
{
local UTPlayerController UTPC;
Super.BecomeViewTarget(PC);
if (LocalPlayer(PC.Player) != None)
{
UTPC = UTPlayerController(PC);
if (UTPC != None)
{
//set player controller to behind view and make mesh visible
UTPC.SetBehindView(true);
UTPC.bNoCrosshair = true;
SetMeshVisibility(UTPC.bBehindView);
}
}
}
simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV )
{
local vector CamStart, HitLocation, HitNormal, CamDirX, CamDirY, CamDirZ, CurrentCamOffset;
local float DesiredCameraZOffset;
CamStart = Location;
CurrentCamOffset = CamOffset;
/* Increase or decrease the number 15 to move the camera up or
down (Z-axis) to the character respectively. */
DesiredCameraZOffset = (Health > 0) ? 15 * GetCollisionHeight() + Mesh.Translation.Z : 0.f;
CameraZOffset = (fDeltaTime < 0.2) ? DesiredCameraZOffset * 5 * fDeltaTime + (1 - 5*fDeltaTime) * CameraZOffset : DesiredCameraZOffset;
if ( Health <= 0 )
{
CurrentCamOffset = vect(0,0,0);
CurrentCamOffset.X = GetCollisionRadius();
}
CamStart.Z += CameraZOffset;
GetAxes(out_CamRot, CamDirX, CamDirY, CamDirZ);
CamDirX *= CurrentCameraScale;
if ( (Health <= 0) || bFeigningDeath )
{
// adjust camera position to make sure it's not clipping into world
// @todo fixmesteve. Note that you can still get clipping if FindSpot fails (happens rarely)
FindSpot(GetCollisionExtent(),CamStart);
}
if (CurrentCameraScale < CameraScale)
{
CurrentCameraScale = FMin(CameraScale, CurrentCameraScale + 5 * FMax(CameraScale - CurrentCameraScale, 2)*fDeltaTime);
}
else if (CurrentCameraScale > CameraScale)
{
CurrentCameraScale = FMax(CameraScale, CurrentCameraScale - 5 * FMax(CameraScale - CurrentCameraScale, 2)*fDeltaTime);
}
if (CamDirX.Z > GetCollisionHeight())
{
CamDirX *= square(cos(out_CamRot.Pitch * 0.0000958738)); // 0.0000958738 = 2*PI/65536
}
/* Increase or decrease to move the camera backward or
forward (X-axis) to the character respectively. */
CamDirX *= 10;
out_CamLoc = CamStart - CamDirX*CurrentCamOffset.X + CurrentCamOffset.Y*CamDirY + CurrentCamOffset.Z*CamDirZ;
if (Trace(HitLocation, HitNormal, out_CamLoc, CamStart, false, vect(12,12,12)) != None)
{
out_CamLoc = HitLocation;
}
out_CamRot.Pitch = -1 * IsoCamAngle;
return true;
}
/* This code makes sure the character keeps aiming straight forward,
remove whole event procedure if you don't want this. */
simulated singular event Rotator GetBaseAimRotation()
{
local rotator POVRot, tempRot;
tempRot = Rotation;
tempRot.Pitch = 0;
SetRotation(tempRot);
POVRot = Rotation;
POVRot.Pitch = 0;
return POVRot;
}
defaultproperties
{
/* Experiment with this for a different view-angle
after you have modified X and Z. It effects how much the camera tilts down- or upwards. */
IsoCamAngle=6420 //35.264 degrees.
}
UTPlayerController extended class:
class MyPlayerController extends UTPlayerController;
state PlayerWalking
{
ignores SeePlayer, HearNoise, Bump;
function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
{
if( Pawn == None )
{
return;
}
if (Role == ROLE_Authority)
{
// Update ViewPitch for remote clients
Pawn.SetRemoteViewPitch( Rotation.Pitch );
}
Pawn.Acceleration = NewAccel;
CheckJumpOrDuck();
}
}
function UpdateRotation( float DeltaTime )
{
local Rotator DeltaRot, newRotation, ViewRotation;
ViewRotation = Rotation;
if (Pawn!=none)
{
Pawn.SetDesiredRotation(ViewRotation);
}
// Calculate Delta to be applied on ViewRotation
DeltaRot.Yaw = PlayerInput.aTurn;
DeltaRot.Pitch = 0; // Keep this at 0 to avoid character weapon/aim pitching up and down.
ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot );
SetRotation(ViewRotation);
NewRotation = ViewRotation;
NewRotation.Roll = Rotation.Roll;
if ( Pawn != None )
Pawn.FaceRotation(NewRotation, deltatime);
}
defaultproperties
{
}
If you are a total newbie with UDK and don't know what to do with the source code above, you might want to take a look at this part of the UDK official manual.