Skip to content

194. 玩家漫游(三)

Published:

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

2025-09-21 12.03.16.gif

这节来做下镜头跟随。

玩游戏的时候,镜头都是跟着人物走的:

image.png

那如何实现这种跟随效果呢?

其实就是把相机放到人物后方,人物动的时候,他跟着一起动。

那是不是放到一个 group 里就好了?

可以的,相机其实也是一个对象 Object3D

image.png

它当然可以加到场景里。

我们去掉 OrbitControls:

image.png

不再通过鼠标控制相机。

模型本身就在一个 group 里,把相机加到这里面就行:

image.png

这样:

image.png

camera.position.y = 300;
camera.position.z = 200;
camera.lookAt(0, 150, 0);

mesh.add(camera);

把相机加到 group 里,调整下位置和 lookAt。

试一下:

2025-09-21 16.08.22.gif

可以看到,相机跟着人物走了。

现在可能不明显,我们加一个 GridHelper。

image.png

const gridHelper = new THREE.GridHelper(10000, 500, 'orange', 'blue');
scene.add(gridHelper);

去掉 AxesHelper 加一个 GridHelper

再试一下:

2025-09-21 16.14.22.gif

2025-09-21 16.15.06.gif

可以看到,不管是前进、后退,镜头都会在人物后方固定的位置。

然后现在速度为 0 的时候应该切换为静止的动画,不然动画是在走,但是位置不变有点怪怪的。

之前讲过如何实现骨骼动画之间的丝滑切换:

先安装下 gsap

pnpm install --save gsap

导出切换动画的方法:

image.png

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 后切换动画到静止:

image.png

setTimeout(() => {
    changeAction?.(true);
}, 2000);

然后按下的时候切换到走路动画,这里要加个 flag,只调用一次:

image.png

let flag = false;
if(!flag) {
  changeAction?.(false);
}
flag = true;
if(!flag) {
  changeAction?.(false);
}
flag = true;

没按下的话把 flag 设为 false:

image.png

else {
    flag = false;
}

这段逻辑写在 keyup 里也行。

试下效果:

首先,最开始是静止动画,然后按下 w 逐渐切换到走路动画:

2025-09-21 16.55.07.gif

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

2025-09-21 16.57.27.gif

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

2025-09-21 16.58.33.gif

2025-09-21 16.58.58.gif

这样,镜头的跟随,动画的切换就都完成了。

案例代码上传了小册仓库

总结

这节我们实现了镜头跟随的效果,并且完成了静止到走路,走路到静止的丝滑动画切换。

相机可以添加到 group 里,跟随模型一起动,这样视角会随着模型的移动而切换。

然后用 weight + gsap 实现了骨骼动画的丝滑切换。

现在还不能切换方向,下节加上通过鼠标切换方向的功能。

评论