Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Any way to set canvas settings for prefab mode?

Discussion in 'Prefabs' started by stopiccot_onthespot, Oct 16, 2018.

  1. stopiccot_onthespot

    stopiccot_onthespot

    Joined:
    Oct 1, 2016
    Posts:
    86
    When opening UI prefabs in new prefab only mode dimensions of my "Canvas (Environment)" node are 287x444 points which is waay to small. Any way to change that settings?
     
  2. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,803
    No, it uses a default Canvas which is based on the size of your Game View.

    You can however create a scene with a Canvas in it that fits your needs and assign that scene as the Environment Scene for UI Prefabs in the Editor Settings for the project.
     
  3. stopiccot_onthespot

    stopiccot_onthespot

    Joined:
    Oct 1, 2016
    Posts:
    86
    Thanks a lot, that's exactly what I was looking for
     
    LeonhardP likes this.
  4. RGV

    RGV

    Joined:
    Jan 25, 2016
    Posts:
    9
    What if you have different size needings for different UI Prefabs? I think I'm missing something because I can't figure out how Environment Scene works.
    I mean, I have a UI Prefab which must anchor to the whole size of whose parent. For instance, imagine a common shop Slot. The slots container will shrink & grow depending on the aspect ratio, so my shop Slop prefab must stretch to both axis. But it stretches to the "Canvas (environment)" size whatever the container size actually is.
     
  5. mmmathias

    mmmathias

    Joined:
    Oct 17, 2017
    Posts:
    1
    What if you have different size needings for different UI Prefabs?

    Thought about the same thing but atm. there seem to be no support for that.

    It works that you'll just need to add a Canvas to the scene and add the same Canvas Scaler as you are using in your regular scene. Then you'll observe that the prefab looks exactly the same in edit mode as in your scene.
     
    RGV and jrumps like this.
  6. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,803
    If different Prefabs need different contexts, we don't have a great solution for that today. We're working on a feature called in-context editing which should address this better.
     
    RGV, tatulaine and HonorableDaniel like this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,951
    It's very confusing that the scene view size of the canvas is tied to the resolution of the game view. Especially when the game view is set to free aspect, so dragging the game view around changes the scene view representation.

    I've found that in order to actually edit canvas prefabs well, I have to either be on a multi-screen setup (where the game view is on a secondary monitor), or lock the resolution of the game view.

    It would be nice to be able to tell the prefab view what resolution I want.
     
    ammirea likes this.
  8. HonorableDaniel

    HonorableDaniel

    Joined:
    Feb 28, 2007
    Posts:
    2,965
    I just have my Game view tabbed alongside my Scene view. Works like a charm.
     
  9. DavidBarlia_AofL

    DavidBarlia_AofL

    Joined:
    Jul 10, 2019
    Posts:
    2
    This looked like just the solution I've been searching for... until I had a UI prefab nested beneath another UI prefab. When I open up the top-level prefab, everything looks great. When I continue into the nested prefab, all the alignments and sizing go wonky as they did before I created a UI Environment scene to match my game scene.

    My Canvas setup is using Screen Space - Camera, with a dedicated UI Camera in the scene.
    I'm using Unity 2018.4.2f1 on Mac.
     
  10. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,803
    RGV likes this.
  11. Schmekz

    Schmekz

    Joined:
    Mar 11, 2016
    Posts:
    7
    Bumped into the problem with canvas size tied to game view size when I was editing UI prefabs in Unity 2019.2. Tried several ways to change canvas size and came to a solution that works and meets my needs.

    You can find script by link below. Code has comments and easy to understand. In short, when you open prefab the special component is automatically added to the root game object of prefab. That component allows you to set size for environment canvas. When you close prefab the component automatically gets destroyed. It works without introducing any changes to your prefab. There are several options to control canvas size:

    upload_2019-11-20_4-18-25.png

    https://github.com/menshikh/UnityUtils/blob/master/Assets/PrefabStageCanvasSize.cs

    P.S. It wasn't tested thoroughly, so let me know if you find any issues.
     
    Last edited: Nov 20, 2019
  12. HashbangGames

    HashbangGames

    Joined:
    May 7, 2011
    Posts:
    39

    This is genius! It worked perfectly and solved the problem!
     
    Schmekz likes this.
  13. gonzolot

    gonzolot

    Joined:
    Jul 15, 2013
    Posts:
    1
    Schmekz: Wow, thanks!
     
  14. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    26
    So wonderful... Thank you

    Is there a way to keep it on the object, or remember the X/Y and Mode?
     
  15. Schmekz

    Schmekz

    Joined:
    Mar 11, 2016
    Posts:
    7
    With some code modifications. Do you need to keep different settings per prefab or to store global settings (to edit next prefab using values set last time)?
     
  16. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    26
    Ideally values used last time on that prefab... but just value use last time (global) would be quite good also
     
  17. Schmekz

    Schmekz

    Joined:
    Mar 11, 2016
    Posts:
    7
    Try this version. Now resizer component can be saved in prefab. If you change any value, prefab becomes dirty, so you just need to click Save as usual.

    What I've done:
    1) Extracted resizer component from static class.
    2) Removed code that deleted resizer on prefab closing.
    3) Removed custom editor for resizer to allow dirtying of the prefab.

    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4.  
    5. #if UNITY_EDITOR
    6. using UnityEditor;
    7. using UnityEditor.Experimental.SceneManagement;
    8.  
    9. /// <summary>
    10. /// Watches for state changes of prefab stage.
    11. /// Adds special component to the root game object when prefab gets open.
    12. /// See related thread:
    13. /// http://forum.unity.com/threads/any-way-to-set-canvas-settings-for-prefab-mode.569923/#post-5159192
    14. /// </summary>
    15. [InitializeOnLoad]
    16. static class PrefabStageCanvasSizeWatcher
    17. {
    18.     static PrefabStageCanvasSizeWatcher()
    19.     {
    20.         if (EditorApplication.isPlaying)
    21.             return;
    22.  
    23.         PrefabStage.prefabStageOpened += stage =>
    24.         {
    25.             // get environment components
    26.             var envRT = stage.prefabContentsRoot.transform.parent as RectTransform;
    27.             var envCanvas = envRT?.GetComponent<Canvas>();
    28.             if (envRT == null || envCanvas == null)
    29.                 return; // non UI prefab
    30.  
    31.             // add resizer component to root game object of prefab
    32.             var resizer = stage.prefabContentsRoot.GetComponent<PrefabStageCanvasSize>()
    33.                         ?? stage.prefabContentsRoot.AddComponent<PrefabStageCanvasSize>();
    34.  
    35.             resizer.Init(envRT, envCanvas);
    36.         };
    37.     }
    38. }
    39. #endif
    40.  
    41. /// <summary>
    42. /// Changes environment canvas size according to chosen mode in the inspector.
    43. /// </summary>
    44. [ExecuteAlways]
    45. public class PrefabStageCanvasSize : MonoBehaviour
    46. {
    47.     // change default values if needed
    48.     public Vector2 ReferenceSize = new Vector2(1920, 1080);
    49.     public Mode CanvasSizeMode = Mode.ExpandUsingGameViewAspect;
    50.  
    51.     public enum Mode
    52.     {
    53.         ReferenceSize,
    54.         HeightFollowsGameViewAspect,
    55.         WidthFollowsGameViewAspect,
    56.         ExpandUsingGameViewAspect,
    57.         NativeBehaviour
    58.     }
    59.  
    60. #if UNITY_EDITOR
    61.     // components of environment game object
    62.     private RectTransform _envRect;
    63.     private Canvas _envCanvas;
    64.     private bool _isInitialized;
    65.     private Vector2 _lastSize;
    66.     private Mode _lastMode;
    67.  
    68.     public void Init(RectTransform envRect, Canvas envCanvas)
    69.     {
    70.         _envRect = envRect;
    71.         _envCanvas = envCanvas;
    72.         _isInitialized = true;
    73.  
    74.         Resize();
    75.     }
    76.  
    77.     public void Resize()
    78.     {
    79.         ReferenceSize.x = Math.Max(ReferenceSize.x, 10);
    80.         ReferenceSize.y = Math.Max(ReferenceSize.y, 10);
    81.  
    82.         _lastMode = CanvasSizeMode;
    83.         _lastSize = ReferenceSize;
    84.  
    85.         if (CanvasSizeMode == Mode.NativeBehaviour)
    86.         {
    87.             _envCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
    88.             _envRect.sizeDelta = Handles.GetMainGameViewSize();
    89.         }
    90.         else
    91.         if (CanvasSizeMode == Mode.ReferenceSize)
    92.         {
    93.             _envCanvas.renderMode = RenderMode.WorldSpace;
    94.             _envRect.sizeDelta = ReferenceSize;
    95.         }
    96.         else
    97.         {
    98.             var game = Handles.GetMainGameViewSize();
    99.             var size = ReferenceSize;
    100.  
    101.             switch (CanvasSizeMode)
    102.             {
    103.                 case Mode.ExpandUsingGameViewAspect:
    104.                 {
    105.                     float refAspect = size.x / size.y;
    106.                     float gameAspect = game.x / game.y;
    107.  
    108.                     if (refAspect < gameAspect)
    109.                         size.x *= gameAspect / refAspect;
    110.                     else
    111.                         size.y *= refAspect / gameAspect;
    112.                 }
    113.                 break;
    114.  
    115.                 case Mode.HeightFollowsGameViewAspect:
    116.                     size.y = size.x * game.y / game.x;
    117.                     break;
    118.  
    119.                 case Mode.WidthFollowsGameViewAspect:
    120.                     size.x = size.y * game.x / game.y;
    121.                     break;
    122.  
    123.                 default:
    124.                     throw new NotImplementedException(CanvasSizeMode.ToString());
    125.             }
    126.  
    127.             _envCanvas.renderMode = RenderMode.WorldSpace;
    128.             _envRect.sizeDelta = size;
    129.         }
    130.     }
    131.  
    132.     private void Update()
    133.     {
    134.         if (!_isInitialized)
    135.             return;
    136.  
    137.         bool mustResize =  CanvasSizeMode == Mode.ExpandUsingGameViewAspect
    138.                         || CanvasSizeMode == Mode.HeightFollowsGameViewAspect
    139.                         || CanvasSizeMode == Mode.WidthFollowsGameViewAspect
    140.                         || _lastMode != CanvasSizeMode
    141.                         || _lastSize != ReferenceSize;
    142.  
    143.         if (mustResize)
    144.             Resize();
    145.     }
    146. #endif
    147. }
    148.  
     
    Last edited: Mar 27, 2020
    Colin_MacLeod likes this.
  18. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    26
    Seem to work quite well... thank :)
     
    Schmekz likes this.
  19. Schmekz

    Schmekz

    Joined:
    Mar 11, 2016
    Posts:
    7
    Note that script name must remain the same: PrefabStageCanvasSize.cs
     
    Colin_MacLeod likes this.
  20. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    26
    Since the change, if user reference size, I need to quit the pre-fab and reopen it to see the X/Y change
     
  21. Schmekz

    Schmekz

    Joined:
    Mar 11, 2016
    Posts:
    7
    Fixed it right up there. Please try.
     
  22. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    26
    Sorry for the delay, yes it work well now... thank you once again :)
     
unityunity