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

React Three.js中3D物体Z轴位置重置失效与动画状态更新异常问题

React Three.js中3D物体Z轴位置重置失效与动画状态更新异常问题

我帮你分析一下问题的核心原因,再给出针对性的解决方案:

问题根源拆解

  1. React状态更新的异步特性
    你在调用setStartCarAnimation(false)后立刻console.log(startCarAnimation),看到的还是true,这是因为React的状态更新是异步批量处理的——当前函数作用域内的变量不会立即更新,要查看最新状态得通过监听机制。

  2. 用React State管理Three.js位置的滞后性
    你用zPosition这个State同步模型Z轴位置,但setZPosition是异步的,而useFrame是每帧执行的高频函数,这会导致模型位置和React State不同步,出现更新延迟甚至重置失效的情况。其实Three.js物体的属性可以直接操作,完全不需要通过React State中转。

  3. 重置时机的逻辑冲突
    你在useFrame里同时执行停止动画和重置位置的操作,但此时useFrame还在基于旧的startCarAnimation值运行,异步状态更新的时序问题会导致重置操作无法被正确执行。

修改后的Scene.jsx代码

import React, { useRef, useEffect } from "react";
import { PerspectiveCamera } from "@react-three/drei";
import { useFrame, useLoader } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

export default function Scene({ startCarAnimation, setStartCarAnimation }) {
  const gltf = useLoader(GLTFLoader, '../public/assets/car/scene.gltf');
  const groupRef = useRef();
  const cameraRef = useRef();
  const targetPosition = -100;

  // 直接操作Three.js物体属性,避免React State的异步延迟
  useFrame((state, delta) => {
    if (startCarAnimation) {
      // 每帧更新Z轴位置,直到触达目标值
      groupRef.current.position.z = Math.max(groupRef.current.position.z - 2, targetPosition);
      gltf.materials.tyres.map.rotation += 0.1;

      // 增加微小误差值,规避Three.js浮点精度判断问题
      if (groupRef.current.position.z <= targetPosition + 0.01) {
        setStartCarAnimation(false);
      }
    }
  });

  // 监听动画状态变化,在动画停止时安全重置位置
  useEffect(() => {
    if (!startCarAnimation) {
      groupRef.current.position.z = 0;
      console.log("动画已停止,位置已重置", startCarAnimation);
    }
  }, [startCarAnimation]);

  return (
    <>
      <PerspectiveCamera ref={cameraRef} makeDefault fov={30} position={[0, 0, 0.52]} />
      <group ref={groupRef} position={[0, -0.9, 0]} rotation={[0, Math.PI, 0]} >
        <directionalLight intensity={8} position={[0,0,1]}/>
        <ambientLight intensity={3}/>
        <primitive object={gltf.scene} />
      </group>
    </>
  );
}

关键修改说明

  • 移除了zPosition状态,直接操作groupRef.current.position.z,保证位置更新实时同步,避免异步延迟。
  • 调整目标位置判断逻辑,增加+0.01的误差值,解决Three.js中浮点精度问题导致的判断失效。
  • 用useEffect监听startCarAnimation的变化,确保重置位置的操作在动画完全停止后执行,避免时序冲突。
  • 将状态日志移到useEffect中,这样能看到最新的状态值。

备注:内容来源于stack exchange,提问作者Dimitris S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 06:18:13