Controlling the perspective of a player in your game is critical for making a fun and enjoyable experience specific to how you want your game to play and feel.
To do this, the HYTOPIA SDK allows you to control the Camera. In game development, a camera is the perspective that a player sees the world from.
HYTOPIA's camera controls expose everything you need to do things like first person perspective, over the shoulder camera perspectives, lock on targeting effects, cinematic panning and camera movement for cutscenes, spectating, field of view control over time for speed effects, and so much more.
Accessing A Player Camera
Player cameras exist for all Player object. You can access their PlayerCamera as follow.
player.camera // returns an instance of the PlayerCamera for the specific player.
Camera Mode (First & Third Person)
The camera currently supports 2 modes. First person, and third person. These modes effect how the players mouse movements control the camera, as well as the relative perspective of the camera.
The camera mode defaults to third person.
Like all other camera properties, you can change the camera mode of a player at any place in your game logic.
All camera interactions are done through an automatically created PlayerCamera class instance assigned to a Player instance. We can access this the moment a player joins a game, or use it at any point in our game logic.
Let's do a quick example showing how we can create a first person perspective for our game with the default player model.
startServer(world => {// Other game setup code..// Notice we're setting the camera for players immediately// when they join, but we can use player.camera anywhere// in our game logic. Also notice that player.camera is// specific to each player, this allows us to control// the camera of each player independently.world.onPlayerJoin= player => {constplayerEntity=newPlayerEntity({ // Create an entity our newly joined player controls player, name:'Player', modelUri:'models/player.gltf', modelLoopedAnimations: [ 'idle' ], modelScale:0.5, });// Setup a first person camera for the player// set first person modeplayer.camera.setMode(PlayerCameraMode.FIRST_PERSON); // shift camrea up on Y axis so we see from "head" perspective.player.camera.setOffset({ x:0, y:0.4, z:0 }); // hide the head node from the model so we don't see it in the camera, this is just hidden for the controlling player.
player.camera.setHiddenModelNodes([ 'head','neck' ]); // Shift the camera forward so we are looking slightly in front of where the player is looking.player.camera.setForwardOffset(0.3); // Spawn the player entityplayerEntity.spawn(world, { x:0, y:3, z:0 ); }// Other game setup code...});
Camera Attachment & Tracking
You can control the origin from which a player's camera sees by changing the entity or position it's attached to. By default, when a player join's a game, if they have a player entity created for them, their camera will automatically attach to their player entity.
You can also make a player camera automatically track another entity or a fixed position as well. Attachments and tracking used independently or together allow you to create a number of camera perspectives for different game types and situations.
Here's an example of how we can attach our player's camera to a cow entity we've created in our game, and have the camera always track and look towards our player entity that we control.
startServer(world => {// .. other game setupconstcow=newEntity({ modelUri:'models/cow.gltf', modelLoopedAnimations: [ 'idle' ], modelScale:0.5, rigidBodyOptions: { // manually setting the cow collider shape type:RigidBodyType.DYNAMIC, enabledRotations: { x:false, y:true, z:false }, colliders: [ { shape:ColliderShape.BLOCK, halfExtents: { x:0.3, y:0.45, z:0.5 }, }, ], }, });cow.spawn(world, { x:2, y:3, z:6 });world.onPlayerJoin= player => {constplayerEntity=newPlayerEntity({ player, name:'Player', modelUri:'models/player.gltf', modelLoopedAnimations: [ 'idle' ], modelScale:0.5, });playerEntity.spawn(world, { x:0, y:10, z:0 });// all camera properties, including attachments// and tracking can be changed anywhere in your game logic// at game runtime!player.camera.setAttachedToEntity(cow);player.camera.setTrackedEntity(playerEntity); };// .. rest of our game setup}
This results in the following camera & perspective effect for the player.
Camera Offsets
In different camera modes, you may need to offset the positioning of a camera relative to the entity or position it's attached to. Such as in a first person perspective where the camera should be placed where the "head" of the player's entity would be. Here's how we can control camera offset.
// Change the offset relative to the attached// entity or position of the camera.// The offset is applied relative to the // internally calculated origin point the camera// attached to for the entity, or position.player.camera.setOffset({ x:0, y:1, z:0 }); // Change the forward offset of the camera.// This is only supported in first person mode.// A positive number move the camera towards // what would be the "face" of a player perspective,// and a negative value shifts the camera towards the// "back of the head" of a player perspective.player.camera.setForwardOffset(0.3);// Change the film offset. This shifts the camera// perspective left or right relative to its // attachment. You can use this to achieve// an over the shoulder effect in third-person// for a fortnite like third-person perspective,// or use it for a variety of other uses like// cinematics. A positive value shifts the camera// right, a negative value shifts it left.// The client will smoothly interpolate changes// to this.player.camera.setFilmOffset(5);
Camera Perspective Effects
You can fully control common perspective effects of the camera. These include field of view (FOV) and zoom. Both of these are smoothly interpolated by the client anytime you change them, allowing you to create smooth fov and zoom related effects. For example, you can progressively set zoom over the course of 1 second of time to create a smooth "scope-zoom" effect in a shooter game.
Here's some example usage of these effects
// Change the player's FOV to 90,// giving a wider field of view.// Default is a FOV of 75.player.camera.setFov(90);// Change the player's zoom giving// a more zoomed in perspective// relative to the camera's attachment point// Default is a Zoom of 2player.camera.setZoom(2)// Increase FOV every 100ms,// creating a warp speed// visual effectsetInterval(() => {constcurrentFov=player.camera.fov;if (currentFov <150) {player.camera.setFov(currentFov +1); }},100)
Hiding Attached Entity Model Parts
In first person mode, it's very common that you'll want your player's camera perspective to be from the position of where they player model's head would be. But what do you do about the head part of the model being in the way?...
Easy, our camera allows us to hide specific parts (model nodes) of the entity the camera is attached to, and they are only hidden for our player's camera perspective and not other players.
We can also hide model nodes in third person if needed, but it's less common.
Here's an example of how to hide model nodes. For this case, we'll hide our head for our player's camera.
// We can pass an array of substrings to// setHiddenModelNodes() to hide any named // node in the .gltf model for the entity // our camera is attached to that matches// a substring.//// For example, if a node is named head_eyes,// a substring of 'head' would match it.// Any node with 'head' anywhere in its name// will be hidden.player.camera.setHiddenModelNodes([ 'head' ]);
If there are features that we don't currently support for PlayerCamera that you'd like to see added to the HYTOPIA SDK, you can submit a feature request here.