C++ Classic Camera Tutorial
Updated: Nov 13, 2018
In this tutorial we will create a camera system similar to classic games such as Resident Evil and Dino Crisis.
We will cover setting up a character, custom cameras, volumes and an animation blueprint.
This tutorial was created using Unreal Engine 4.20.
Other assets used: Visual Studio Community 2017, VAssistX, Sun Temple, Mannequin (from TP Template), animations from Kubold’s: Movement Animset Pro assigned to Mannequin.
The base idea of this tutorial is that we will have cameras and volumes that we can place around a world. We can associate cameras with the volumes so that when a player exits a volume, the camera view will switch.
YouTube Video Tutorial
The first thing we want to do is setup our input mappings. Here is a screenshot of my input mappings that I use in this tutorial:
Let’s start by creating our own C++ character class. To create our own C++ character, head over to the C++ classes folder in the content browser, right click and create a new C++ class.
Make sure you select character class, name the class: PlayerCharacter.
Select public and on the end of the path, add: /Pawns
Hit create class, it should compile and open Visual Studio automatically.
Player Character Source Code
In the header file for the Player Character, we declare 4 functions.
Move Forward, which will handle the forwards/backwards movement of the player character.
Turn, which will handle the rotation of the character.
Start Sprint, this will increase the character movement speed to our run speed.
Stop Sprint, this will reset the character movement speed back to the default walk speed.
We also declare 3 UPROPERTY's in the header.
Turn Amount, this is used to store the turn input. We will use this in an animation blueprint to drive turn in place animations.
Walk Speed and Run Speed, these are used to set the default values for running and walking.
Source code: PlayerCharacter.H
In the PlayerCharacter.cpp file, we include the header files for components that we will be using. Include the Input Component and the Character Movement Component header files.
We will be adding in classic tank movement controls so we can rotate using our Left/Right input. So to help us rotate we want to make sure that we disable the yaw controller rotation, which is enabled by default.
In the Constructor, we disable the controller rotation yaw by setting bUseControllerRotationYaw to false.
We also adjust the relative location/rotation of the character mesh so it is in the right position for the Mannequin mesh, which we will assign in a blueprint.
We also set the default movement speed for the character to be our WalkSpeed property.
That's all we add to the constructor.
In the SetupPlayerInputComponent function we bind our input events to the movement functions.
The MoveForward movement function simply adds movement input in the direction of the forward vector of the player character * by the input scale value.
In the Turn function, we set the Turn Amount property to the incoming InputAxis. We then Add local rotation to the player character on the yaw by feeding in the Turn Amount.
On StartSprint we set the MaxWalkSpeed of the character movement component to the value of RunSpeed.
On StopSprint we set the MaxWalkSpeed of the character movement component to the value of WalkSpeed.
Source code: PlayerCharacter.cpp
After compiling, we want to create a Blueprint based on our C++ GameMode so we can assign which character we spawn as. To do this, head to the C++ classes folder and find the Game Mode, right click on this and select “Create a blueprint based on <GameModeName>”.
Now that we have created a Game Mode, we can create a Blueprint based on our C++ character class. Name this: PlayerCharacter_BP.
Open up the Game Mode and assign the “Default Pawn Class” as the PlayerCharacter_BP we just created.
This will allow us to spawn as our Player Character, but before we do, we want to assign the mannequin mesh, open up the PlayerCharacter_BP.
Assign the “Mesh” component, drop down the Skeletal Mesh Component slot and assign the mannequin.
Testing the character
We are ready to spawn as the player character to test our input movement controls.
Let’s add a Camera (this is just to test) to our level by dropping down the arrow in the top left of the viewport, then select “Create Camera here”.
We can Pilot a camera by pressing CTRL+SHIFT+P. This allows us to place the camera in a position of our choosing in the level. Drop down the arrow in the top left to Unpossess the camera again.
To make this camera active by default when we start the game:
Select the camera, in the details panel on the right, drop down “auto active for player” and choose player 0.
Make sure you have assigned the Game Mode (Settings > World Settings) and that there is a “Player Start” in the level, after that, hit Play.
You should be able to walk + run around as the T-Pose mannequin character (we will be adding an animation blueprint later). If you press A/D you should rotate. Press left shift while moving to sprint.
Custom Player Camera System
Now that we have a Player Character, let’s create a C++ camera actor based on the Camera actor we just used. We can also delete the one we just used as we will be replacing it.
In the C++ classes folder, lets add a new C++ class. Check the “Show All Classes” checkbox and search for the CameraActor. Select it and hit next.
Name this “PlayerCamera”, make it public and add to the end of the path: /Actors. Then hit Create Class.
Player Camera Source Code
In the header file for the Player Camera, we declare a constructor, override the begin play function and we declare a boolean property to mark if this camera is the starting camera.
Source Code: PlayerCamera.h
Inside the constructor for the Player Camera, we get the camera component and set any default properties we want the camera to have.
Inside begin play, we check to see if the camera is marked as the starting camera. If it is the starting camera, we get the player controller and check that it is valid. If the player controller is valid we set the view target to this camera.
Source Code: PlayerCamera.cpp
Camera Switch Volume Source Code
Let’s create a new c++ class in the c++ classes folder.
Name it “CameraSwitchVolume”, make it public and make the path /Actors.
In the header file for the Camera Switch Volume, we forward declare the components we will be using.
We will be using a UBoxComponent for the volume. We will also be using a UTextRenderComponent just for some preview text to represent either side of the volume. We will also be exposing two APlayerCamera references so we can assign cameras to the camera switch volume. The player will switch to these cameras depending on which side the player exits the volume.
After forward declaring the components, we declare the components just under the declaration of the constructor.
Underneath the override for the tick, we override the OnConstruction function. This function is the equivalent of a blueprint construction script.
We declare UPROPERTY's for the volume width and volume height, these will be exposed in the details panel when we select the volume in the world.
We declare APlayerCamera UPROPERTY's for the New Camera and the Previous Camera. These will be exposed on the details panel too. These are the cameras that the player will switch to depending on which side of the volume the player exits from.
Finally we declare a UFUNCTION that will handle the overlap event when the player exits the volume.
Source Code: CameraSwitchVolume.h
In the cpp file for the Camera Switch Volume, we include the header files we will need.
We includethe header files for the box component, text render component, player camera, character class and the gameplaystatics.
In the constructor we create the components for the Box Collision and Text Render components.
With the text render components we setup some default values so they are positioned and orientated the correct way. We also make sure that they are not visible when playing the game.
On begin play, we bind the OnActorEndOverlap event to our OnEndOverlap function we declared.
For the implementation of the OnConstruction function, we set the volumes width and height. As soon as we make an adjustment to the volume width/height properties this will fire and adjust the volumes shape.
Finally, for the implementation of the OnEndOverlap function, we store locally the player character, player controller and camera transition parameters.
When something exits the volume, we check to see if the player character is valid, if the actor that exits the volume is the player character and we check to see if the player controller is valid.
If all these are true, we store an FVector of the players location relative to the volume.
We then check to see if the player has exited from the side that is associated with the New Camera. We do this by checking if the new camera is valid and if the X value of the PlayerRelativeLocation is greater than 0. If it is, this means the player character has just exited the volume from the new camera side, so we set the camera to the New Camera actor.
If any of the above is false, we repeat the steps but for the previous camera side and by checking if the players relative location X is less than 0. If it is, this means that the player character has just exited the volume from the side associated with the Previous Camera. So the camera will switch to the Previous Camera.
Source Code: CameraSwitchVolume.cpp
Now all our C++ code is complete. We can compile and test everything out.
In our level, let’s make sure that we have two cameras and one checked as the starting camera. Now let’s add our volume into the world, notice the properties on the side where we can adjust the volume width/height. Make sure to place the volume so that the player character will enter from the “previous camera” side.
Now let’s dropdown or use the medicine dropper tool to select the “previous camera” on the details panel. The previous camera will be the starting camera in this case.
Then select the NewCamera, this will be the camera we will switch to when the player exits from the new camera side.
Hit play and you should be able to walk back and forth through the volume, the camera will switch accordingly.
Try adding in more volumes and more cameras!
Make sure you name your volumes and cameras, as to not get confused!
That is the camera system part of the tutorial complete! The next steps will cover setting up an animation blueprint for our character.
NOTE: I use Animations from Kubold's Movement Animset Pro
To create an animation blueprint, Right click in the content browser: Animation > Animation Blueprint.
Unreal will ask the target skeleton, I am using the mannequin so I will assign it to the UE4_Mannequin_Skeleton.
Hit OK and name it: PlayerCharacter_AnimBP
Switch over to the event graph tab and call the "try get pawn owner" function. From this we can drag out the return value and cast to our PlayerCharacter_BP.
We want to store our Turn Amount, Speed and Direction.
From the PlayerCharacter_BP we can drag out from the blueprint reference with the "As Player Character BP" pin and we can call "Turn Amount" to get our C++ property we created. With this we can right click on this and promote it to a variable with the same name.
To calculate the characters speed, drag out from the blueprint again and call the "Get Velocity" function, this returns a vector. With this vector return value we can drag it out and call the "Vector Length" function. This now returns our speed, so we can promote this to a variable named "Speed".
To calculate the characters direction, right click anywhere in the graph and call the "Calculate Direction" function. Connect the vector return value from the Get Velocity to the Velocity input on the Calculate Direction.
Drag out from the blueprint again and call the "Get Actor Rotation" function and use the return value for the Base Rotation.
Now we can promote the return value of the Calculate Direction function as a variable, we can name this Direction.
That's all we are going to do in the animation blueprint event graph.
Now let's return to the content browser and create a Blendspace for the mannequin. Right click and go to Animation > Blendspace.
Assign it to the UE4 Mannequin skeleton and name this asset "PlayerMovement_BS".
First lets start by setting up the Axis Settings, in the top left of the details panel.
The Horizontal Axis is named "Direction" and it goes between -180 and 180 on the axis values. We give it only 2 Grid Divisions, which will allow us to assign Move Forward and Move Backward Animations. We can also apply some interpolation time to this if we want to.
The Vertical Axis is named "Speed" and it goes between 0 and 500 on the axis values. This uses 4 Grid Divisions. We can also apply some interpolation time to this, if we want to.
Now let's assign the animations to the Blendspace.
Drag the idle animation from the right panel, onto the bottom left corner, bottom centre and bottom right.
Drag the Walk Forward animation to the center and the Walk Backward animation to the far left and the far right on the line above.
On the top line, Drag the Run Forward animation to the top centre and the Run Backward animation to the top left corner and top right corner.
That is our Blendspace complete, we can return to the animation blueprint.
Switch over to the anim graph tab and right click and add in a new state machine by typing: "New State Machine".
Name this Base Locomotion and connect it to the final result.
Once connected to the final result, double click on the state machine to enter it.
Now let's setup our state machine, you can drag out from Entry to add a state and drag out from new states to add more states.
We will be setting up 3 states with the assigned assets:
Player Movement Blendspace - Animation: PlayerMovement_BS
Turn in Place Left - Animation: TurnLt90_Loop
Turn In Place Right - Animation : TurnRt90_Loop
Transition Rule from Blendspace to Turn In Place Left:
We can transition into our Turn in Place Left animation by making sure our speed is 0 AND if our turn amount is less than 0 (which would mean we are turning left!).
Transition Rule from Turn In Place Left to Blendspace:
To transition from Turning Left back to our Blendspace we want to make sure our speed is above 0 OR our turn amount is greater than or equal to 0. (This means the player must be moving, stood idle OR turning right).
Transition Rule from Blendspace to Turn In Place Right:
We can transition into our Turn in Place Right animation by making sure our speed is 0 AND if our turn amount is greater than 0 (which would mean we are turning right!).
Transition Rule from Turn In Place Right to Blendspace:
To transition from Turning Right back to our Blendspace we want to make sure our speed is above 0 OR our turn amount is less than or equal to 0. (This means the player must be moving, stood idle OR turning turning left).
Now let's return to the PlayerCharacter_BP and assign the animation blueprint we created by dropping down the Anim Class, above where we set the skeletal mesh.
Now when we play the game, our Player Character will be animated!
- Gavin Milroy (Tesla Dev)