2

I am trying to animate this group of trees inside component. But the treeRefs keeps on increasing by 2 times on each frame and results in very wonky behaviour filled with glitches. Logic - I have components which is a 3D Mesh. I am spwaning these trees on a random position and moving them along z-axis and when the mesh hits z = 0 I change it's position around some starting point. This way trees should simulate moving animation. I am using useRef to keep track of each component and animate it's position. Also I have ScrollControls wrapped around and when I scroll this animation starts acting weird and useRefs starts to multiplying. Example logs before scroll enter image description here

Example logs after scroll enter image description here

import { Detailed, useGLTF } from '@react-three/drei';
import { useFrame } from '@react-three/fiber';
import React, { createRef, useEffect, useMemo, useRef, useState } from 'react';
import { useStore } from './store/store';

function map_range(value, low1, high1, low2, high2) {
    return low2 + ((high2 - low2) * (value - low1)) / (high1 - low1);
}

export const Forest = () => {
    const treeRefs = useRef([]);
    const [positions, setPositions] = useState([]);
    const { acceleration, setAcceleration, currentAction, setCurrentAction } = useStore();

    // Move each tree towards starting when reaches the end line
    useFrame((state, delta) => {
        console.log('Delta', delta);
        console.log('Length ', treeRefs?.current?.length);
        console.log('Length Pos ', positions?.length);
        treeRefs?.current?.map((TreeMesh) => {
            // console.log('TreeMesh', TreeMesh.position.z);

            if (TreeMesh?.position?.z) {
                // console.log('Inside useFrame ', currentAction);
                TreeMesh.position.z = TreeMesh.position.z - delta;
                if (TreeMesh.position.z <= 0) {
                    TreeMesh.position.z = Math.random() * 50;
                }
            }
            return TreeMesh;
        });
    });

    useEffect(() => {
        // Create 30 objects with random position and rotation data
        const positions = [...Array(30)].map(() => {
            const randomPositionAmplitude = map_range(Math.random(), 0, 1, 2, 10);

            const randomPositionDirection = Math.sign(map_range(Math.random(), 0, 1, -1, 1));

            const xPosition = randomPositionAmplitude * randomPositionDirection;

            return {
                position: [xPosition, 1.7, Math.random() * 50],
                // rotation: [Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, Math.random() * Math.PI * 2],
                rotation: [0, 0, 0],
                ref: createRef(),
            };
        });
        setPositions(positions);
    }, []);

    return (
        <>
            {positions.map((props, i) => (
                <Tree innerRef={(el) => treeRefs.current.push(el)} key={i} {...props} />
            ))}
        </>
    );
};

function Tree({ innerRef, ...props }) {
    // This will load 4 GLTF in parallel using React Suspense

    const { nodes, materials, animations, scene } = useGLTF('/Tree.glb');
    const copiedScene = useMemo(() => scene.clone(), [scene]);
    // By the time we're here these GLTFs exist, they're loaded
    // There are 800 instances of this component, but the GLTF data is cached and will be re-used ootb
    return (
        <Detailed ref={innerRef} distances={[300]} {...props}>
            {/* All we need to do is dump them into the Detailed component and define some distances
          Since we use a JSX mesh to represent each bust the geometry is being re-used w/o cloning */}

            <primitive object={copiedScene} />

            {/* <group /> */}
        </Detailed>
    );
}

What can be done to fix this?

Not sure what to try, I have other workarounds for this. But I want to know what's wrong with my code.

0 Answers0