Search Unity

Supporting Multiple iOS Resolutions (iPad, iPhone4, 3GS)

Discussion in 'iOS and tvOS' started by the_golden_gunman, Feb 15, 2011.

  1. the_golden_gunman

    the_golden_gunman

    Joined:
    Feb 15, 2011
    Posts:
    17
    Please excuse my ignorance, but I cannot seem to find much documentation on how to go about setting up a project such that it can support multiple screen resoultions at the same time.

    I know that I would have to include textures and re-sized images for each of the devices I want to support in one project, but how do I go about switching between active materials and textures? For example, for my title screen, I would like to use a certain texture, but if the user is playing my app on their 3GS, I would like my project to use a different texture than the one that an iPhone 4 user would see displayed.

    Is there any documentation or discussion available anywhere that someone could please point me to that covers this subject?
     
  2. MikaMobile

    MikaMobile

    Joined:
    Jan 29, 2009
    Posts:
    845
    This is a script I used to do what you're describing in my latest release. It's pretty simple, basically it just checks to see if the screen is 500 or more pixels wide, and if so, it loads a texture from my resources folder with one name, and if its less than 500, it uses the same name except with the suffix -Lo added. (i.e. PirateTexture and PirateTextureLo)

    So for everything that I needed to have different resolution textures for, I just attached this script and typed in the base name of the texture in the inspector. Turning on the "shared" boolean just tells the script that the material in question is shared between multiple objects. Once its work is done, the script deletes itself.

    You'd probably want to modify the resource path to suit your own project's directory structure. It's also important to make sure that the material you're modifying through this script starts with no texture at all, otherwise you'll potentially be loading that starting texture AND another one at the same time, wasting precious RAM.

    Code (csharp):
    1. var textureName = "textureName";
    2. var shared = false;
    3.  
    4. function Awake () {
    5.     var tempRenderer : Renderer;
    6.     tempRenderer = gameObject.GetComponent("Renderer");
    7.     if (Screen.width > 500) {
    8.         if (shared) {
    9.             tempRenderer.sharedMaterial.mainTexture = Resources.Load("DynamicTextures/" + textureName);
    10.         }
    11.         else {
    12.             tempRenderer.material.mainTexture = Resources.Load("DynamicTextures/" + textureName);
    13.         }
    14.     }
    15.     else {
    16.         if (shared) {
    17.             tempRenderer.sharedMaterial.mainTexture = Resources.Load("DynamicTextures/" + textureName + "Lo");
    18.         }
    19.         else {
    20.             tempRenderer.material.mainTexture = Resources.Load("DynamicTextures/" + textureName + "Lo");
    21.         }
    22.     }  
    23.     tempRenderer.enabled = true;
    24.     Destroy(this);
    25. }
     
  3. the_golden_gunman

    the_golden_gunman

    Joined:
    Feb 15, 2011
    Posts:
    17
    Thanks! I had been trying some resource loading code with little to no effect, so thank you for showing me such a great example.
     
    Last edited: Feb 16, 2011
  4. johot

    johot

    Joined:
    Apr 11, 2011
    Posts:
    201
    When I do this using renderer.sharedMaterial the setting is remembered even after my game has exited.

    This means that the tip make sure the material starts with no texture at all will never work since the textures will be given a material after the game has been debugged once.

    How do you solve this issue?

    Also how do we know that the material set in the editor is used if you override it in Awake()? Are we not "fast" enough to override the value before it's used in the game?

    Thanks for any help on this!
     
  5. RazorCut

    RazorCut

    Joined:
    May 7, 2009
    Posts:
    393
    Add a method OnApplicationQuit() and in there set the material's texture to null (warning: this doesn't always work though especially after a crash during development). This is only needed in the editor, by the way... it's not actually necessary on-device since it's not possible to modify the materials on-device like the editor environment can.

    When I've loaded textures dynamically like this, I've had to create an editor script that would clear out these materials for me as a preprocessing step before the build occurs. I'd place these materials in a directory with a special name, create a customized script that would do my building for me (instead of using the built-in build menu), and have that script clear out the textures before doing the build.
     
    Last edited: May 4, 2011
  6. johot

    johot

    Joined:
    Apr 11, 2011
    Posts:
    201
    Ah thanks RazorCut I was thinking about doing a similair thing, nice to hear it atleast works :)

    What im currently thinking about is doing, is this. And note we are using Sprite manager 2.

    1.Three editor scripts:
    * Set high resolution textures
    * Set low resolution textures
    * Set automatic texture resolution (do this before an actual build)

    (The reasons for the top two scripts would be so I can still see the textures in the editor most of the time)

    2.A script that takes all sprite materials, that uses the sprite atlases textures, and when the texture of these are null, which happens by appliying "script 3", the correct low or high resolution texture is found and applied at runtime depending on the device.

    Currently all sprite atlases are put in a folder named "Sprite Atlases" by sprite manager 2. I might need to move them to the resources folder? Also I would need to be able to find all materials that uses these during runtime. So I might need to move those materials to resources aswell, right?
     
  7. blacksmithgames

    blacksmithgames

    Joined:
    Aug 30, 2009
    Posts:
    24
    Hi,

    I have the same problem like johot ("renderer.sharedMaterial the setting is remembered even after my game has exited") using Sprite Manager 2. Somebody found a good workaround?
     
  8. johot

    johot

    Joined:
    Apr 11, 2011
    Posts:
    201
    Yes it will be remembered. What i did was that I cleared it in OnApplicationQuit. But you could also create an editor script that clears it all out I guess. Unlike miika mobile I created one script that could take care of multiple textures, like a manager.

    However today we just check mipmaps on our textures which gives the same affect but I guess with a memory penalty.
     
  9. x10z

    x10z

    Joined:
    Aug 18, 2009
    Posts:
    54
    Do I have to do this in every scene ? From what I've seen , you cannot change the material in one scene and have it changed in the next one , you have to change every time a new scene loads ... right ?
     
  10. x10z

    x10z

    Joined:
    Aug 18, 2009
    Posts:
    54
    What if I have the game in low resolution , and only load the textures when I detect retina , and after it I do Resources.UnloadUnusedAssets(); ... that might take more time loading but will not affect RAM when game is playing, right ?
     
  11. Wild-Factor

    Wild-Factor

    Joined:
    Oct 11, 2010
    Posts:
    607
    You will have a pic in memory usage -> can crash your game on ios (stability on device not shutdown for a while OR not enough memory)
    (I'm not sure about that) You will increase memory fragmentation -> perf impact if the GC need to defrag.

    Of course if your game don't use a lot of memory, you will have no problem with your solution.
     
  12. x10z

    x10z

    Joined:
    Aug 18, 2009
    Posts:
    54
    Yeah makes sense, but I need to see stuff in the editor while working... Maybe I'll make that change only for the last build... it's a damn shame you can not change materials for all scenes! :D

    Thanks