上节实现了加速、减速、后退:

这节来做下镜头跟随。
玩游戏的时候,镜头都是跟着人物走的:

那如何实现这种跟随效果呢?
其实就是把相机放到人物后方,人物动的时候,他跟着一起动。
那是不是放到一个 group 里就好了?
可以的,相机其实也是一个对象 Object3D

它当然可以加到场景里。
我们去掉 OrbitControls:

不再通过鼠标控制相机。
模型本身就在一个 group 里,把相机加到这里面就行:

这样:

camera.position.y = 300;
camera.position.z = 200;
camera.lookAt(0, 150, 0);
mesh.add(camera);
把相机加到 group 里,调整下位置和 lookAt。
试一下:

可以看到,相机跟着人物走了。
现在可能不明显,我们加一个 GridHelper。

const gridHelper = new THREE.GridHelper(10000, 500, 'orange', 'blue');
scene.add(gridHelper);
去掉 AxesHelper 加一个 GridHelper
再试一下:


可以看到,不管是前进、后退,镜头都会在人物后方固定的位置。
然后现在速度为 0 的时候应该切换为静止的动画,不然动画是在走,但是位置不变有点怪怪的。
之前讲过如何实现骨骼动画之间的丝滑切换:
先安装下 gsap
pnpm install --save gsap
导出切换动画的方法:

let changeAction;
export {
changeAction
}
const walkAction = mixer.clipAction(gltf.animations[3]);
walkAction.play();
const idleAction = mixer.clipAction(gltf.animations[0]);
idleAction.play();
walkAction.weight = 0;
idleAction.weight = 1;
changeAction = (toIdle) => {
if(toIdle) {
let obj = {
w: 0
}
gsap .to(obj, {
w: 1,
duration: 2,
ease: 'none',
repeat: 0,
onUpdate() {
idleAction.weight = obj.w;
walkAction.weight = 1- obj.w;
}
});
} else {
let obj = {
w: 0
}
gsap .to(obj, {
w: 1,
duration: 2,
ease: 'none',
repeat: 0,
onUpdate() {
walkAction.weight = obj.w;
idleAction.weight = 1- obj.w;
}
});
}
}
就是传入 bool 值,分别把两个动画的 weight 从 0 到 1,从 1 到 0 ,实现丝滑的动画切换。
用一下试试:
首先,松开 w、s 键之后,大概减速一段时间就会静止,我们松开 2s 后切换动画到静止:

setTimeout(() => {
changeAction?.(true);
}, 2000);
然后按下的时候切换到走路动画,这里要加个 flag,只调用一次:

let flag = false;
if(!flag) {
changeAction?.(false);
}
flag = true;
if(!flag) {
changeAction?.(false);
}
flag = true;
没按下的话把 flag 设为 false:

else {
flag = false;
}
这段逻辑写在 keyup 里也行。
试下效果:
首先,最开始是静止动画,然后按下 w 逐渐切换到走路动画:

松开后,慢慢切换到静止动画:

按住 s 往后运动也是一样:


这样,镜头的跟随,动画的切换就都完成了。
案例代码上传了小册仓库
总结
这节我们实现了镜头跟随的效果,并且完成了静止到走路,走路到静止的丝滑动画切换。
相机可以添加到 group 里,跟随模型一起动,这样视角会随着模型的移动而切换。
然后用 weight + gsap 实现了骨骼动画的丝滑切换。
现在还不能切换方向,下节加上通过鼠标切换方向的功能。