How to set the camera in Babylon.js to be in third person?
I managed to create a code where the cameras follow the "tank" object. But with the mouse, you can zoom in and out of the camera. Tell me how to set up the camera so that it moves like in GTA behind the car?
Here is an example from GTA Vice City. When playing, the camera follows the car and does not move. In my case, using the mouse, you can change the camera path. How to fix it and make it like in GTA?
My code: "index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="pointerLock.js"></script>
<title> Babylon FPS</title>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script src="main.js" type="module"></script>
</body>
</html>
main.js
window.addEventListener('DOMContentLoaded', function(){
// get the canvas DOM element
var canvas = document.getElementById('renderCanvas');
// load the 3D engine
var engine = new BABYLON.Engine(canvas, true);
var createFollowCamera = function(scene,canvas,target){
var camera = new BABYLON.FollowCamera("tankFollowCamera",new BABYLON.Vector3(10,0,10), scene);
camera.heightOffset= 2;
camera.rotationOffset = 180;
camera.cameraAcceleration = .1;
camera.maxCameraSpeed = 1;
camera.lockedTarget = target;
camera.attachControl(canvas, true);
return camera;
}
// createScene function that creates and return the scene
var createScene = function () {
var scene = new BABYLON.Scene(engine);
var sun = new BABYLON.PointLight("Omni0", new BABYLON.Vector3(60, 100, 10), scene);
// Ground
var ground = BABYLON.Mesh.CreateGroundFromHeightMap("ground", "https://www.babylonjs-playground.com/textures/heightMap.png", 200, 200, 100, 0, 10, scene, false);
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.diffuseTexture = new BABYLON.Texture("https://www.babylonjs-playground.com/textures/grass.png", scene);
groundMaterial.diffuseTexture.uScale = 6;
groundMaterial.diffuseTexture.vScale = 6;
groundMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
ground.position.y = -2.05;
ground.material = groundMaterial;
// Skybox
var skybox = BABYLON.Mesh.CreateBox("skyBox", 1000.0, scene);
var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("https://www.babylonjs-playground.com/textures/TropicalSunnyDay", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.disableLighting = true;
skybox.material = skyboxMaterial;
var tank = new BABYLON.MeshBuilder.CreateBox("tank",{height:.5, depth:1, width:1},scene);
var tankMaterial = new BABYLON.StandardMaterial("tankMaterial",scene);
tankMaterial.diffuseColor = new BABYLON.Color3(1,0,5);
tank.material = tankMaterial
tank.position.y = 5;
tank.speed = 1;
tank.frontVector = new BABYLON.Vector3(0,0,1);
//var camera =
createFollowCamera(scene,canvas,tank);
console.log(tank.move);
//set up input map
var inputMap = {};
scene.actionManager = new BABYLON.ActionManager(scene);
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyDownTrigger, function (evt) {
inputMap[evt.sourceEvent.key] = evt.sourceEvent.type == "keydown";
}));
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, function (evt) {
inputMap[evt.sourceEvent.key] = evt.sourceEvent.type == "keydown";
}));
scene.onBeforeRenderObservable.add(function(){
if(tank){
if(inputMap["w"] || inputMap["ArrowUp"]){
tank.moveWithCollisions(tank.frontVector.multiplyByFloats(tank.speed,tank.speed,tank.speed));
}
if(inputMap["a"] || inputMap["ArrowLeft"]){
tank.rotation.y -= .1;
tank.frontVector = new BABYLON.Vector3(Math.sin(tank.rotation.y),0,Math.cos(tank.rotation.y));
}
if(inputMap["s"] || inputMap["ArrowDown"]){
tank.moveWithCollisions(tank.frontVector.multiplyByFloats(-tank.speed,-tank.speed,-tank.speed));
}
if(inputMap["d"] || inputMap["ArrowRight"]){
tank.rotation.y += .1;
tank.frontVector = new BABYLON.Vector3(Math.sin(tank.rotation.y),0,Math.cos(tank.rotation.y));
}
}
})
return scene;
};
// call the createScene function
var scene = createScene();
createPointerLock(scene);
// run the render loop
engine.runRenderLoop(function(){
scene.render();
});
// the canvas/window resize event handler
window.addEventListener('resize', function(){
engine.resize();
});
});
link to https://codepen.io/Smith37/pen/OJxdmaw
Solution 1:
You need to remove Babylon's default camera pointer input handling. You could remove all camera input handling:
camera.inputs.clear();
Or remove just the pointer handling:
-
ArcRotateCamera
camera.inputs.removeByType('ArcRotateCameraPointersInput');
-
FollowCamera
camera.inputs.removeByType('FollowCameraPointersInput');
Example:
- https://codepen.io/kaliatech/pen/GROOZeZ
More info:
- https://doc.babylonjs.com/divingDeeper/cameras/customizingCameraInputs
- https://github.com/BabylonJS/Babylon.js/tree/master/src/Cameras/Inputs