I have recently begun reading "the textbook" on cameras in gaming, and I am excited to share whatever knowledge I gain from it with you. So, I will be implementing a third-person camera system in Unreal Editor 4 - similar to the one in Journey - and sharing every step of this process; while attempting to apply my newly learned knowledge in aid of both integrating and communicating these concepts. The main inspiration for this project is a GDC 2014 talk by John Nesky called "50 Camera Mistakes" (see http://gdcvault.com/search.php#&category=free&firstfocus=&keyword=john+nesky&conference_id=).
A starting piece of wisdom from John Nesky, the camera designer for Journey, who says (and I paraphrase)
"A camera is 7 numbers: yaw, pitch, roll, distance from pivot, lateral offset, vertical offset, and field of view."
In this article, I will analyse the existing C++ for the Code Third Person project provided by Epic Games with UE4.
The camera seems to be coded in the "MyCharacter" class. Let's examine the header file to see the variables involved
Variables to keep track of (this is not working code), referenced by letter index in the following sections
a)
/** Camera boom positioning the camera behind the character */
TSubobjectPtr<class USpringArmComponent> CameraBoom;
b)
/** Follow camera */
TSubobjectPtr<class UCameraComponent> FollowCamera;
c)
/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
float BaseTurnRate;
d)
/** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
float BaseLookUpRate;
Now over to the .cpp file to see how these are initialized:
The controller rotation is unhooked from the character rotation by setting 3 booleans (related to yaw, pitch, and roll) = false.
// Create a camera boom (pulls in towards the player if there is a collision)
CameraBoom = PCIP.CreateDefaultSubobject<USpringArmComponent>(this, TEXT("CameraBoom"));
CameraBoom->AttachTo(RootComponent);
CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character
CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller
The camera boom is created first and it follows the player at a set length, rotates based on the controller rotation, and is attacted to the root component of the player. (a) is the pointer used to represent this object.
FollowCamera = PCIP.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FollowCamera"));
FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation
FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm
(b) is the pointer that represents the camera itself, which depends on the boom for placement in real-time.
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AMyProjectCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AMyProjectCharacter::LookUpAtRate);
Input is obviously an important aspect of camera orientation, even with a camera that cannot be controlled independently from the character (as seen in Journey). Mouse and Gamepad provide two different orientation styles which require separate implementations. For this project, I will use a RAT-7 mouse, and a PS4 gamepad with drivers from this source: http://www.gamefront.com/files/listing/pub2/PlayStation-4-Controller-Drivers/
That is all I could find in the files at present. It really does not paint a great picture of the basic implementation for a third person camera. I will consult the forums and tutorials to learn more about this system in UE4 and find where the camera behaviours I want to analyze are hidden.