Search Unity

How to disable (hide) UI elements without disabling them

Discussion in 'UGUI & TextMesh Pro' started by Aurecon_Unity, Nov 25, 2014.

  1. Aurecon_Unity

    Aurecon_Unity

    Joined:
    Jul 6, 2011
    Posts:
    241
    Hi

    I have an issue where I want to hide certain elements without actually disabling them.

    So if I have a toggle that turns another UI element on and off, how can I achieve this without changing the active state of the target element?

    The issue for me is that if the target element has a script attached and I want the element to start hidden (disabled), it also disables the attached script which I don't want to happen.

    In DFGUI this was handled by giving UI elements a 'Visible' toggle so you could change the visibility rather than the active state. An invisible object also allowed raycasts through.

    I did try adding a Canvas Group component and toggling the alpha, however even when alpha = 0 the elements were still being interacted with. For instance, if the element was a toggle and even when it was hidden (alpha = 0), I could still click where the toggle was and it would change the toggle state.

    Thanks
     
    BruceBai and Harinezumi like this.
  2. Mikeysee

    Mikeysee

    Joined:
    Oct 14, 2013
    Posts:
    155
    +1, this is super annoying and requires hacky workarounds.

    I have started a couple of other posts on this topic already..
     
    Plaximo and missplaced_manic like this.
  3. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Disable the component? GetComponent(Text).enabled = false;

    --Eric
     
  4. Aurecon_Unity

    Aurecon_Unity

    Joined:
    Jul 6, 2011
    Posts:
    241
    Hi Mikeysee, curious as to what the workarounds you found are. Easiest one I can think of is to move items out of the canvas range instead of toggling their active state.

    Eric, I don't think that will work - my elements contain child elements made up of different items (toggles, text, images etc) which won't always be the same amount - your way would involve specifying every sub item right? And hard coding them all into the solution which wouldn't work if more items are added / removed.

    The functionality in DFGUI works where the element and all child elements are hidden if the 'visible' checkbox is unticked. Essentially it performs the same way as setting the element as inactive, except that it's still active (just hidden).

    EDIT: The best solution would be too make the UI non-interactable (pass through raycasts / clicks / touches) when a Canvas Group is added and alpha set to 0.
     
    Railon23 likes this.
  5. Aurecon_Unity

    Aurecon_Unity

    Joined:
    Jul 6, 2011
    Posts:
    241
    I've just successfully tested another workaround that changes the scale of the Rect Transform to 0,0,0 when the element should be hidden - this keeps it hidden when it needs to be while staying active and not having to worry about moving things around.

    Still not ideal though...
     
    Konomira and misterpuper like this.
  6. Breyer

    Breyer

    Joined:
    Nov 10, 2012
    Posts:
    412
    Imo canvas renderer should work like mesh renderer where u could disable them in editor and via scripting.... im really suprised that actual canvas renderer is counter intuitive compared to mesh renderer

    As another workaround you probably could override OnFillVBO and add bool parameter to every script where u need hiding functionality but not ideal too
     
    MrEzman likes this.
  7. razielanarki

    razielanarki

    Joined:
    Jun 1, 2014
    Posts:
    58
    I had a run in with a similar problem, however for me the solution was to disable the hidden elements (which are complex nested panels in my case) and reinitialize their them to the correct state when enabling (this may need some refactoring separating "presenation" from "logic"), as invisible/non-interactable/non-blocking canvasgroups are still being rendered/meshed it seems, and this can affect performance in a big way (especially in the webplayer, but i suspect this is the case on mobile too)
     
    Last edited: Nov 25, 2014
  8. buggle52

    buggle52

    Joined:
    Nov 17, 2013
    Posts:
    5
    I'm just moving them to a non-canvas GameObject by changing their parent (I remembered from the vids that GUI objects only get rendered if they're under a canvas). Then I can make them visible again by moving them back into the canvas, though sometimes I have to check their positioning.
     
    Kamilche_ likes this.
  9. Aurecon_Unity

    Aurecon_Unity

    Joined:
    Jul 6, 2011
    Posts:
    241
    Hmm, I did forget about draw calls actually... using my hack of changing the scale to 0,0,0, it actually increases(!) draw calls when the object is 'hidden' (scale 0,0,0).

    So, this solution probably won't work.

    Any Unity devs here with an idea? Should I submit a bug?
     
    misterpuper likes this.
  10. akingdom

    akingdom

    Joined:
    Mar 30, 2013
    Posts:
    15
    If I have understood what is being asked, I have had success with...

    CanvasGroup cg = MyRectTransform.GetComponent<CanvasGroup>();
    cg.interactable= false;
    cg.alpha = 0;

    Edit: Don't forget to clear the
    BlockRaycasts on any overlaid RectTransforms.
     
    Last edited: Dec 12, 2014
    Geocake, Railon23, ilmario and 2 others like this.
  11. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    Unless I'm confused also then CanvasGroup should be the solution.
     
  12. Aurecon_Unity

    Aurecon_Unity

    Joined:
    Jul 6, 2011
    Posts:
    241
    Yep, it seems to work fine now - I can only assume there was an issue with it in previous betas, or I'm just a numpty... One thing though - is it possible for completely hidden (alpha = 0) CanvasGroup elements to not be drawn? ie - even when something is hidden it still seems to take up draw calls.
     
  13. akingdom

    akingdom

    Joined:
    Mar 30, 2013
    Posts:
    15
    Maybe try gameObject.SetActive(false); for the relevant object?
    That works for me in a quick test.
     
  14. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    Hey there,

    If you have a bunch of elements mixed in that you want to turn on and off you could take advantage of camera layers. Group all elements that need to be toggled into their own layer and with code you could toggle the camera to not draw that layer. I am 80% sure you could do the same for the input module to stop input on that layer. (I am on my phone so it's slow to google)

    Regards
     
  15. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    Learned something new when I got home. This will not work. uGUI does not care about layers. Seems weird.
     
  16. Nikola-B

    Nikola-B

    Joined:
    Jan 31, 2014
    Posts:
    42
    Being able to disable the CanvasRenderer just like we can disable a Mesh Renderer to hide an individual object would be nice. Using a Canvas Group and setting Alpha to 0 doesn't provide control over each individual object within that Canvas Group plus there is additional processing required to alter the vertex colors of all those UiVertex?

    As far as I know disabling a Mesh Renderer was the most efficient way to make an object disappear.
     
    dkriver, Bencarbon and andywatts like this.
  17. SmartyP

    SmartyP

    Joined:
    Nov 15, 2012
    Posts:
    7
    I ran into a very odd bug (that only appeared on certain Android devices) relative to enabling/disabling UI items. Moving to using a .alpha on a CanvasGroup worked around the issue, but there are way more draw calls that route. I would really like a way to hide without draw calls or side effects to my scripts.
     
  18. qq83833224

    qq83833224

    Joined:
    Jan 15, 2015
    Posts:
    4
  19. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    +1 for needing to disable the component, not the object.
     
  20. Deleted User

    Deleted User

    Guest

    This worked for me, and I setup the script to be Universal; meaning, it can be used by any Game Object for any Tag. Here you go:

    // Variables
    GameObject popUp1;
    Vector3 currentPosition;
    public string tagName = "";

    // Use this for initialization
    void Start () {
    // Let's hide the pop-up for now
    popUp1 = GameObject.FindWithTag (tagName);
    currentPosition = popUp1.transform.localPosition;
    popUp1.transform.localPosition = new Vector3 (1000, 1000);
    }

    // Method for showing the pop-up
    void PopUp () {
    popUp1.transform.localPosition = currentPosition;
    }
     
    art092 likes this.
  21. lexacutable

    lexacutable

    Joined:
    Jan 24, 2014
    Posts:
    8
    I would also love to be able to disable this component. Just using the CanvasGroup is a no-go due to having some children that ignore their parent groups.
     
  22. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    I accidentally came across a potential fix for this situation when I was trying to programmatically create a UI element and couldn't figure out why it wasn't showing up on screen (it was being created outside the UI canvas parent). I am going to try changing a UIObject's parent from the canvas to an empty GameObject called Disabled in the scene when I want to hide the panel (it won't be drawn), and I'll reparent it when I need it back.

    Having a 10 pane UI system is almost impossible when you're having to hunt down items and run coroutines that are attached to disabled objects. Nightmare!
     
    Harinezumi likes this.
  23. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Just use SetActive on the GameObject and put your code that needs to remain live elsewhere.
     
    montag64 and Harinezumi like this.
  24. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    From an OOP perspective, that makes for some extremely messy code IMO.

    Also, my solution works pretty well. I was able to implement it at 2 AM yesterday and haven't had any issues. Not sure what the performance impact would be on that but I assume changing a parent isn't too costly (just a reference change).
     
    Bencarbon and damp_phoenix like this.
  25. BMayne

    BMayne

    Joined:
    Aug 4, 2014
    Posts:
    186
    You could also do your own logic. All the UI is filled in the OnFillVBO function. Override that and it will not draw if you don't call base. You could also just extend the source.
     
    Kiwasi likes this.
  26. Tinjaw

    Tinjaw

    Joined:
    Jan 9, 2014
    Posts:
    518
    What about putting in an extra layer of abstraction. Parent the UI components to a GameObject. Then SetActive() on the parent GameObject.

    Thus Canvas > GameObject > UI Component;
     
  27. garraeth

    garraeth

    Joined:
    Apr 20, 2014
    Posts:
    10
    jackalkane's solution is working for me (so far). Do you think it's best to make the empty disabled GameObject scale 0x0x0, or leave it at 1x1x1?

    My concern with moving the panel/canvas around is the redrawing (which is why I like jackalkane's solution -- assuming it's not incurring the same draw calls...I'm not sure). That is probably going to be very slow on the device. I constantly get the "ArgumentException: Mesh can not have more than 65000 verticies" error. (My UI is complex.)

    Thanks.
     
  28. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    1,212
    I had this problem with my chat window, which I've defaulted to minimized because I'm still developing and don't need to see it much. The chat.text is inherently inactive because the ChatUI is turned off. So when anything tries to report "Exp gain" "You were hit" etc. it returns null and everything breaks.

    I worked around this because the script is still in existant, just the UI.Text is not. For example:
    Code (CSharp):
    1. public void AddChat (string chat) {
    2.         if (gameObject.activeSelf) {
    3.             chatText.text += "\n" + chat;
    4.         }
    5.         else {
    6.             if (builtUpStrings != "") {
    7.                 builtUpStrings += "\n" + chat;
    8.             }
    9.             else {
    10.                 builtUpStrings = chat;
    11.             }
    12.         }
    13.     }
    I build up the yet to be added strings in a string and then dump them into the chat OnEnable, whenever that happens. I assume this means you could program something outside of the script to call MyDisabledScript.RunUpdateForMeBro() and have it run any commands you need it to. The Monobehaviour in it however is not going to call the Update() for you.

    too lazy to test that bit, but my chat is working!
     
  29. llamagod

    llamagod

    Joined:
    Sep 27, 2015
    Posts:
    76
    One thing you can do is make a game object with a text component with no text, then increase the width and height until it covers the UI then activate/deactivate when needed. If you're using raycasts it will block it.
     
  30. sozeray

    sozeray

    Joined:
    Aug 24, 2013
    Posts:
    2
    You can do this by adding a "Canvas" element to the parent of the UI group that you want to hide. This makes it possible for you to stop/start rendering the group by setting the "enabled" property of the "Canvas" element as you wish.

    Important: You will notice that the method above results in touch events not working. You should also add "Graphics Raycaster" element to those groups which you've added the "Canvas" element. This fixes it.

    Hope this helps.
     
    Last edited: Jan 15, 2016
    blade_sk and forcepusher like this.
  31. smallbit

    smallbit

    Joined:
    Oct 3, 2013
    Posts:
    60
    I know is kind of old topic but I will share my observations. In my case disabling off screen stuff was to reduce drawcalls, my ui is setup in 5 horizontal pages, have had huge amount of drawcalls given that off screen pages don't cull.
    So here what I discovered based on all solutions here and elsewhere

    Disabling game object:
    On enabling back too big lag spike, especially on UI.text components (around 1MB for GC)

    Scaling to 0.0.0:
    On setting scale back to 1.1.1, draw calls double. Also substantial GC alloc.

    Moving off the canvas:
    On setting back to canvas more than double drawcalls, Colossal GC alloc.

    Setting separated layer and Culling it on the camera:
    Will only cull if canvas is set to screen space-camera. On Setting back drawcalls double. substantial GC

    Canvas.enabled
    Colossal lag spike on enabling back.

    Note all of them are too bad to be acceptable, I was considering to just accept my drawcalls or redesign the UI.

    Untill I found here my winner, which is
    CanvasGroup.alpha = 0;
    this has very little lag spike on setting back to 1. Now my UI is not laggy anymore :)

    Cheers
     
  32. ortin

    ortin

    Joined:
    Jan 13, 2013
    Posts:
    221
    @smallbit while you have your project can you test adding 2DRectMask component on root Canvas(es) and then just moving an element you need to hide offscreen?
     
  33. smallbit

    smallbit

    Joined:
    Oct 3, 2013
    Posts:
    60
    @ortin I tested this, and moving offscreen while having 2D rect mask on canvas does not reduce drawcalls at all. I had similar issue with scrollrect (very long one), I wrote a script for automatic scrollrect occlusion that helped a lot (thus was based on go.SetActive).
     
  34. ortin

    ortin

    Joined:
    Jan 13, 2013
    Posts:
    221
    Last edited: Jun 16, 2016
  35. smallbit

    smallbit

    Joined:
    Oct 3, 2013
    Posts:
    60
  36. TheGering

    TheGering

    Joined:
    Nov 26, 2012
    Posts:
    29
    here, look at my code for disabling the graphic on a toggle element, to toggle between two graphics rather than blending a checkbox over the background:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3.  
    4. namespace UnityEngine.UI
    5. {
    6.     [ExecuteInEditMode]
    7.     public class ToggleGraphicSwap : MonoBehaviour {
    8.  
    9.         Toggle _toggle;
    10.         Toggle toggle {
    11.             get { return _toggle ?? (_toggle = GetComponent<Toggle>()); }
    12.         }
    13.  
    14.         void Awake() {
    15.             toggle.onValueChanged.AddListener(OnTargetToggleValueChanged);
    16.         }
    17.  
    18.         void OnEnable() {
    19.             toggle.targetGraphic.enabled = !toggle.isOn;
    20.         }
    21.  
    22.         void OnTargetToggleValueChanged(bool on) {
    23.             toggle.targetGraphic.enabled = !on;
    24.         }
    25.     }
    26. }
    27.  
     
  37. disturbingon3

    disturbingon3

    Joined:
    Jul 6, 2012
    Posts:
    26
    FYI - this is a lifesaver!

    Lowered my gameplay from 200 -> 30 draw calls bro. Thanks!

    Untill I found here my winner, which is
    CanvasGroup.alpha = 0;
    this has very little lag spike on setting back to 1. Now my UI is not laggy anymore:)
     
    Railon23 likes this.
  38. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    I was reading through my posts that's over a year old now in this thread and I have to say, I 100% disagree with what I said then and have done an about-face. I'm working in a project with about 20k lines of code and 50 different classes with multiple scenes and at least 20 ui panes and it became utter hell (hell!!!) to work with moving stuff between the hidden and viewable ui canvases. I'll do my best to explain the reason why (and propose a solution).

    When I started working on this project and working within Unity in general, I was dragging quite a bit of game objects onto other game objects. In this case, specifically UI elements. So you want to build a menu system that takes you from one ui pane (say, clicking options button in menu pane) to bring you to another ui pane (options pane)? That's easy right? just drag and drop gameobjects and make everything public. Or at least that's what Unity makes you think you should do because it's such a friendly and simple way to do things.

    The reason why I couldn't do setactive(false) like what boredmormon says (btw, I read your posts about interfaces a while back, excellent info) is because i had my account logic tied into my game object scripts. So instead of using some MVC framework or even EC, for instance, I had my account login/integration (controllers) inside a monodevelop directly attached to the logon ui object. What happens if you disable the logon ui? Suddenly you lose all your references. Also sharing the same script with 3 pages of registration is extremely hairy when you have your data operations stored inside the same class. What happens when you want to move a button pane across scenes? then you lose all of your references to in-scene objects. For simple things or prefabs with self-contained elements, drag and drop is great... anything else It becomes a real nightmare. Don't create references to non prefabbed objects, and instead, do it all in script. Prefab as much as you can, especially with UI. If you need to create references on a prefab that exists in two different scenes, set up your view script on your ui objects to take note of what scene the game is in (by subscribing to scenemanagement.onscenechanged or whatever) and remapping your prefabs accordingly. Then instantiate any prefabbed ui you need on the fly, and destroy it when moving between ui panes. It's very clean and saves you from having to keep everything in memory all the time (even if it's disabled).

    Not only that but Unity made some change now a couple versions ago to where moving content between canvases where one is disabled seems to totally destroy the position values. I got away with a workaround by creating a viewable canvas and putting it on another monitor. I have a mobile game so this works but it an extremely dumb hack but it worked in a jam.

    My solution to all of this was rewrite 70% of my own project code and prefab everything like I described and redesigning the UI and code integrations. I've spent probably >60 hrs already on it but I'm pretty close to done. Needless to say the client wasn't exactly happy but fact was I had no idea what I was doing when I started with Unity. It's also made it a lot quicker already to make changes. Another added benefit is that I can copy the prefab to another scene, or another game project entirely.

    Also make sure you use events and interfaces when setting up your UI to keep it decoupled (There are some great tutorials on Unity's site that appeared not too long ago; I strongly recommend them). it'll make things a lot easier for you later.

    also @smallbit, I'm not sure what the draw call amounts/performance considerations are for instantiating/destroying ui. I assume more because you're instantiating a prefab and thus you'd be doing an IO call which is more expensive. I'm sure there would be a way for me to instantiate these and put them somewhere off screen but since my art is simple I really don't see any lag, even on older iPhones. If you end up testing or have any thoughts, I'd be interested to know what you find. I had memory issues on the iPad 2 keeping everything in scene so I think keeping it all in memory has its downsides as well depending on how advanced your UI is.
     
    Last edited: Feb 1, 2017
    frarf likes this.
  39. montag64

    montag64

    Joined:
    Mar 15, 2014
    Posts:
    23
    Also something that I found depressing was that I really missed the ease of the drag and drop for building prefabs. So I wrote some code that checks the children of the game obj on screen and binds correspondingly named objects to serialized fields (just like auto drag and drop, but in code). It uses reflection (oh noes! performance hit) but I've heard the later c# runtimes run reflection a bit more efficiently than before. Plus I only call it once.

    Here's the reflection code I put in a static util class. Wrap it in a for loop if you need to iterate through and match multiple buttons.

    Code (CSharp):
    1.        
    2.  
    3. //put this in your static utils class or wherever
    4. /// <summary>
    5.         /// Binds an object field to a component.
    6.         /// </summary>
    7.         /// <param name="objWithField">Object with field.</param>
    8.         /// <param name="gameComponent">Game component.</param>
    9.         /// <typeparam name="T">The gameobject with the fields you want to bind (typially this)</typeparam>
    10.         /// <typeparam name="K">The game component you want to bind to the field of gameObj T (typically buttons, text, etc)</typeparam>
    11.         public static void BindObjFieldToComponent<T,K>(T objWithField, K gameComponent)
    12.             where T : MonoBehaviour where K : Component {
    13.  
    14.             //get the type and then of the type get the field of the same name a the game component.
    15.             //the binding flags signifiy to get all fields regardless of access level. Then, lastly, set the field value with
    16.             //the name-matched component.
    17.             objWithField.GetType().GetField(gameComponent.name, BindingFlags.NonPublic | BindingFlags.Instance |
    18.                 BindingFlags.Public | BindingFlags.IgnoreCase).SetValue(objWithField, gameComponent);
    19.         }
    20.  
    21. //then you'd wrap it like below and put it in the awake class of your prefabbed ui game object:
    22.  
    23. foreach(Button button inthis.gameObject.GetComponentsInChildren<Button>())
    24. {
    25.       Utils.BindObjFieldToComponent(this,button);
    26. }
    27.  
    28.  

    This is a script for a 2 buttoned-popup window I wrote that I can customize instead of creating a dozen prefabs of generic popups. I also wanted to have the client have an option to generate popups arbitrarily from a database with text content without me having to rebuild the game every time someone has some marketing idea.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Events;
    5. using UnityEngine.UI;
    6.  
    7. namespace MyGameProject {
    8.     public class PopUpView_2Button : MonoBehaviour {
    9.  
    10.         Text headerText;
    11.         Text mainText;
    12.         Text leftButton;
    13.         Text rightButton;
    14.         GameObject leftAction;
    15.         GameObject rightAction;
    16.  
    17.         /// <summary>
    18.         /// Sets the user interface elements.
    19.         /// </summary>
    20.         /// <param name="headerText">Header text.</param>
    21.         /// <param name="mainText">Main text.</param>
    22.         /// <param name="leftButtonText">Left button text.</param>
    23.         /// <param name="rightButtonText">Right button text.</param>
    24.         /// <param name="leftButtonAction">Left button action.</param>
    25.         /// <param name="rightButtonAction">Right button action.</param>
    26.         public void InitUIElements (string headerText, string mainText, string leftButtonText, string rightButtonText, UnityAction leftButtonAction, UnityAction rightButtonAction) {
    27.  
    28.             foreach (Text childText in this.gameObject.transform.GetChild(0).GetComponentsInChildren<Text>()) {
    29.          
    30.                 switch (childText.name) {
    31.  
    32.                     case "HeaderText":
    33.                         childText.text = headerText;
    34.                         break;
    35.                     case "MainText":
    36.                         childText.text = mainText;
    37.                         break;
    38.                     case "leftButtonText":
    39.                         childText.text = leftButtonText;
    40.                         childText.transform.parent.GetComponent<Button>().onClick.AddListener(leftButtonAction);
    41.                         break;
    42.                     case "rightButtonText":
    43.                         childText.text = rightButtonText;
    44.                         childText.transform.parent.GetComponent<Button>().onClick.AddListener(rightButtonAction);
    45.                         break;
    46.                 }
    47.             }
    48.         }
    49.     }
    50. }
     
    Last edited: Feb 1, 2017
  40. nights007

    nights007

    Joined:
    Aug 12, 2014
    Posts:
    17
    He said WITHOUT disabling them.
     
  41. hamberge

    hamberge

    Joined:
    Aug 30, 2015
    Posts:
    36
    Funny, this guy above turned this into a zombie thread. However, it brings up a good point.

    Yes, this is important. The GUI objects should simply call functions that are exposed by other, persistent objects, like managers, and/or only have scripts related to display and functioning of the GUI itself, and not related to game logic. Any complicated game logic should not be placed on a GUI object script. One way to achieve this is to create a manager game object with nothing visible. For example, a game manager object or a player manager object or something. Then all substantive code can go there. You could even have multiple such objects.
     
  42. forcepusher

    forcepusher

    Joined:
    Jun 25, 2012
    Posts:
    227
    Thanks for writing that up. Seems like this is the intended way to switch between UI states and disable/enable major UI panels. CanvasGroup in the other hand is intended be used for smaller grouped elements within the child canvas.

    I wish Unity made this page earlier, I wasted too much time on silly things... https://unity3d.com/learn/tutorials/topics/best-practices/fundamentals-unity-ui
     
    blade_sk likes this.
  43. LyonLoi

    LyonLoi

    Joined:
    Oct 31, 2013
    Posts:
    3
    I'm surprised that no one knows the simple way out. lol
    What you need to do is:
    1. Create a layer call "UI"(if there's not one already), and set every UI element's layer to "UI"
    2. On the top right, click on "layers" and make "UI" invisible.
    3. Done.

    You can create more layers to hide certain UI only. Like UI_a UI_b UI_c
     
    Last edited: Mar 6, 2018
  44. smallbit

    smallbit

    Joined:
    Oct 3, 2013
    Posts:
    60
    The discussion here is about the runtime, what you talk about is an editor function.

    On the topic, in the 2 years since my last post, Unity exposed a lot of information about UI but the most efficient method remains the same (Canvas group alpha)
     
    Railon23 and forcepusher like this.
  45. CubeFlix

    CubeFlix

    Joined:
    Sep 9, 2017
    Posts:
    15
    You could use alpha transparency, like this:
    UIOBJECT.color = new Color(0, 0, 0, 0);

    This will make the color transparent with the fourth alpha transpareny.
     
  46. dreg_master

    dreg_master

    Joined:
    Jan 4, 2016
    Posts:
    44
    Using a Canvas group solved it form me with Alpha. I am still using bools and setActive() on the menu structure and sub-menus, but at least now i can close all Canvases at once and come straight back to where i left off.


    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class NewBehaviourScript : MonoBehaviour
    6. {
    7.     //The Canvas that i have attached a Canvas Group to (currently 2)
    8.     public CanvasGroup[] cg;
    9.  
    10.     //At start of my game these 2 canvases are off.
    11.     [SerializeField]private bool canvasesAre = false;
    12.     //The button responsible for toggling the Canvas Group
    13.     private Button CoreButton;
    14.  
    15.     // Use this for initialization
    16.     private void Start()
    17.     {
    18.         //Get button and start listening to it
    19.         CoreButton = GetComponent<Button>();
    20.         CoreButton.onClick.AddListener(() => ToggleMainMenu());
    21.  
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     private void Update() {}
    26.  
    27.     private void ToggleMainMenu()
    28.     {
    29.         //Switch Canvases on or off
    30.         canvasesAre = !canvasesAre;
    31.         foreach (CanvasGroup cv in cg)
    32.         {
    33.             if (canvasesAre)
    34.             {
    35.                 cv.alpha = 1;
    36.                 cv.interactable = true;
    37.             }
    38.             else
    39.             {
    40.                 cv.alpha = 0;
    41.                 cv.interactable = false;
    42.             }
    43.         }
    44.     }
    45. }
    46.  
     
    Railon23 likes this.
  47. forcepusher

    forcepusher

    Joined:
    Jun 25, 2012
    Posts:
    227
    Finally there is an official answer on this question from Unity Technologies.
    See "How to hide a Canvas" section:
    https://unity3d.com/how-to/unity-ui-optimization-tips
    That wraps it up.
    I told you guys.
     
    Last edited: Jun 19, 2018
    Ultroman and vanxining like this.
  48. Steve-Tou

    Steve-Tou

    Joined:
    Aug 4, 2018
    Posts:
    10
    This 'answer' doesn't solve the original posted problem. I am trying to save data from Inputfields that are on Canvases. My 'game' (3D) involves stopping at different locations, clicking on an 'investigation point' (sphere) which sets a Canvas active with a Question and Answer Panel with Toggles and/or InputFields used to answer the question. There will be different versions and/or modules of the 'game' that will be created. Infinite possibilities of investigative points exist as versions/modules are developed. I simply want the player to be able to save (and reload) their data they have entered with a single button click from a main menu screen, not have to have a save button (and reload button) in each investigation point Canvas. This would be done in a case where they want to come back later to complete their investigations, or possibly to then print up a 'GOOD WORK!!' certificate once they have gotten all the correct answers at all points (which would need another script to compare all the answers to the correct ones). Data in an Inputfield is not found via script when the parent Canvas is inactive. Still looking for a good way to do this. Thanks.
     
  49. vorelv

    vorelv

    Joined:
    Sep 27, 2019
    Posts:
    1
    What about
    Code (CSharp):
    1. this.canvas.targetDisplay = 2
    ?
     
  50. as3mbus

    as3mbus

    Joined:
    Dec 5, 2016
    Posts:
    71
    sorry for necro bumping this. but i don't find proper solution for this problem.
    using canvas group, yes it might help and it is the closest one that unity teams recommended and most ppl agreed with it's being having best performance.

    but is using canvas group for multiple pooled object is feasible ?
    i am currently using grid layout group where i need game object to stay active for the layout group to allocate rect space for it's siblings.

    i don't think using canvas group for each pooled object is somewhat good idea, unless it is a group where an object object can be assigned. or is there any other trick am i missing either with grid layout or canvas group.