Harmonizing speed of runner game on all device / cap FPS

Hi guys,

I made this little project for my personal purpose.
https://gitlab.com/Vincent789/portfolio
portfolio-rho-five-31.vercel.app
It uses react-three-fiber.

My animations don’t look the same on all devices as I can go up to 190-200 fps with my gaming laptop and maybe 50-60 fps with my Mac (retina 2013) and my family’s laptop that isn’t really powerful.

So I thought (maybe I’ve missed something important here) that it would be a great idea to cap framerate in order to harmonize all the users experiences.

I used this solution here that works like a charm (really) on all browsers but Chrome :
https://github.com/pmndrs/react-three-fiber/discussions/667

More precisely this part :

function FPSLimiter() {
    const set = useThree((state) => state.set);
    const get = useThree((state) => state.get);
    const advance = useThree((state) => state.advance);
    const frameloop = useThree((state) => state.frameloop);
    
    useLayoutEffect(() => {
        const initFrameloop = get().frameloop;

        return () => {
            set({ frameloop: initFrameloop });
        };
    }, []);

    useFrame((state) => {
        if (state.get().blocked) return;
        state.set({ blocked: true });

        setTimeout(() => {
            state.set({ blocked: false });

            state.advance();
        }, Math.max(0, 1000 / 60 - state.clock.getDelta()));
    });

    useEffect(() => {
        if (frameloop !== 'never') {
            set({ frameloop: 'never' });
            advance();
        }
    }, [frameloop]);

    return null;
}

That can be imported in the canvas and does its job… but brings a quite unpleasant issue.
The canvas loads but not the objects… in it unless :

  • I change browser tab and go back
  • I update (one way or another) the canvas (which i tried to do but it seems to me that this solution is not … the one)
  • I disable the preloader (if the scene is not hidden at the beginning, it works… but the preloader aims to hide the little loading time so it’s not very useful)

See here : http://artisons.fr/

So i’m stuck to this choice : either I do not cap the framerate and my runner game goes faster than flash on powerful computers (and goes as it wants to go on other devices), or I use the frameLimiter above and my scene won’t show when needed.

So my questions are :

  • How to harmonize the speed of my runner game on devices ?
  • Is it a good idea to cap the FPS ?
  • Why does the above solution messes things up ?

Again, using the above solution does a perfect (visual at list) job and allows to control the speed on very different (age and specs) devices… preloader’s case appart.

Thanks a lot guys.
Have a nice day !

can you delay using the frame limiter until everything has been running for a while?

1 Like

Hum no it’s quite complicated as the speed loop will be very fast during introduction and adjust after Time (it will look like a Time lapse with the helicopter not going at the same speed)… Unless I remove it. It seems to me it’s not a good solution. But yes i could activate the limiter when scene objects are displayed I think.

Ok I tried what you said. It did the trick :

{introCompleted ? (
    <FPSLimiter/>
):null}

Updated :
http://artisons.fr/

I’m eager to learn another way to do this (it seems it uses more ressources + a small lag effect) if someone knows ! Thanks for your answer !