简体   繁体   中英

React Native Rendering with SetInterval Issue

I've just stumbled upon a performance issue with my app. I'm trying to make a game loop, with a setInterval() function and re-rendering my game constantly with this.forceUpdate() . I've also tried using this.setState() to re-render but they all feel the same. Now, in my gameloop, I'm constantly updating the y position of a blue square (View). It move's but it's a bit laggy.

I set the interval of the setInterval() function to 1000/60 to simulate 60FPS, but in my app, it feels like 20. I've also tried setting the interval to 1, and it's smooth, but it stutters a lot. I get tiny lag spikes that are very disorientating.

I don't think this.forceUpdate() or this.setState() is right in my scenario.

Is there another way I could do this to make the performance better?

UPDATE: I have used the requestAnimationFrame() function as well but it still stutters on re-render. Is there an alternative to this.forceUpdate() or this.setState() ? And how would I delay the requestAnimationFrame() loop so it goes off at 60FPS?

Thanks for reading and I hope we find a solution.

If you're adamant that requestAnimationFrame is not a good fit for your app/game loop, I would suggest using setTimeout over setInterval . The reason is, if a loop iteration takes longer than 16ms (1000/60) to execute, then you'll get iteration overlap - another iteration will start, even if the prior hasn't completed. Over time, this will cause real problems and can be a cause of stuttering.

As an alternative, try the following (pseudo code):

doLoopIteration = () => {

    this.setState({ /* your mutation */ }, 
    () => { // This callback is fired after a component render caused by setState

        // Sechule next loop iteration in ~16ms. This approach protects
        // against the overlap issue mentioned above
        setTimeout(() => this.doLoopIteration(), 1000 / 60);
    })        
}

// Start the iteration
doLoopIteration()

For more on the setState callback, see this documentation . Also, see this documentation for details on the overlap problem that setInterval based loops are sensitive to. Hope that helps!

Okay i think i've managed to make a frankenstein code from your guys's suggestions. Here it is.

  componentDidUpdate() {
    setTimeout(() => {
      requestAnimationFrame(this.loop);
    }, 1000/60);
  }

  loop = () => {
    this.forceUpdate();
  }

I've noticed that the performance was actually better then all other methods i've tried. I think it's the setInterval/forceUpdate thats too heavy. Is there another method of re-rendering my app/game? Perhaps bypassing re-render functions?

If anyone wants to know, you really shouldn't be doing game code within react-native's state. Instead, write your game code outside of react-native. Example, react-native-canvas can graphically draw things without state!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM