0
\$\begingroup\$

I am developing a Mobile game for Android and iOS on Unity.

Currently Im in the optimisation stage of development and trying to work out what is the best way to detect device capabilities, with the aim of then setting an appropriate quality setting.

OS/platform detection is simple, but how can I detect between a high performance android device and a low or medium performance device at runtime?

I did find this question that is similar https://stackoverflow.com/q/21565468/4148676 but the question is old, the answers not great and hoping there's a better way in the last 4 years of solving the problem.

The only other solution I have is monitor the average FPS and adjust the quality based on the frame rate.

Any advice would be appreciated.

\$\endgroup\$
0
1
\$\begingroup\$

I cannot give "the best practice" because it really depends on your situation. But I can give two real world examples from games I worked on.

In Love & Hip Hop, we checked the RAM of the device. At the time, 2GB devices could definitely render a lot more than 1GB devices. So we tried to target the lowest 2GB devices with high-resolution assets, and others with low-resolution assets.

Dead by Daylight has a resolution changer that drops resolution if the framerate is crap for too many frames. Then it bumps it back up later if it's smooth for long enough. Though this game is made with Unreal 4, there's no reason Unity couldn't use this tactic. DbD also has user-selected quality settings for graphics since PC hardware is so varied.

\$\endgroup\$
0
\$\begingroup\$

The first step is to determine the list of devices you'd like to target/support. To construct this list, simply go to each major phone manufacturer and go backwards from their most recent models until you find a device that you no longer want to support. The simpler or more light-weight your game is to run, the farther back in the model history you can go.

Once you think you have your list of supported devices, compare the specs of the lowest ranking ones. The ideas is for the minimum specs to be similar. You may support the 7 most recent iPhone models but only the 4 most recent Samsungs for example.

Then make your game work for the least powerful supported device. In initialization there's a whole list of device properties you can check to see what the particular active device can support. Since you know the specs of the lowest tier devices that you will support, you have your checks verify these minimums and adjust accordingly.

While device hardware is technically what limits framerate, using the raw framerate to estimate device specs can be deceiving because there other factors that can bottleneck performance such as unoptimized code or heavy art assets. When in doubt, add graphics options to your game so the user can lower quality when they know their device is not up to par.

\$\endgroup\$
6
  • \$\begingroup\$ This really isn't a practical way of doing this, especially when you consider a) how many android devices there are and b) how often new devices come out and how often you would have to update your app. The only similar way to this would be to look at GPU and ram and then segment that way as there are far less options to take into account. \$\endgroup\$ – unknownSPY Mar 2 '19 at 13:56
  • \$\begingroup\$ I didn't say it was easy, but I used to work at a mobile game studio for a popular mobile game and this was our process. a) Yes, there are a lot of android devices. This is a pain for devs, just focus on the major manufacturers and draw the line somewhere. b) New devices coming out has zero impact on your game. All new devices will automatically meet your min specs. You don't need to update your app every time a new phone comes out. \$\endgroup\$ – RAM804 Mar 4 '19 at 7:52
  • \$\begingroup\$ "all new phones meet your mine spec" that just really isn't true. Manufacturers release low end phones every year.. (I do work currently at mobile studio, just not one using Unity that's why I wondered if there was a unity way of detecting performance). \$\endgroup\$ – unknownSPY Mar 4 '19 at 8:00
  • \$\begingroup\$ you would have to be crazy to go by device ID as there are thousands of android device when you take into account all of the Chinese brands and knock offs \$\endgroup\$ – unknownSPY Mar 4 '19 at 8:00
  • \$\begingroup\$ Ok, true, I made the mistake of assuming you were talking about modern smartphones. For our target market, new phones were never the concern, just older models. I don't know what you're talking about with device IDs? I never mentioned device IDs, because you're right, that wouldn't make sense. Our QA and engineering teams had about 50 devices of different models (a few duplicates). We tested on each monthly. If you don't have the kind of budget or manpower for that kind of testing, then the solution we used will likely not be viable for you. All I can say is it worked. \$\endgroup\$ – RAM804 Mar 4 '19 at 8:36
0
\$\begingroup\$

This is 2 years old, but still quite relevant and as the answers are somewhat lacking (in my opinion), I'll share my experience and solution to the question for anyone who might be or still be looking for some tips and answers.

The first thing about mobile (Android especially) is that there's no flat ground nor standards, regardless of what anyone tells you. iOS makes things a bit easier because there's only 1 source (Apple) and they usually follow their own set of rules, but even iOS gets modified now and then in a way that break things.

As such, it's always best to not get too deep into the search for the perfect solution as any solution will become usually obsolete at some point in time, be it from an update to Unity (the engine) or the newest generation of Android or iOS released and applied/used by the manufacturers.

Still, it's normal to wish for a good approach and one of such would be to use 2 methods that works hands in hands and to which Unity has full support (or at least offer good access to).

The first method is to use some hard coded system stats.

SystemInfo.systemMemorySize

This is a good way to get an "idea" of the average memory available for the app. The one thing to remember is that, on mobile, this will NOT return the full value of the available memory of the device, but will return what memory the OS allows the App to use when it's being used in Foreground. For example, if a mobile device has 1.5GB of RAM and the version of Android uses 1GB of RAM to run in average, systemMemorySize will return around 500-512MB. Due to that, it's not a "work-best-and-always" trick, but it does help you know how much memory the user's device might have in general. (For example, even if a mobile device with 4GB of RAM, if the user is leaving the Facebook App, a web browser with a few tabs, chat via Skype and play the game at the same time, the game might be able to get access to only 0.5GB-1GB memory. Some app used by many people every day are real memory hungry and there's nothing you can do about.)

Keeping track of the FPS within the game can also be a good gauge. By using a coroutine, you can check the FPS every now and then. There's no need to check it every frame though. The trick is to check the average within an acceptable amount of time and drop a few things if the FPS average gets under a certain threshold. But this is assuming that you have already profiled your game so that it remains constant and fixed in its FPS at all time. If you know some part of your game might have some heavy impact on the FPS and wishes to be safe during those moments from having fake drop in the FPS, you can always set the threshold on the fly as needed.

Another thing that can be useful is this function:

Application.lowMemory

While the example in the link is useful, one good example of use of the lowMemory function is to do a memory sweep and load a "safe scene" which allow the memory usage of the App to drop. An important point to remember is that, whenever lowMemory is being called, it's not that the FPS is just low, but it's that the OS struggle to maintain the App integrity and might close it soon if nothing is done.

A last thing would be to consider checking the version of Android or iOS that is being used. There's a few way of looking it up (like this ). Knowing the version won't give you a clear answer, but the API version (OS version) gives an idea of what kind of compatible or incompatible thing comes around from the OS itself. You might be able or forced to turn off some features or graphics effects if the device runs on an API below 23, for example, like AR/VR or physics-based particles. If a device API is 20 or below, you should consider, by default, that it's a low-end device (in today's and Unity's mobile standards) 23 is low-average with compatibility with enough memory. 24 to 27 is low-medium-high and are the most used in the World right now. 28 or more are high and should, generally speaking, run well unless systemMemorySize returns a low value.

Remember that "high" models, in what I wrote above, are NOT the best available, but more like the best available in a big part of the World. When it comes to testing your App with multiple devices, it's best to do the simple, yet most common thing: Go to a popular store around your area and speak with the store clerk. Explains your position and ask him what's the worse phone (or tablet) he has in his opinion, which one is the most popular outside of the newest models and, if your budget allows you to, which one is the most popular (which is usually one expensive). You might know more about mobile device than him or her, but he's the one who actually sell the devices and you might be surprised about what models will comes to your hands. If you explain your position as a mobile game app developer, not only the store clerk might be interested in your own story (and game), but he or she might be more willing to help you with honesty. (And he or she knows you might return for another testing device in the future.) Obviously, some store clerk might attempt to mislead you in one of the devices, but remember that if he tries to mislead you, he'll mislead others and that's a common thing which makes it so that your "average every-day's Joe" will usually buy that thing because the store clerk sells it to him (or her).

Also, last tip, don't purchase device below your minimal standard just for the sake of, maybe, be able to downgrade your project below your expectations. If you set your goal for the App to run on devices with at least 1GB of RAM, don't buy devices with 512MB of RAM. Remember that both the Google Play store and iOS iTunes store (for games/app) allow you to set a "minimum" level of compatibility which will make your App visible not compatible and downloadable with device below your target. Don't fall into the rabbit hole of over-optimization for the sake of reaching a lower device as this will often result in breaking something in the app for higher/better devices.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.