EDIT: I’ve noticed that there was a mistake to the Light Environment section. I forgot to include “Class=DynamicLightEnvironment” under the “//Setting up the light environment” section. It should work correctly now.
You’ll need a total of four classes to get this to work. The first of which is your YourGameInfo class.
class YourGameInfo extends GameInfo; //This line tells UDK that you want to inherit all of the functionality of GameInfo.uc, and< add your own. The name after "class" must match the file name.
DefaultProperties //Self explanatory
bDelayedStart = false
PlayerControllerClass = class ‘YourGame.YourGamePlayerController’ //Setting the Player Controller to your custom script
DefaultPawnClass = class ‘YourGame.YourGamePawn’ //Setting the Pawn to your custom script
Now that we have our initial game set up, we’ll need to add a a pawn to manipulate inside of the game. Here is the YourGamePawnclass.
simulated function name GetDefaultCameraMode(PlayerController RequestedBy)
//Setting up the light environment
Begin Object Class=DynamicLightEnvironment Name=MyLightEnvironment
//Setting up the mesh and animset components
Begin Object Name=InitialSkeletalMesh
//What to change if you’d like to use your own meshes and animations
//Setting up a proper collision cylinder
Begin Object Name=CollisionCylinder
Our Game and Pawn are all set up, but now we’ll need a way to interact with this pawn. That’s where the YourGamePlayerController class comes it. This is what allows us to actually control our pawn on screen. There’s quite a bit of code there, but most of it is heavily annotated, so if you break it down it should be pretty easy to understand.
Not all of it is needed either.
class YourGamePlayerController extends GamePlayerController;
var float PreDist; //tore our previous camera distance so that when we switch back to the normal camera, we’ll be at our original setting.
simulated event PostBeginPlay() //This event is triggered when play begins
Log("I am alive!"); //This sends the message "I am alive!" to thelog (to see the log, you need to run UDK with the -log switch)
//Functions for zooming in and out
exec function NextWeapon() /*The "exec" command tells UDK that this function can be called by the console or keybind.
We’ll go over how to change the function of keys later (if, for instance, you didn’t want you use the scroll wheel, but page up and down for zooming instead.)*/
if (PlayerCamera.FreeCamDistance < 512) //Checks that the the value FreeCamDistance, which tells the camera how far to offset from the view target, isn’t further than we want the camera to go. Change this to your liking.
`Log "MouseScrollDown"); //Another log message to tell us what’s happening in the code
PlayerCamera.FreeCamDistance += 64*(PlayerCamera.FreeCamDistance/256); /*This portion increases the camera distance.
By taking a base zoom increment (64) and multiplying it by the current distance (d) over 256, we decrease the zoom increment for when the camera is close,
(d < 256), and increase it for when it’s far away (d > 256).
Just a little feature to make the zoom feel better. You can tweak the values or take out the scaling altogether and just use the base zoom increment if you like */
exec function PrevWeapon()
if (PlayerCamera.FreeCamDistance > 64) //Checking if the distance is at our minimum distance
PlayerCamera.FreeCamDistance -= 64*(PlayerCamera.FreeCamDistance/256); //Once again scaling the zoom for distance
CameraClass=class ‘YourGameCamera’ //Telling the player controller to use your custom camera script
DefaultFOV=90.f //Telling the player controller what the default field of view (FOV) should be
exec function ShoulderCam() // Declaring our ShoulderCam function that we bound to
`Log("Shoulder Camera"); // Yet another log…
PreDist = PlayerCamera.FreeCamDistance; //Storing our previous camera distance…
YourGameCamera(PlayerCamera).CameraStyle = ‘ShoulderCam’; //Type casting our camera script to access the variable CameraStyle
exec function ReturnCam() //This is called on release of left shift
PlayerCamera.FreeCamDistance = PreDist; // Restoring the previous camera distance
YourGameCamera(PlayerCamera).CameraStyle = ‘ThirdPerson’; // Restoring the previous camera style
The last thing we’re going to need is the camera system itself. We’re going to call this YourGameCamera. There’s a lot of code in here, but most of it is heavily annotated, so if you break it down into bits it is actually pretty easy to understand.
Much of the code is not needed, but allows for us to easily switch between camera styles by simply swapping out a few lines of code. By default, this camera style is configured to have a free (mouse controlled) third person perspective, then by hitting a key of our choice (shift in this example), the camera will quickly zoom into an over the shoulder view for our character. Upon release, the camera will return to its previous state.
class YourGameCamera extends Camera;
// initializing static variables
var float Dist;
var float TargetFOV;
var float TargetZ;
var float Z;
var float TargetOffset;
var float Offset;
var float pival;
FreeCamDistance = 256.f
pival = 3.14159;
function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
//Declaring local variables
local vector Loc, Pos, HitLocation, HitNormal;
local rotator Rot;
local Actor HitActor;
local CameraActor CamActor;
local bool bDoNotApplyModifiers;
local TPOV OrigPOV;
// store previous POV, in case we need it later
OrigPOV = OutVT.POV;
// Default FOV on viewtarget
OutVT.POV.FOV = DefaultFOV;
// Viewing through a camera actor.
CamActor = CameraActor(OutVT.Target);
if( CamActor != None )
// Grab aspect ratio from the CameraActor.
bConstrainAspectRatio = bConstrainAspectRatio || CamActor.bConstrainAspectRatio;
OutVT.AspectRatio = CamActor.AspectRatio;
// See if the CameraActor wants to override the PostProcess settings used.
CamOverridePostProcessAlpha = CamActor.CamOverridePostProcessAlpha;
CamPostProcessSettings = CamActor.CamOverridePostProcess;
// Give Pawn Viewtarget a chance to dictate the camera position.
// If Pawn doesn’t override the camera view, then we proceed with our own defaults
if( Pawn(OutVT.Target) == None ||
!Pawn(OutVT.Target).CalcCamera(DeltaTime, OutVT.POV.Location, OutVT.POV.Rotation, OutVT.POV.FOV) )
// don’t apply modifiers when using these debug camera modes.
bDoNotApplyModifiers = TRUE;
case ‘Fixed’ : // No update, keeps previous view
OutVT.POV = OrigPOV;
case ‘ThirdPerson’ : //Enters here as long as CameraStyle is still set to ThirdPerson
case ‘IsometricCam’ : //Isometric camera
case ‘ShoulderCam’ : //Side Scrolling Camera for Mega Man 2
case ‘FreeCam’ :
Loc = OutVT.Target.Location; // Setting the camera location and rotation to the viewtarget’s
Rot = OutVT.Target.Rotation;
if (CameraStyle == ‘ThirdPerson’)
Rot = PCOwner.Rotation; //setting the rotation of the camera to the rotation of the pawn
TargetZ = 0;
TargetFOV = 90;
TargetOffset = 0;
if (CameraStyle == ‘IsometricCam’) // A basic if statement
/*Rot.pitch = -10000;*/
/*Rot.yaw = -5500; With these two statements, we’re telling the camera to stay fixed at these rotation values, provided by rahatropa */
Rot = PCOwner.Owner.Rotation;
TargetZ = 300;
TargetFOV = 90.f;
TargetOffset = 100;
FreeCamDistance = 64;
if (CameraStyle == ‘ShoulderCam’)
Rot = PCOwner.Rotation;
FreeCamDistance = 64;
TargetFOV = 60.f;
TargetZ = 32;
TargetOffset = 32;
if(CameraStyle == ‘FreeCam’)
Rot = PCOwner.Rotation;
Loc += FreeCamOffset >> Rot;
Loc.Z += Z; // Setting the Z coordinate offset for shoulder view
//Linear interpolation algorithm. This is the "smoothing," so the camera doesn’t jump between zoom levels
if (Dist != FreeCamDistance)
Dist = Lerp(Dist,FreeCamDistance,0.15); //Increment Dist towards FreeCamDistance, which is where you want your camera to be. Increments a percentage of the distance between them according to the third term, in this case, 0.15 or 15%
if (Z != TargetZ)
Z = Lerp(Z,TargetZ,0.1);
if (DefaultFOV != TargetFOV)
DefaultFOV = Lerp(DefaultFOV,TargetFOV,0.1);
if (Offset != TargetOffset)
Offset = Lerp(Offset,TargetOffset,0.1);
Pos = Loc – Vector(Rot) * Dist; /*Instead of using FreeCamDistance here, which would cause the camera to jump by the entire increment, we use Dist, which increments in small steps to the desired value of FreeCamDistance using the Lerp function above*/
// Setting the XY camera offset for shoulder view
Pos.X += Offset*sin(-Rot.Yaw*pival*2/65536);
Pos.Y += Offset*cos(Rot.Yaw*pival*2/65536);
// @fixme, respect BlockingVolume.bBlockCamera=false
//This determines if the camera will pass through a mesh by tracing a path to the view target.
HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12));
//This is where the location and rotation of the camera are actually set
OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation;
OutVT.POV.Rotation = Rot;
break; //This is where our code leaves the switch-case statement, preventing it from executing the commands intended for the FirstPerson case.
case ‘FirstPerson’ : // Simple first person, view through viewtarget’s ‘eyes’
default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
if( !bDoNotApplyModifiers )
// Apply camera modifiers at the end (view shakes for example)
//`log( WorldInfo.TimeSeconds @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV );