You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Three Fiber中不使用lookAt()实现相机动画?

解决React Three Fiber相机动画弹跳问题

问题根源

你遇到的弹跳现象,是因为相机位置通过lerp平滑过渡,但lookAt的目标点是突然切换的(从模型原位置直接跳到Z+2的位置)。相机每帧都要朝向一个突变的目标,导致朝向动画与位置动画不同步,产生抖动弹跳。

解决方案

让相机的朝向目标点也跟着平滑过渡,和相机位置的动画速率保持一致,确保位置和朝向的动画同步执行。

修改后的代码

import { useAnimations, useGLTF } from '@react-three/drei'
import { useEffect, useRef } from 'react'
import { useControls, button} from 'leva'
import { useFrame } from '@react-three/fiber'
import { Vector3 } from 'three'

export default function Character ({isContact}) {
    const character = useGLTF('./model.gltf')
    const { actions } = useAnimations(character.animations, character.scene)
    
    const markerRef = useRef()
    const cameraPos = new Vector3()
    // 定义两种状态下的朝向目标点
    const targetContact = new Vector3()
    const targetDefault = new Vector3()
    // 用于平滑过渡的当前朝向目标
    const currentTarget = useRef(new Vector3())
    
    // 初始化目标点(模型位置固定时只需执行一次)
    useEffect(() => {
        if (!markerRef.current) return
        const pos = markerRef.current.position
        // 联系状态下的朝向目标(Z轴偏移+2)
        targetContact.set(pos.x, pos.y + 1, pos.z + 2)
        // 默认状态下的朝向目标
        targetDefault.set(pos.x, pos.y + 1, pos.z)
        // 初始朝向默认目标
        currentTarget.current.copy(targetDefault)
    }, [])
    
    useFrame((state) => {
        if (isContact) {
            // 平滑过渡相机位置到联系状态
            cameraPos.set(-4, 0, 0)
            // 平滑过渡朝向目标到联系状态的点
            currentTarget.current.lerp(targetContact, 0.01)
        } else {
            // 平滑过渡相机位置到默认状态
            cameraPos.set(-3, 1.5, 4)
            // 平滑过渡朝向目标到默认状态的点
            currentTarget.current.lerp(targetDefault, 0.01)
        }
        // 更新相机位置
        state.camera.position.lerp(cameraPos, 0.01)
        // 朝向平滑过渡后的目标点
        state.camera.lookAt(currentTarget.current)
        
        // 注意:updateProjectionMatrix 仅在修改相机投影参数(如fov、aspect)时需要,此处可移除
    })
    
    return (
        <primitive 
            object={character.scene}
            position-y={-1.2}
            ref={markerRef}
        />
    )
}

关键修改点

  1. 分离目标点与位置动画:定义两种状态的朝向目标点,并用currentTarget作为中间变量实现平滑过渡,避免目标点突变。
  2. 同步动画速率:相机位置和朝向目标的lerp使用相同的速率(0.01),确保两者动画同步。
  3. 移除不必要的updateProjectionMatrix:仅当相机的投影参数(如视野、宽高比)变化时才需要调用该方法,移动位置/朝向时不需要。

内容的提问来源于stack exchange,提问作者lorenzoajt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:45:36