From c0e7567849b08d51a9d8a3311fba2b7cb3238aea Mon Sep 17 00:00:00 2001 From: Tom Boullay Date: Tue, 2 Jun 2026 23:36:13 +0200 Subject: [PATCH] fix(ebike): hide interact prompt while actively riding the bike While the player is mounted on the e-bike and pressing a movement key, the persistent 'Descendre du bike' prompt was visible on screen and polluted the view during gameplay. The InteractableObject is now unmounted as soon as window.ebikeDriveInputActive flips to true and remounted the moment the bike comes to a stop. The driving signal is read in a useFrame and only flips React state on transitions, so this adds zero per-frame re-renders. --- src/components/ebike/Ebike.tsx | 47 ++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/components/ebike/Ebike.tsx b/src/components/ebike/Ebike.tsx index a0fdf03..7a86bdf 100644 --- a/src/components/ebike/Ebike.tsx +++ b/src/components/ebike/Ebike.tsx @@ -358,6 +358,19 @@ export function Ebike({ ? "Monter sur le bike" : "Descendre du bike"; + // Hide the interact prompt while the player is actively riding the bike + // (driving input pressed) so the "Descendre du bike" label doesn't + // pollute the view. The prompt comes back the moment the bike comes to + // a stop. window.ebikeDriveInputActive is published every frame by + // PlayerController based on whether a movement key is currently held. + const [isEbikeDriving, setIsEbikeDriving] = useState(false); + useFrame(() => { + const driving = + movementMode === "ebike" && window.ebikeDriveInputActive === true; + if (driving !== isEbikeDriving) setIsEbikeDriving(driving); + }); + const showInteractPrompt = !isEbikeDriving; + const handleInteract = useCallback((): void => { if (window.ebikeBreakdownActive === true) return; @@ -465,22 +478,24 @@ export function Ebike({ {/* radius 20 → ~7 unités monde (scale 0.35). Sphère omnidirectionnelle pour que le raycast fonctionne quelle que soit l'orientation de la caméra (montée ou à pied). */} - - - - - - + {showInteractPrompt ? ( + + + + + + + ) : null} {/* GPS + Speedmeter – same group so they are perfectly co-localised. GPS: full circle (Fresnel mask), renderOrder 10 000