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.