Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Matching Camera Viewport to Screen Space Overlay Canvas

Discussion in 'UGUI & TextMesh Pro' started by JAKJ, Sep 2, 2014.

  1. JAKJ

    JAKJ

    Joined:
    Aug 17, 2014
    Posts:
    185
    I'm using a "Screen Space - Overlay" canvas for my game (the whole game is menus and tiles and such like a board game, so the entire game is inside the canvas) with Reference Resolution set to 1920x1080, which keeps the canvas object in 3D space set to that size and adjusts the scaling factor. This works correctly: Narrower aspect ratios give me black bars above/below just like I want.

    However, I want to render 3D things like objects and particle systems *behind* the UI elements and have them lined up properly. However, since it doesn't work to have the 3D objects actually in the Canvas (pretty sure 3D objects can't be given a RectTransform), I can't figure out a way to get things to line up. The game automatically changes the camera's viewport ratio to match the screen's ratio which is how all of this works, so I can't just create a GameObject with the same dimensions and scaling of the Canvas, and if I switch to a world-space canvas, that'll break all the nice auto-ratio-handling. What's the real way to do this?
     
  2. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,901
    3D objects can have a RectTransform fine, they just ignore the rect and are positioned at the pivot position of the RectTransform. Anchoring will still work.

    However, in Screen Space - Overlay mode the 3D objects will not appear in screen space unless you manually position your camera in a very specific way. I suggest you instead switch to using Screen Space - Camera. Then your 3D objects will render aligned together with the UI. They can be behind the UI if you set the plane distance in the Canvas sufficiently small.
     
  3. JAKJ

    JAKJ

    Joined:
    Aug 17, 2014
    Posts:
    185
    So then I would create a container GameObject that changes its scale to match that of the canvas each time the screen's resolution changes. That's kind of neat: It turns the entire Canvas into just a quad but Reference Resolution still seems to work.
     
  4. JAKJ

    JAKJ

    Joined:
    Aug 17, 2014
    Posts:
    185
    Just got this working flawlessly and wanted to put it here so people know.

    1) Put "Reference Resolution" on Canvas and set highest targetted resolution.
    2) Put Canvas into "Screen Space - Camera" and insert reference to main camera.
    3) Change orthographic "Size" of camera to be 1/2 the height of your reference resolution (so for 1920x1080, that's 540), and change camera position to be (0,0,0).
    4) Create empty game object at (0,0,500), or whatever z-value suits the Plane Distance of your Canvas.
    5) Put this script on something:

    Code (CSharp):
    1. using UnityEngine ;
    2.  
    3. public class ScaleWorldByCanvas : MonoBehaviour
    4. {
    5.     public Transform WorldObject ;
    6.     public Transform CanvasObject ;
    7.  
    8.     int CachedWidth ;
    9.     int CachedHeight ;
    10.  
    11.     void Refresh ( )
    12.     {
    13.         CachedWidth = Screen . width ;
    14.         CachedHeight = Screen . height ;
    15.  
    16.         WorldObject . localScale = CanvasObject . localScale ;
    17.     }
    18.  
    19.     void Start ( )
    20.     {
    21.         Refresh ( ) ;
    22.     }
    23.  
    24.     void Update ( )
    25.     {
    26.         if ( Screen . width == CachedWidth )
    27.         {
    28.             if ( Screen . height == CachedHeight )
    29.             {
    30.                 return ;
    31.             }
    32.         }
    33.  
    34.         Refresh ( ) ;
    35.     }
    36. }
    Now, put all your 3D UI objects under that one GameObject that's being scaled, and you can position things as if one world unit is one pixel and it will remain fixed relative to the UI.
     
    arg_barg, krajzeg, a318 and 9 others like this.