Game engine agnostic third person camera implementation

Totally Rad web games!
and indie game content!

News
Cowabunga! Little hooligans are on the way! Choose your hero and arrange an amazing disorder ^_^ Collect coins, upgrade bonuses, buy cool skateboards, avoid dangerous obstacles and get scores as much ...
Players in the game to get the first is the ultimate goal, there are a variety of fun props in the game, riding a motorcycle to a 360 ° air rotation. The scene of riding on the vehicle name can be...
You fight in an underground area of Moscow metro full of angry KGB soldiers trying to bring you down. Pick up various weapons to defend yourself and lead to the top of rank table!WASD - movement...
Subway Surf 2 is an endless runner game. As the hooligans run, they grab gold coins out of the air while simultaneously dodging collisions with railway cars.Controls Mouse Arrows...
Yo dude, you into tanks and wanna rack up some serious points by taking down some enemies? Look no further, this here simulator is perfect for gettin' ya take action on. Pick your fave weapon and blas...
Armed With Wings is a sword-fighting action game with a platformer element.Tap To Play ...
Gun Mayhem is finally back, after the smash hit Gun Mayhem 2. After a long break, you can now battle your friends or the AI in the epic Gun Mayhem Redux. There are 21 unique weapons with 2 fire modes ...
Armour Crush is a strategy tank deployment game. Objective is to destroy the opponent base by deploying the tanks. Deploy at least 3 tanks to advance towards enemy base. Selecting the right tanks at a...
Offroad Racing 2D is a fun racing game with multiple cars and levels.Use arrows to play...
Battle of Orcs is real time strategy units deployment game. Objective is to destroy the opponent base by deploying the orcs. Try different combination of units to make effective attack force. Selectin...
Cowabunga! Little hooligans are on the way! Choose your hero and arrange an amazing disorder ^_^ Collect coins, upgrade bonuses, buy cool skateboards, avoid dangerous obstacles and get scores as much ...
Players in the game to get the first is the ultimate goal, there are a variety of fun props in the game, riding a motorcycle to a 360 ° air rotation. The scene of riding on the vehicle name can be...
Home/Blog/Game engine agnostic third person camera implementation

Game engine agnostic third person camera implementation

BlogKev Zettler10 Apr, 2023

I recently migrated to a new game engine from a custom game engine. I needed to implement a third person character controller. This is something I did previously in the custom engine but forgot how. It took me a few days to relearn. I eventually reverse enginered my previous camera system. Finding resources online was suprisingly challenging. The style of camera I wanted is an "over the shoulder". Lots of the resources I found on how to implement were missing details on vertical axis rotation The implementation I settled on is odd and more of an 'arc ball' implementation that follows a player. The camera has an invisible 'view sphere' with a camera eye on one point of the spehere and a lookat target on the other.

This implementation is also agnostic to input devices. The player can use mouse+keyboard, a touch screen, or gamepad. This implementation assumes the player has a directional input for movement like WASD keys or Dpad. It is also assumed the player has another input for camera control like a mouse, analog stick, or touch screen. For the sake of consistency we will assume keyboard and mouse inputs.

sketch of a game engine agnostic third person camera controlerCrude sketch of the entire system

The following implementation uses some fake pseudocode to demonstarte the math mechanics. Mainly it demonstrates the required values and their relative mutations. I am documenting the implementation in this post so I will remember how to do it in the future.

Start with the front vector.

Setup a basic scene with a character mesh and a perspective camera. The character mesh and camera should face the world front vector this vector depends on the coordinate system of your game engine. The coordinate system of the latest engine I'm using is a Z up axis and the X axis is forward. This is similiar to the Unreal engines coordinate system. Previously I was working in a Y up and Z forward coordinate system. Freya Holmér has produced helpful chart on which tools use which coordinate systems It really dosen't matter what world vector you use as long as the camera and character default to facing the same vector and you consistenly use it for all view calculations.

Set a default offset for the view sphere

Next you want to create an offset vector that is the "view sphere offset". This is the vector that will translate the camera to a position over the shoulder of the player. This offset should be relative to the players position. You could update this vector on each frame as the player moves or you could make it a child entity of the player entity so it is calculated by the engine entity transform heiarchy. In our implementation we will manually be updating it each frametick.

Set the default camera and target positions

Next you will set the initial values for the camera eye and camera lookat positions. These vectors will be relative to the view sphere offset vector. They will be on opposite sides of the view sphere sphere. They extend forward and back from the view sphere center.

camera_lookat_position = view_sphere_offset + world_front * view_sphere_radius;
camera_eye_position = view_sphere_offset - world_front * view_sphere_radius;

The difference between the two is the addition and minus operations to the camera offset. The addition operation of the camera_target_position moves the camera positively to the front and the minus operation moves the camera_eye_position to the back.

At this point we have all the components for a static over the shoulder view of our player mesh. Next we will add code to to handle player input.

default view of engine agnostic third person cameraDefault position of player and camera

The player rotation quaternion

The first player input we want to address is horizontal axis rotation. The horizontal axis rotation will effect all our other movement calculations. We will need a quaternion to handle horizontal rotation. When the mouse moves on the X axis we rotate the horizontal quaternion on the around the vertical axis. this looks like:

horizontal_rotation_quat *= new_quaternion_from_rotation_z(delta_mouse_position_x * mouse_sensitivity)

This code assumes the quaternion implementation you're using has from_rotation methods that take a euler angle and create a new quaternion from that angle. Each gameplay frame we will use the horizontal_rotation_quat to update the players rotation and heading, we will apply the rotation value in the next section.

horizontal rotation in game engine agnostic third person cameraHorizontal rotation. orb is center point of the view sphere

Handling player movement input

Now that we have our heading for the players horizontal direction it makes sense to tackle the WASD input We need a few new variables to capture this:

  • player_forward_vector - The vector the player is facing and and headed towards
  • player_right_vector - The vector to the players right that they can strafe towards
  • player_direction - a vector combining the players forward and right vectors indicating their heading
  • player_speed - a scaler value represening movement speed
player_forward_vector = horizontal_rotation_quat * world_front_vec;
player_right_vector = horizontal_rotation_quat * world_right;
player_direction = [0,0,0] // empty vector

With those heading vectors in place we can handle the WASD inputs. Assuming we have a keydown input handler:

if(keydown == W) player_direction += player_forward
if(keydown == S) player_direction -= player_forward
if(keydown == A) player_direction -= player_right
if(keydown == D) player_direction += player_right

finally we can update the players position based on the direction and speed

player_position = player_direction * speed;

This code will update the player mesh. We also need to apply the horizontal_rotation_quat to the camera view and target offests

camera_rotation_quat = horizontal_rotation_quat
camera_front_vector = camera_rotation_quat * world_front;
view_sphere_offset = world_up_vector * up_offset + player_right_vector * right_offset;

target_distance_from_player = camera_front * distance;
camera_distance_from_player = -camera_front * distance;
camera_target_position = player_position + view_sphere_offset + target_distance_from_player;

camera_eye_position = player_position + view_sphere_offset +

Now we have the basics of a third person camera. The player can move and rotate on the horizontal axis and the camera will rotate with the player.

movement and horizontal rotation in game engine agnostic third person cameraKeyboard movement enabled

Vertical rotation and aim

Next let us handle vertical rotation. This is where I've seen gaps in many third person camera learning resources. To capture vertical aim we will create another quaternion similiar to the horizontal_rotation_quat. The new quaternion will be called vertical_rotation_quat and we will update it from the mouse Y axis movement deltas.

vertical_rotation_quat *= new_quaternion_from_rotation_y(delta_mouse_position_y * mouse_sensitivity)

combine vertical and horizontal quaternions

Now that we are capturing horizontal and vertical rotation input we will combine them in to a new quaternion we'll for the overal camera translation

camera_rotation_quat = horizontal_rotation_quat * vertical_rotation_quat;

The camera_rotation_quat is used to determine what is the cameras front direction:

camera_front = camera_rotation_quat * world_front

given the cameras front vector we can project vectors forward and back from the view_sphere_center to give us the position of the lookat and eye. We then have all the data we need to set the final lookat and eye position. This captures all expected user input: WASD movement, Mouse vertical and horizontal look movement.

movement and vertical rotation in game engine agnostic third person cameraKeyboard movement enabled, vertical, horizontal rotation

Game engine agnostic third person camera controller peusdocode

The following is a peusdocode implementation of the mechanics discussed above. It contains a for_each_frame do: section which is synonymous to a update handler in any game engine.

world_front = X_axis
world_right = Y_axis
world_up = Z_axis

player_position = [0,0,0]
player_front = world_front
player_speed = 5;

view_sphere_up_offset = 7;
view_sphere_right_offset = 2;
view_sphere_radius = 7
view_sphere_offset = player_position + world_up * view_sphere_up_offset + world_right * view_sphere_right_offset;
camera_lookat_position = view_sphere_offset + world_front * view_sphere_radius;
camera_eye_position = view_sphere_offset - world_front * view_sphere_radius;
camera_front = world_front

horizontal_rotation_quat = [0,0,0,0]
vertical_rotation_quat = [0,0,0,0]

mouse_sensitivity = 5;

for_each_frame do:
    // update rotation quaternions with mouse delta changes
    horizontal_rotation_quat *= new_quat_from_z_rotation_angle(mouse_delta_x * mouse_sensitivity)
    vertical_rotation_quat *= new_quaternion_from_rotation_y(delta_mouse_position_y * mouse_sensitivity)

    // update player forward and right vectors with new rotation
    player_forward = horizontal_rotation_quat * world_front;
    player_right = horizontal_rotation_quat * world_right;

    // set player direction based on WASD keyboard input
    player_direction = [0,0,0] // empty vector
    if(keydown == W) player_direction += player_forward
    if(keydown == S) player_direction -= player_forward
    if(keydown == A) player_direction -= player_right
    if(keydown == D) player_direction += player_right

    // update player position with new direction and speed
    player_position += player_direction * player_speed;

    //update view_sphere_offset to the new player_right vector
    view_sphere_offset = world_up * view_sphere_up_offset + player_right * view_sphere_right_offset;

    // create a camera rotation quat from the horizontal and vertical rotations
    camera_rotation_quat = horizontal_rotation_quat * vertical_rotation_quat;

    // create a camera front vector that applies the camera rotation to the world front
    camera_front = camera_rotation_quat * world_front

    // project the eye and offset out from the view sphere center by a radius
    // lookat is positive so its in front of player
    // eye is negative so it is behind player
    camera_lookat_offset = camera_front + view_sphere_radius
    camera_eye_offset = camera_front - view_sphere_radius

    // finally calculate the camera look at and eye positions
    camera_lookat_position = player_position + view_sphere_offset + camera_lookout_offset;
    camera_eye_position = player_position + view_sphere_offset + camera_eye_offset;

Additional third person camera features

This is a fairly functional third person camera implmentation but there are extra cirricular features to ad

  • clamp the vertical rotations

    The current implementation has no limit on the vertical rotation. This is a problem because the camera can easily flip over or under the player mesh. To alleviate this we would create a variable that represents the vertical euler angle rotation like camera_pitch. This pitch variable would be updated each frame with the mouse coordinates like we do with the vertical_rotation_quaternion the camera_pitch would then be clamped at max min values to prevent the flipping. The vertical_rotation_quaternion would then be generated from the pitch angle using the same new_quaternion_from_rotation_y helper function.

  • decouple the horizontal rotations

    In this current implementation the player and camera horizontal rotations are coupled and use the same horizontal_rotation_quat This coupling enforces that the player and camera are always facing the same direction. We could give the player and camera seperate horizontal rotation quaternions which would enable the camera to freely rotate the view sphere space while the player mesh could look in other directions. This camera experience is similiar to what you seein in AAA thrid person camera games like From Software titles.

  • smooth out the movment with lerps

In this current implementation we are instantly updating all our calculations for the camera position. The movement could be improved by adding some interpolation to smooth out the camera and also apply some curves to the movement to give it a smoother effect.

Summary

This camera system is my niave implementation that came togeter after random hacking. I could not get a pitch, yaw, polar coordinate implementation working. Let me know in the comments if there are more correct ways to implement this type of camera system or any improvements.

If you liked this content follow us on Twitter for more!

Comments:

Categories
UncategorizedActionAdventureArcadeBoard GameDrivingFightingMultiplayerOtherPuzzlesShootingStrategy

Instantly play your favorite free online games Play unlimited free games at RadCade.com is the best place to go if you’re searching for a variety of popular games

Policies
Privacy PolicyTerms and ConditionsDisclaimer
ContactRadCadeemail admin at radcade.com
RadCade is a Red Trench Media Corp Property