Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FPS issues #68

Open
gokadi opened this issue Feb 15, 2022 · 9 comments
Open

FPS issues #68

gokadi opened this issue Feb 15, 2022 · 9 comments

Comments

@gokadi
Copy link

gokadi commented Feb 15, 2022

Hi!
Currently I’m trying to figure out the reasons of FPS drop in my game, so here I got several questions about it.

  • I know that GameEngine handles update itself - I never call setState in components by myself. Also I strictly follow ECS pattern here. But for some cases I really need to use timers and intervals, like SpawnEnemiesSystem (in terms of ECS). I know that I can do a workaround and just pass a flag to the system from onUpdate callback, but it violates ECS pattern. So, here is question 1: can intervals affect FPS? (I have about 5 in my code currently).
  • There are lots of animations in my game. Some of them are implemented using React Native Animated api (for simple staff like fade in/out), but for complex animations I made custom react component, where I just replace sprites, also using timeout (to simulate animation fps). Can this be a reason?
    In this game sometimes I have about 100 entities on the screen, half of which may be animated either way and FPS becomes 1 :-(.
    I tried to investigate this issue, but didn’t succed yet.
@bberak
Copy link
Owner

bberak commented Feb 15, 2022

Hi @gokadi,

I've never used the GameEngine to render 100 entities on the screen, but I suspect that this is the main cause for your horrible FPS. Unfortunately, I don't think there is an easy fix here.

Have you tried using PureComponent or React.memo to optimize your entity rendering? That might help, but probably not to an acceptable level.

I know that I can do a workaround and just pass a flag to the system from onUpdate callback, but it violates ECS pattern.

Not sure exactly what you meant by this 👆. You can try remove the timers and intervals completely to see what affect it has on your FPS. If there is an improvement, you should be able to refactor-out the timers and intervals because your systems are provided with timing information that you should be able to use to drive spawning etc without the need for timers and callbacks.

Also, is the horrible FPS on iOS, Android or both? In my experience, Android performs worse than iOS from my experience.

@gokadi
Copy link
Author

gokadi commented Feb 16, 2022

Hi @bberak ! Thanks for quick response.

Related to PureComponent - as I got it, "shouldComponentUpdate" is the only difference from React.Component. But scenes with fps issues in my app mostly have only dynamic components, like enemies are always in motion and main hero is also almost always in motion, so I guess this doesn't fit my needs.
Also, React.memo doesn't fit it due to the same reason - almost nothing is static.
But still, I'll use these 2 options for other scenes like menus for the game, where components are rendered once.

You can try remove the timers and intervals completely to see what affect it has on your FPS.

Unfortunately it cannot be very clear experiment, because enemies' shooting is made using interval. So, if I remove this interval, amount of entities on the screen would strongly decrease.

because your systems are provided with timing information that you should be able to use to drive spawning etc without the need for timers and callbacks

Thanks for the advice, probably this will help. I'll try to modify some parts of code to rely on system's time from args.

Also, is the horrible FPS on iOS, Android or both? In my experience, Android performs worse than iOS from my experience.

Well, actually on both. But some old android simulators start loosing FPS much earlier. For example, on android 6 I see fps loss even in the main menu, where there are about 10 entities only.

@gokadi
Copy link
Author

gokadi commented Feb 16, 2022

I've never used the GameEngine to render 100 entities on the screen, but I suspect that this is the main cause for your horrible FPS. Unfortunately, I don't think there is an easy fix here.

Did you or someone else performed tests to collect any statistics about this? Or probably you know something cloe to this statistics for React Native itself?
The game genre is something close to "bullet hell", so big amount of entities on the screen is something that we really need to support :-(

@bberak
Copy link
Owner

bberak commented Feb 19, 2022

Hey @gokadi,

I was playing around with particle systems using React Native and found the FPS dropped horrible when I had about 30-60 basic particles on the screen. This was on older hardware - but your audience might not be running the latest and greatest devices either.

If you change the renderer out to something like GLView, you will probably get better performance - but this will require some effort on your part.

However, if your project is commercial in nature, I would probably avoid React Native (for the time being) for your "bullet hell" style game. Chances are you will run into some bottlenecks or performance issues due to the large number of entities, particles and effects you will have on the screen at one time. If this is a personal project, then I guess you can afford to live on the edge a bit ☺️.

@gokadi
Copy link
Author

gokadi commented Feb 19, 2022

That’s sad 😞

Well, as I got it from expo doc, I can generate native code and work with it,can I? So I can continue develop it using rnge and at some moment split it to 2 native projects for iOS and Android and check/fix performance issues there?

@bberak
Copy link
Owner

bberak commented Feb 22, 2022

Hey @gokadi,

Yeah, if you create your project with Expo, you should be able to integrate your own native code for iOS and Android as required. However, I'd say that this would be a pretty big cost in terms of effort. You'll have 2 native modules to maintain, plus all the JS logic running on RNGE. And then there's the issue of what to keep in JS/RNGE and what to move over to native code.. For example, if you move the physics over to native, you'll still need to inform the JS side of the collisions etc.

Anyway, I don't wish to turn you off React Native (or RNGE for that matter). I love JavaScript and think there is a future in it for native mobile game development and scripting. I just don't want to overstate the capabilities of the platform in its present form.

Let me know your thoughts and in which direction you end up going 🙏

@gokadi
Copy link
Author

gokadi commented Feb 23, 2022

Hi!
I spent some time investigating this issue, removed some timers, tried "production mode" and for now, fps drops (like, from 60 to 1 by 1 second, very quickly) after "views" in performance monitor of expo becomes ~350. After this amount it starts growing very fast, like 350-390-500-.. and so on - this is probably because spawning is still implemented using custom JS interval (my assumption is that in event loop removing of old entities start working slower that spawning new and probably can be fixed if I remove custom interval).
But I think this is apporximately the best result we can achieve with RN + RNGE combination for now and probably should be documented.
I guess, ~350 animated components ("views" in expo terms), is enough for most cases. But still, we'll continue investigating, because our game will have particle system which will take most part of these 350 views

UPD: after removing interval for spawning, that threshold increased to 500. Quite good

@gokadi
Copy link
Author

gokadi commented Feb 23, 2022

Speaking about splitting to native projects - I meant completely split the project. As I understand, anyway it's being compiled to somewhat close to native code - mobile devices cannot execute js code, as I assume. So, this way we can spend less time by developing kind of MVP using rn+rnge and after that split it to independent native projects to fix details like performance, can we?

@bberak
Copy link
Owner

bberak commented Feb 26, 2022

Hey @gokadi,

Thanks for taking the time to investigate further. Are you saying that you have managed to render 350 dynamic views while still maintaining a reasonable frame rate 🤔? That seems quite high (from experience on my devices), but maybe I have misunderstood your analysis.

In regards to React Native, your device will actually execute your app's JS code using an embedded JavaScript engine (JavaScriptCore). Your JS source code is simply transpiled and bundled into a single .js file that will be executed by the engine (not compiled into a native executable or anything). Facebook is developing an alternate JS engine (Hermes) that might be more suitable (and performant) for React Native apps going forward - but this might not necessarily be beneficial for game development.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants