import { useLayoutEffect, useRef } from "react"; import type { RefObject } from "react"; import type { Group } from "three"; type ActorPosition = readonly [number, number, number]; type CompletePreviousTickPositionOptions = { groupRef: RefObject; tick: number; target: ActorPosition; }; const SETTLED_DISTANCE = 0.025; export function useCompletePreviousTickPosition({ groupRef, tick, target, }: CompletePreviousTickPositionOptions) { const previousTickRef = useRef(tick); const previousTargetRef = useRef(target); useLayoutEffect(() => { const group = groupRef.current; const previousTarget = previousTargetRef.current; if (group && tick !== previousTickRef.current && !isAtPosition(group, previousTarget)) { group.position.set(previousTarget[0], previousTarget[1], previousTarget[2]); } previousTickRef.current = tick; previousTargetRef.current = target; }, [groupRef, target, tick]); } function isAtPosition(group: Group, target: ActorPosition): boolean { return ( Math.abs(group.position.y - target[1]) <= SETTLED_DISTANCE && Math.hypot(group.position.x - target[0], group.position.z - target[2]) <= SETTLED_DISTANCE ); }