This is in response to Marti’s comment. Thank you Marti for your code request!
This is a very basic tutorial for implementing a custom camera in the UDK using UnrealScript. I will be using examples from my Starfox game as well. In order for the UDK engine to recognize and start using your camera class you need to set up a few things.
GameInfo
You will need to first set up a class that extends GameInfo, in my case I just named my class MyGameInfo. Here, you can tell the UDK which classes to use as the controller, which class to use as the default pawn, as well as which class to use as the HUD. For our example we just need to tell it our controller class, in my case it’s MyPlayerController. This is going to be done in the defaultproperties section.
class MyGameInfo extends GameInfo;
defaultproperties
{
Name="Default__MyGameInfo"
PlayerControllerClass=class'MyPlayerController'
}
PlayerController
Next, you will need to make the MyPlayerController class. This class is closely coupled with the default pawn class. I find that a lot of logic for reading in player input and then taking action on the player is found in this class. My class contains logic for determining when bullets are shot, when bombs are shot, calling barrel roll on the player, telling the player to lock on a target, etc. The only important thing for this tutorial is telling UDK which camera is linked to this controller. My class is just MyCamera, again, you can use any name you wish.
class MyPlayerController extends PlayerController;
defaultproperties
{
Name="Default__MyPlayerController"
CameraClass=class'MyCamera'
}
Camera
Alright, now we can use our camera class. Make sure your class extends Camera, but other than that I only found one important method that must be overridden to in order to update your camera. This is the UpdateViewTarget function, which is called by the engine every frame.
class MyCamera extends Camera;
function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
{
//your camera logic here
//...
//make sure to update OutVT
//OutVT.POV.Rotation = myRotation;
//OutVT.POV.Location = myLocation;
}
In this method, write your logic for your camera and when you’re done, simply update the parameter ‘OutVT’ with your final Rotation and Location for your camera. Rotations are always represented by the Rotator struct, and Locations are represented by the Vector struct.
Notes
You might see a lot of coding tutorials where they extend UDKGame instead of GameInfo, and UDKPlayerController instead of PlayerController. This is OK to do as well, however, this will include a lot of gaming logic pertaining to Unreal Tournament and the FPS genre. I often found that the engine was trying to do a lot of things behind the scenes that was taking control away from me, and I would get lost trying to fix them. Since my game is very different from an FPS I choose to extend from the very generic GameInfo and PlayerController classes.
StarFox Example
I’ll post my game’s camera code next. Let me know if I helped, or share your own story by posting a comment in the comments section. Thanks for reading!
class MyCamera extends Camera;
//member variables
var MyPawn cameraTarget;
var int cameraDistance;
var BoundingPlane myBounds;
var bool bInitialized;
var Vector myLocation;
/**
* Custom method for setting up camera.
* Setup initial location.
* Setup custom bounding box (camera used to be bounded,
* but now it just holds information about the center of the screen)
*/
function Initialize()
{
//top left of the bounding plane
local Vector topLeft;
//setup initial location
myLocation = cameraTarget.Location;
myLocation.X = cameraTarget.Location.X - cameraDistance;
//create bounding plane
myBounds = new class 'BoundingPlane';
myBounds.width = 1000;
myBounds.height = 400;
topLeft.X = myLocation.X;
topLeft.Y = myLocation.Y - (myBounds.width / 2);
topLeft.Z = myLocation.Z + (myBounds.height / 2);
myBounds.topLeft = topLeft;
}
/*
* Main update function for camera, gets called by engine.
*/
function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
{
local Rotator myRotation;
local Vector origin;
local float rotationPercentage, panningPercentage;
//grab the player
cameraTarget = MyPawn(PCOwner.Pawn);
//now that the player has spawned
if(cameraTarget != none)
{
//initialize camera
if(!bInitialized)
{
Initialize();
bInitialized = true;
}
//follow player if alive
if(cameraTarget.bAlive)
{
//camera's freedom
rotationPercentage = 0.15;
panningPercentage = 0.6;
//adjust rotation
myRotation.Pitch = cameraTarget.Rotation.Pitch * rotationPercentage;
myRotation.Yaw = cameraTarget.Rotation.Yaw * rotationPercentage;
//adjust location
origin = myBounds.topLeft;
origin.Y += myBounds.width*0.5;
origin.Z -= myBounds.height*0.5;
myLocation.Y = (cameraTarget.Location.Y - origin.Y)* panningPercentage + origin.Y;
myLocation.Z = (cameraTarget.Location.Z - origin.Z)* panningPercentage + origin.Z;
myLocation.X = cameraTarget.Location.X - cameraDistance;
}
//else watch player die
else
{
myRotation = Rotator(cameraTarget.Location - myLocation);
}
//Output values
OutVT.POV.Rotation = myRotation;
OutVT.POV.Location = myLocation;
}
}
DefaultProperties
{
DefaultFOV = 90.f //default is 90
cameraDistance = 280 //distance behind player
bInitialized = false
}