Blog

Simplifying Screen Positioning in Unity

User interface resides in one of the nine sections of any screen it’s designed for: Upper Left, Upper Middle, Upper Right, etc. and maintaining consistent positioning for your UI while trying to centralize game code to be run on multiple device resolutions can be annoying and tedious.

To help simplify screen positioning for UI and any other elements I’ve put together a super simple C# extension for Unity that exposes a new method to Transform and GameObject called ScreenPlacement. I’ve also included a demo scene which shows how to position things perfectly as well as included a nice component called “ScreenPlacement” that you can put on any object to set it’s position visually in the editor.

Once added to your project, ScreenPlacement can easily be used to place things within one of the 9 sections of a screen:

//Place an object in the lower right of the screen:
transform.ScreenPlacement(ScreenPosition.LowerRight);

//Place an object in the lower right of the screen 60 pixels from the right and 20 pixels from the bottom:
transform.ScreenPlacement(ScreenPosition.LowerRight, new Vector2(60,20));

If you choose to use a camera other than the Main Camera for your UI to help stack aspects of your game display, pass that camera into ScreenPosition to ensure calculations are accurate to that camera:

//Place an object in the lower right of the screen using a camera other than Main Camera:
transform.ScreenPlacement(ScreenPosition.LowerRight, MyInterfaceCamera);

//Place an object in the lower right of the screen 60 pixels from the right and 20 pixels from the bottom using a camera other than Main Camera:
transform.ScreenPlacement(ScreenPosition.LowerRight, new Vector2(60,20), MyInterfaceCamera);

Download

21 Comments

  1. May 19, 2011

    Awesome, this is EXACTLY what I needed, perfect timing, thank you!

  2. pixnlove
    July 4, 2011

    This is totally awesome. My gosh I am going to have much more fun designing my UI now. Thanks so much

  3. August 11, 2011

    I’ve been playing with this for a bit ovr an hour, and I cannot get it to work at all. The positions it is moving the game object are nonsensical, like changing the Z value in the position…

    Does this have to be put on a GUITexture directly? I ask because when putting it on a GameObject with GUITexture/GUIText children, it always aligns them off the screen.

    Does it require a Camera at a certain z,y, and z position?

    • August 15, 2011

      Sorry I have been slow to help on this. Do you have any Pixel Insets set on the GUITexture or GUIText?

  4. October 19, 2011

    This is really useful, thanks for sharing.
    I did however find a little problem where the y offset wasn’t working for ScreenPosition.Right. A quick fix on line 173 did the trick:

    original:
    screenPosition = renderingCamera.ScreenToWorldPoint(new Vector3(Screen.width-pixelsFromEdge.x, Screen.height/2, zPosition));

    fix:
    screenPosition = renderingCamera.ScreenToWorldPoint(new Vector3(Screen.width-pixelsFromEdge.x, (Screen.height/2) pixelsFromEdge.y, zPosition));

    • October 20, 2011

      Nice catch and thank you. Just updated it and I missed this for a few of them but they are all correct now.

    • Robert Shearing
      October 24, 2011

      Can you check the download link. All that is in the package is a file called “Position.cs”, “ScreenPlacementExtension.cs” is missing.
      Thanks.

    • October 24, 2011

      Thanks so much for the heads up. The package has been fixed and I included a demo scene to show how to use everything as well as included a nice component so you can visually assign positions to objects in your scene.

  5. Robert Stehwien
    November 17, 2011

    I made a modification to allow setting what camera to use in the unity editor so I could have a separate GUI camera rendered above the main scene. Using the camera that follows the player caused some crazy behavior:

    public class ScreenPlacement : MonoBehaviour {

    public ScreenPosition position;
    public Vector2 pixelOffset;
    public Camera placementCamera;

    void Update(){
    if (placementCamera != null)
    transform.ScreenPlacement( position, pixelOffset, placementCamera );
    else
    transform.ScreenPlacement( position, pixelOffset );
    }
    }

  6. gianluca
    March 26, 2012

    I cant begin to express my gratitude for this simple yet effective tool! thank you very much! 😉

    • March 26, 2012

      Awesome, glad I could help – I haven’t looked at this in a while so let me know if anything is broken.

  7. Florent
    May 1, 2012

    Thanks a lot for that !

    Question : If i want a button(gameobject) to be placed on the top right of my screen, but with a certain offset on the left.
    If i want this offset (finally a margin or space ) to look the same on any screen resolution, how would you do it ?

    At the beginning, i tried with a static value, like 50 pixel margin, but 50 pixels on 800*600 and 50 pixels on 1600*900 resolution won’t look the same.

    I was thinking of adding a factor ( 0.04 here ), but it does not make the trick either

    ScreenPlacementExtension.ScreenPlacement(GameObject.Find(“ControlPauseButton”), ScreenPosition.UpperRight, new Vector2(Screen.width * 0.04F, Screen.height * 0.05F));

    in 1600, it will be placed at 64 pixels ( screenshot here http://postimage.org/image/vyl3airxj/ )
    in 800, it will be placed at 32 pixels ( screenshot here http://postimage.org/image/6pbwy27a9/ )

    I can’t work out to make it look the same on any resolution, any hint ?

    Thank you very much

    • May 2, 2012

      My recommendation would be to establish a scale value based off a root design size. Typically we design at either iPad (1024×768) or iPad Retina’s (2048×1536) resolution which ends up being our root size for our percentage values.

      So if the core design was iPad:

      Vector2 scale = new Vector( Screen.width/1024f, Screen.height/768f );
      

      Then in practice you could set margins and offset with this scale value:

      //set 50 pixels margin scaled appropriately:
      ScreenPlacementExtension.ScreenPlacement(GameObject.Find(“ControlPauseButton”), ScreenPosition.UpperRight, new Vector2( 50 * scale.x, 50 * scale.y ));
      

      Wrote this code in WordPress so I can’t guarantee it’s error free but I hope it helps.

      I’m actually working on a full GUI framework for Unity that helps leverage its built-in GUI but helps to formalize cross-resolution solutions like the one you brought up in your comment.

    • Florent
      May 2, 2012

      Understood,

      However, the application im currently developping will target all android platforms ( tablet, phone …). i’ll be working with quite a lot of different resolution.
      Do you think there is no other way to define the scale like the following ( which is finally the same solution you have proposed above)

      if(Screen.width > 1024) {
      Scale = 0.04
      } else if(Screen.width < 1024) {
      Scale = 0.06
      } else if(Screen.width < 800) {
      Scale = 0.08
      }
      and so on

      I find it a bit cumbersome. If you have any other hint, please let me know

      Cheers

    • May 2, 2012

      This route has worked well for me with cross-device development as it scales nicely across all resolutions.

      Hope you find something that better suites your needs if that doesn’t work.

  8. February 18, 2013

    I created an editor extension that sitts inside the transform inspector to help layout 2d assets using your code as a base:
    http://justtodayonly.tumblr.com/post/43431702855/2d-layout-in-unity

    Your code is most useful, I just wanted an instant, viewable version that I could use.

    It needs some tweaks, like editing a transforms position updates its offset, but for the most part it works well enough.

    Thanks for sharing!

  9. Iktan Trejo
    October 15, 2013

    oh man i been spending a lot of time with this topic, works great thank you!! 😀

  10. Michael
    May 11, 2014

    Hello, i have to camera’s both active and on screen. The placement needs to be at my main camera. Problem is that my main camera has depth -2 and the other camera has depth -1. Therefore all placements of objects is done at the wrong camera. Is there a solution for this problem?

    Thanks in advance, great tool! will help me a LOT

    • May 13, 2014

      Yes, you can simply use the overload that allows you to choose what camera to use for the calculations. Something like this:

      public class ScreenPlacement : MonoBehaviour {

      public ScreenPosition position;
      public Vector2 pixelOffset;
      public Camera renderingCamera;

      void Update(){
      transform.ScreenPlacement( position, pixelOffset, renderingCamera );
      }
      }

  11. Sanam Baig
    June 2, 2014

    I love this, you saved the day. Pixel perfect placement was work of hours but you solved it and now it is work of two minutes. Amazing, Superb Job, Awesome. Thank you very much for sharing you work.