Author Topic: Atlas Switching script  (Read 53421 times)

n8

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Atlas Switching script
« on: June 25, 2012, 04:48:43 PM »
Hey everybody,
I have seen quite a few people on this forum trying to figure out the best way to switch the atlas at runtime.  I have created a script that handles that, and thought I would share it here.  There is some setup required to get this to work properly, but really it is pretty painless.

you will need:
-Reference Atlas - build your entire UI off this atlas, and then have this atlas point to one of these below
-Reference Font
-SD atals - (iphone 3gs and below)
-SD font
-HD atlas - (ipad 1&2, iphone 4+)
-HD font
-SHD atlas - (ipad 3) --- SHD = Super High Def (didn't know what else to call this.  Also this is not needed if you don't want to support it)
-SHD font

You will need to store all three "real" atlases and corresponding fonts (not reference) in your "resources" folder under the following folder structure "GUI/SD", "GUI/HD", "GUI/SHD".
For clarity I put all things related to the atlas in each of these folders (prefab, image, material).

Attach this script to an empty gameObject in your scene.

 **********
*IMPORTANT* 
 **********
In Unity go to "Edit -> Project Settings -> Script Execution Order"  Now add "ResolutionSwitchController" to the list and move it up towards the top.  You want this script to be one of the very first scripts to run.  ESPECIALLY before any of the NGUI scripts (I have mine set to the second in the list just below "localization").

Notes:
-script assumes you are in landscape (all screen resolution checks are based on width -- this could/should probably be changed)
-the two labels are for debugging purposes, to ensure that you are running the resolution that you think you are on your device
-script can be set to not run in the editor, as this can screw up all of your references.

Please feel free to use, update, and modify this script to fit your needs.  Hope this helps somebody!

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class ResolutionSwitchController : MonoBehaviour {
  5.        
  6.         public bool disableInEditor = true;
  7.         public int HDResolutionCutOff = 960;
  8.         public int SHDResolutionCutOff = 2048;
  9.        
  10.         public UIAtlas ReferenceAtlas;
  11.         public string SDAtlasName;
  12.         public string HDAtlasName;
  13.         public string SHDAtlasName;
  14.        
  15.         public UIFont ReferenceFont;
  16.         public string SDFontName;
  17.         public string HDFontName;
  18.         public string SHDFontName;
  19.        
  20.         public GameObject ReplacementAtlas;
  21.         public GameObject ReplacementFont;
  22.        
  23.         public UILabel screenWidthLabel;
  24.         public UILabel screenHeightLabel;
  25.        
  26.         // Use this for initialization
  27.         void Awake () {
  28.                
  29.                 if(disableInEditor && Application.isEditor)
  30.                 {
  31.                         return;
  32.                 }
  33.                
  34.                 int ScreenHeight = Screen.height;
  35.                 int ScreenWidth  = Screen.width;
  36.                
  37.                 if(screenHeightLabel)
  38.                 {
  39.                         screenHeightLabel.text = ScreenHeight.ToString();
  40.                 }
  41.                
  42.                 if(screenWidthLabel)
  43.                 {
  44.                         screenWidthLabel.text = ScreenWidth.ToString();
  45.                 }
  46.                
  47.                 if( ScreenWidth >= SHDResolutionCutOff )
  48.                 {
  49.                         ReplacementAtlas =  Resources.Load("GUI/SHD/" + SHDAtlasName ) as GameObject;
  50.                         ReplacementFont = Resources.Load("GUI/SHD/" + SHDFontName ) as GameObject;
  51.                         Debug.Log("Setting texture to SHD");
  52.                 }else if( ScreenWidth >= HDResolutionCutOff )
  53.                 {
  54.                         ReplacementAtlas =  Resources.Load("GUI/HD/" + HDAtlasName ) as GameObject;
  55.                         ReplacementFont = Resources.Load("GUI/HD/" + HDFontName ) as GameObject;
  56.                         Debug.Log("Setting texture to HD");
  57.                 }else {
  58.                         ReplacementAtlas =  Resources.Load("GUI/SD/" + SDAtlasName ) as GameObject;
  59.                         ReplacementFont = Resources.Load("GUI/SD/" + SDFontName ) as GameObject;
  60.                         Debug.Log("Setting texture to SD");
  61.                 }
  62.                
  63.                 ReferenceAtlas.replacement = ReplacementAtlas.GetComponent<UIAtlas>();
  64.                 ReferenceFont.replacement = ReplacementFont.GetComponent<UIFont>();
  65.                
  66.         }
  67. }
  68.  

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Atlas Switching script
« Reply #1 on: June 25, 2012, 05:08:12 PM »
Cool stuff. I have some notes. :)

For one of our upcoming games, I used a similar setup but with arrays of atlases and fonts, since I had a few of them.

I also defaulted my reference atlas to the low res so I could work with it in the editor, instead of having to setup while playing. When I do this, I have to switch back to the low res when I end a play (OnDisable or OnDestroy) or the prefab will be marked as changed in version control.

I'm not sure why you need the script execution order for this, since it should change "nicely" no matter when you change the things. This may just have been a sideeffect in my project, since it had the low res loaded from the beginning.

I also just attached mine to the UIRoot so I knew it would always be in the scene, but anywhere will do.

n8

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Atlas Switching script
« Reply #2 on: June 25, 2012, 11:20:19 PM »
Cool stuff. I have some notes. :)

For one of our upcoming games, I used a similar setup but with arrays of atlases and fonts, since I had a few of them.

I also defaulted my reference atlas to the low res so I could work with it in the editor, instead of having to setup while playing. When I do this, I have to switch back to the low res when I end a play (OnDisable or OnDestroy) or the prefab will be marked as changed in version control.

Yeah I was only needing the three atlases, so I didn't bother with setting up arrays.  And yeah I could see setting up to revert back to the first atlas, I find it easier to just not have the script run in the editor.

I'm not sure why you need the script execution order for this, since it should change "nicely" no matter when you change the things. This may just have been a sideeffect in my project, since it had the low res loaded from the beginning.

I guess it could work without doing that. I was just under the impression that it needed to run before ngui loaded

I also just attached mine to the UIRoot so I knew it would always be in the scene, but anywhere will do.

Good idea!

Curzed

  • Guest
Re: Atlas Switching script
« Reply #3 on: August 06, 2012, 01:35:14 PM »
Does anyone have a version of this that includes Android as well and wouldn't mind sharing?

Thanks

n8

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Atlas Switching script
« Reply #4 on: August 08, 2012, 04:19:07 PM »
this script should work just fine on android.  You will just need to figure out what resolutions you want to use to trigger the switch.  For instance the nexus s has a resolution of 480 x 800.  I use that as the "SD" resolution. the Galaxy tab 10.1 (roughly equivalent to the ipad in resolution) is 1280x800, so that could be your cut off for "HD" resolutions.  You could also go the route of treating most phones as "SD", most 7" tablets as "HD" and then 10" tablets as "SHD".  it is really all up to you.

Urwin78

  • Guest
Re: Atlas Switching script
« Reply #5 on: October 06, 2012, 09:16:25 AM »
Read everything about this topic, watched the tutorial everything works fine, build on iPad2 and iPad3 only one small thing.
After the build in Xcode I'm receiving 15 Thread error errors

Starting with the Thread1: EXC_BAD_ACCESS (CODE=1,adress=0x0

0 ResolutionSwitchController_Awake
1 Wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr_
2 mono_jit_runtime_invoke
3 mono_runtime_invoke
4 mono_runtime_invoke_profiled_fast_(MonoMethod*,MonoObject*(*)void*,MonoException**),...

Does anyone know how to fix this?

Unity 3.5.6
IOS 5.1.1



ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Atlas Switching script
« Reply #6 on: October 06, 2012, 09:32:06 AM »
Don't quote me on this, but I think that particular error is caused by turning on stripping.

Urwin78

  • Guest
Re: Atlas Switching script
« Reply #7 on: October 06, 2012, 12:21:39 PM »
Thank you for helping.

Code stripping is disabled in Unity or didn't you meaned that.
No errors when I don't use the resolutionswitch script.

« Last Edit: October 06, 2012, 12:27:30 PM by Urwin78 »

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Atlas Switching script
« Reply #8 on: October 07, 2012, 02:09:08 PM »
Urwin78 something in the ResolutionSwitchController's awake accesses something bad. It probably tries to access a null's member or method. Check every line there.

Do note, that script execution order is not necessarily the same in the editor and on device, which means you may have lucked out on the timing of awakes in the editor, but crapped out on the device, if ResolutionSwitchController relies on something being set in another Awake.

Multiple solutions:
1) Move ResolutionSwitchController's awake stuff to Start() instead.
2) Set a custom script execution order where ResolutionSwitchController runs after whatever it relies on.

Joe @ ByDesign Games

  • Guest
Re: Atlas Switching script
« Reply #9 on: October 26, 2012, 07:59:00 PM »
Does the above code actually work?  Asking, because we're doing something similar and seeing ReplacementAtlas == null despite the path being absolutely valid.

Reasoning:
  1. ReplacementAtlas =  Resources.Load("GUI/SHD/" + SHDAtlasName ) as GameObject;
doesn't actually set the variable to a game object (test for null to see what i mean)

You'll note all the game object / prefab examples that use Resources.Load use Instantiate (Resources.Load()). If we change the above line to use Instantiate, then it works fine, but of course, we're left with the instantiated gameObject in the scene, and the reference atlas property gets set to null on Stop.

Are we missing something here?
« Last Edit: October 26, 2012, 08:07:28 PM by Joe @ ByDesign Games »

Joe @ ByDesign Games

  • Guest
Re: Atlas Switching script
« Reply #10 on: October 26, 2012, 11:27:16 PM »
Happily, this works 100% here:
  1. ReplacementAtlas = Resources.Load("GUI/SHD/" + SHDAtlasName, typeof(UIAtlas)) as UIAtlas;

And should use fewer resources too boot! Woot! :)

n8

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Atlas Switching script
« Reply #11 on: October 31, 2012, 12:20:54 AM »
Happily, this works 100% here:
  1. ReplacementAtlas = Resources.Load("GUI/SHD/" + SHDAtlasName, typeof(UIAtlas)) as UIAtlas;

And should use fewer resources too boot! Woot! :)

nice! when I was writing my script I was attempting to make it as easy as possible to use in most systems.  I am surprised it did not work as is in yours.  I like your solution to target the UIAtlas specifically though.

FizzPow

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 83
    • View Profile
    • FizzPow Games
Re: Atlas Switching script
« Reply #12 on: December 27, 2012, 08:49:38 PM »
Does anyone know if by setting script execution order like this thread suggests, if it will catch Unity before it loads whatever atlas was last set in the Editor?  I ask this to avoid loading the wrong texture first and then it loading the correct one, causing longer load times and possibly run out of memory on a low-end SD device.

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Atlas Switching script
« Reply #13 on: December 28, 2012, 10:49:18 AM »
It will not.

If you want it not to load the one set in editor, you should clear the reference when building - then it will be clear first, and then load whichever one you need.

Nicki

  • Global Moderator
  • Hero Member
  • *****
  • Thank You
  • -Given: 33
  • -Receive: 141
  • Posts: 1,768
    • View Profile
Re: Atlas Switching script
« Reply #14 on: December 28, 2012, 10:49:53 AM »
I said that a little too confidently.. I mean "i'm pretty sure it won't". :)
« Last Edit: December 28, 2012, 10:30:58 PM by Nicki »