Search Unity

Any way to set canvas settings for prefab mode?

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

  1. stopiccot_tds

    stopiccot_tds

    Joined:
    Oct 1, 2016
    Posts:
    111
    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

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    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.
     
    xenofusion, furkan83, NukeGs and 18 others like this.
  3. stopiccot_tds

    stopiccot_tds

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

    RGV

    Joined:
    Jan 25, 2016
    Posts:
    48
    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:
    2
    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

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    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.
     
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    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.
     
  8. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    I just have my Game view tabbed alongside my Scene view. Works like a charm.
     
    ow3n likes this.
  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

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    RGV likes this.
  11. menshikh

    menshikh

    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
    Novack, colinleet, asorgejr and 9 others like this.
  12. HashbangGames

    HashbangGames

    Joined:
    May 7, 2011
    Posts:
    40

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

    gonzolot

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

    Morphus74

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

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

    menshikh

    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:
    174
    Ideally values used last time on that prefab... but just value use last time (global) would be quite good also
     
  17. menshikh

    menshikh

    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:
    174
    Seem to work quite well... thank :)
     
    menshikh likes this.
  19. menshikh

    menshikh

    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:
    174
    Since the change, if user reference size, I need to quit the pre-fab and reopen it to see the X/Y change
     
  21. menshikh

    menshikh

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

    Morphus74

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

    AlejMC

    Joined:
    Oct 15, 2013
    Posts:
    149
    On Unity 2020 it seems to work, however not always? If I go inside a nested prefab it says "Prefab in Context" and for sure it is not using neither the Regular or UI editing environments nor 'the context Canvas' in which it was when it got opened.
    The UI Editing Environment scene has: Canvas Raycaster/Scaler/All-AditionalShadersAttributes, etc.

    When opening a prefab from the browser it does have a custom canvas at the top with the UI Env settings, but opening in context it doesn't like the following:
    - The 'context' from which is to be opened from shows an UI Edit Environment one
    - The opened prefab from the previous step (Prefab in Context) just shows a Canvas component at the top with default Canvas values (none of the other Raycaster, Scaler, feed the additional shader attributes, etc)

    Is there a way to make this work like in 2019? or an option somewhere?

    EDIT: my bad, there's the option to open the 'prefab in isolation' which basically is the older default behaviour. Was not fully acquainted with what was going on and the new Prefab in context new (and nice!) workflow.
    It seems to be a bug to me then, that the highlighted prefab in context doesn't inherit fully the environment it was in when displaying it.

    EDIT #2: There's something really wrong going on. I use shortcuts to go in and out of prefabs (in 2019 being the default 'open in isolation' prefab).
    Currently that shortcut got auto assigned to 'open prefab in context' which has the above mentioned UI Edit Environment issues. There's also another shortcut on the 'Stages' section called 'Go Back' and a new one 'Open Prefab In Isolation'. Using Open Prefab In Isolation shortcut and Go Back shortcut together: Go Back actions always goes back to the scene and not the nested prefab it was opened from. Using Alt Click Open on the prefab inspector option, opens in isolation (similar to the shortcut) but in that case Go Back shortcut works as expected. Alt Click Open and Open Prefab In Isolation shortcut do not seem to do the same operation.
     
    Last edited: Oct 8, 2020