如何在Three.js中动画真实的translateZ属性(适配GSAP)
解决Three.js中基于局部坐标系的translateZ动画问题
你之前的代码问题在于直接修改世界坐标的Z值,导致移动方向依赖世界坐标系而非对象自身局部坐标系。以下是两种可行的解决方案,均基于GSAP实现符合需求的击退动画:
方案一:转换局部位移为世界目标位置
先计算对象沿自身局部Z轴向后移动10单位后的世界坐标,再用GSAP平滑动画到该位置:
// 执行你已有的旋转逻辑,让玩家转向敌人反方向 const dirToPlayer = this._FindPlayer(); const controlObject = object; const _R = controlObject.quaternion.clone(); const m = new THREE.Matrix4(); m.lookAt( new THREE.Vector3(0, 0, 0), dirToPlayer.negate(), new THREE.Vector3(0, 1, 0) ); _R.setFromRotationMatrix(m); controlObject.quaternion.copy(_R); // 计算局部坐标系下向后偏移的世界目标位置 const localBackOffset = new THREE.Vector3(0, 0, -10); // 局部Z负方向对应自身后方 const targetPosition = localBackOffset.clone(); controlObject.localToWorld(targetPosition); // 将局部偏移转换为世界坐标 // GSAP动画到目标位置 gsap.to(controlObject.position, { x: targetPosition.x, y: targetPosition.y, z: targetPosition.z, duration: 0.6, ease: "power2.out" // 添加缓动让击退动作更自然 });
方案二:动画进度值+实时调用translateZ
通过GSAP动画一个自定义进度变量,在每帧更新时调用Three.js的translateZ方法,完全模拟无动画版本的局部移动逻辑:
// 执行旋转逻辑 const dirToPlayer = this._FindPlayer(); const controlObject = object; const _R = controlObject.quaternion.clone(); const m = new THREE.Matrix4(); m.lookAt( new THREE.Vector3(0, 0, 0), dirToPlayer.negate(), new THREE.Vector3(0, 1, 0) ); _R.setFromRotationMatrix(m); controlObject.quaternion.copy(_R); // 记录初始位置,避免位移累加错误 const startPosition = controlObject.position.clone(); // 动画自定义进度值 gsap.to({ progress: 0 }, { progress: 1, duration: 0.6, onUpdate: function() { const currentProgress = this.targets()[0].progress; // 重置到初始位置后,按进度沿局部Z轴向后移动 controlObject.position.copy(startPosition); controlObject.translateZ(-10 * currentProgress); }, ease: "power2.out" });
两种方案对比
- 方案一仅需一次坐标转换,动画性能更优,适合旋转状态固定的场景(你的需求刚好符合)。
- 方案二直接复用Three.js的局部移动逻辑,更直观,若后续需要在动画过程中调整对象旋转,该方案更灵活。
内容的提问来源于stack exchange,提问作者user3112634
相关产品推荐
相关产品推荐

