Search Unity

Creating a GUI from code

Discussion in 'UGUI & TextMesh Pro' started by StephanieRowlinson, Aug 21, 2014.

  1. StephanieRowlinson

    StephanieRowlinson

    Joined:
    Jul 23, 2014
    Posts:
    137
    I've been messing about with the new GUI and I can't figure out how to create a Canvas with a Button on it from code without using prefabs.

    So far I've got:

    Code (CSharp):
    1.  
    2. GameObject canvas  = new GameObject("canvas", typeof(Canvas));
    3. GameObject button = new GameObject("button");
    4. button.AddComponent<Button>();
    5. button.transform.parent = canvas.transform;
    But that's not working. Am I missing something obvious or should I just add all the necessary components to the canvas GameObject manually?

    EDIT:

    So I went and added all the components manually and now I have a button. Is there an easier/quicker way to do this than:

    Code (CSharp):
    1.  
    2. GameObject canvas  = new GameObject("canvas", typeof(RectTransform));
    3.         canvas.AddComponent<Canvas>();
    4.         canvas.AddComponent<GraphicRaycaster>();
    5.         GameObject button = new GameObject("button", typeof(RectTransform));
    6.         button.AddComponent<Button>();
    7.         button.AddComponent<CanvasRenderer>();
    8.         button.AddComponent<Image>();
    9.         button.transform.parent = canvas.transform;
    10.  
     
    Last edited: Aug 21, 2014
  2. arturmandas

    arturmandas

    Joined:
    Sep 29, 2012
    Posts:
    240
    I can't seem to be able to access Button component at all, do you have to add some directive? My code:

    var buttonConnect = GameObject.Find("Button_Connect").GetComponent<Button>();

    buttonConnectGameObject.onClick.AddListener(DoConnect());
     
  3. DESTRUKTORR

    DESTRUKTORR

    Joined:
    Jul 4, 2012
    Posts:
    22
    You need to either use the UnityEngine.UI namespace, or apply the namespace every time you reference the Button class.

    Use SetParent(Transform parent, bool worldPositionStays)

    You can find this in the unity docs. As far as I've found, it's best to set worldPositionStays to false (if you're using camera space).
     
    rakkarage likes this.
  4. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,689
    @SRowlinson Your second set of code looks fie and yes that's how it's made up at the moment. Only through the editor are the dependant components added automatically.
    However there will only ever be one Canvas, so that would only need to be done once (You will also need an Event System if you want to actually click the button).

    As for the button it'self you could create a prefab of your button setup to make it quicker or create your own control.

    All the UI elements are effectively script components now, not bulky objects as before.

    With great power and flexibility, comes great responsibility.

    Hope this helps
     
  5. Taschenschieber

    Taschenschieber

    Joined:
    Jun 8, 2014
    Posts:
    238
    I have a similar problem right now, and I tried solving it by creating a Button prefab - which instantiates just fine, but is completely invisible both in game mode and edit mode during pauses. I can resize and move it, but it is completely invisible.

    Same thing happens if I drag the prefab into the scene hierarchy in Edit Mode.

    I'll probably go ahead and steal... um... borrow SRowlinson's code, but it would be a lot easier and more consistent with usual Unity behaviour if this could just be done with a prefab.

    (*grumble* I just wanted to mess around with the new UI for a couple of minutes and then it was so much fun that I ended up redoing my whole UI. Curse you, Unity, you're just too good! -.-)

    EDIT: It seems that for whatever reason Unity set the Scale for my button to (0,0,0) while instantiating the prefab. Setting the scale to (1,1,1) after instantiating fixed the problem for me.

    EDIT#2: Now I have a follow-up question: how do I access a component's anchor in a script? Anybody figured that out yet? Because the docs don't mention that.
     
    Last edited: Aug 21, 2014
  6. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I came up with this code. It creates a button with a text on it. The problem is - the button doesn't react to user input. Something is still missing.

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.UI;
    4.  
    5. public class CreateButton : MonoBehaviour
    6. {
    7.     private void Start()
    8.     {
    9.         if (FindObjectOfType<EventSystem>() == null)
    10.         {
    11.             var es = new GameObject("EventSystem", typeof(EventSystem));
    12.             es.AddComponent<StandaloneInputModule>();
    13.         }
    14.  
    15.         var canvasObject = new GameObject("Canvas");
    16.         var canvas = canvasObject.AddComponent<Canvas>();
    17.         canvas.renderMode = RenderMode.Overlay;
    18.  
    19.         var buttonObject = new GameObject("Button");
    20.         var image = buttonObject.AddComponent<Image>();
    21.         image.transform.parent = canvas.transform;
    22.         image.rectTransform.sizeDelta = new Vector2(180, 50);
    23.         image.rectTransform.anchoredPosition = Vector3.zero;
    24.         image.color = new Color(1f, .3f, .3f, .5f);
    25.  
    26.         var button = buttonObject.AddComponent<Button>();
    27.         button.targetGraphic = image;
    28.         button.onClick.AddListener(() => Debug.Log(Time.time));
    29.  
    30.         var textObject = new GameObject("Text");
    31.         textObject.transform.parent = buttonObject.transform;
    32.         var text = textObject.AddComponent<Text>();
    33.         text.rectTransform.sizeDelta = Vector2.zero;
    34.         text.rectTransform.anchorMin = Vector2.zero;
    35.         text.rectTransform.anchorMax = Vector2.one;
    36.         text.rectTransform.anchoredPosition = new Vector2(.5f, .5f);
    37.         text.text = "Привет, мир!";
    38.         text.font = Resources.FindObjectsOfTypeAll<Font>()[0];
    39.         text.fontSize = 20;
    40.         text.color = Color.yellow;
    41.         text.alignment = TextAnchor.MiddleCenter;
    42.     }
    43. }
     
  7. primaerfunktion

    primaerfunktion

    Joined:
    Jan 16, 2012
    Posts:
    98
    Oh boy. Was just getting into porting my UI, looked up how to add buttons via code, found this and now I think I'll stick with the old system for that part at least...
     
  8. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    That will create a button, but it won't create and set up and EventSystem. You also need to add an event system and a raycast module to the canvas.
     
    p87 likes this.
  9. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Thank you. I added GraphicRaycaster to the canvas and the button came to life.

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.UI;
    4.  
    5. public class CreateButton : MonoBehaviour
    6. {
    7.     private void Start()
    8.     {
    9.         if (FindObjectOfType<EventSystem>() == null)
    10.         {
    11.             var es = new GameObject("EventSystem", typeof(EventSystem));
    12.             es.AddComponent<StandaloneInputModule>();
    13.         }
    14.  
    15.         var canvasObject = new GameObject("Canvas");
    16.         var canvas = canvasObject.AddComponent<Canvas>();
    17.         canvasObject.AddComponent<GraphicRaycaster>();
    18.         canvas.renderMode = RenderMode.Overlay;
    19.  
    20.         var buttonObject = new GameObject("Button");
    21.         var image = buttonObject.AddComponent<Image>();
    22.         image.transform.parent = canvas.transform;
    23.         image.rectTransform.sizeDelta = new Vector2(180, 50);
    24.         image.rectTransform.anchoredPosition = Vector3.zero;
    25.         image.color = new Color(1f, .3f, .3f, .5f);
    26.  
    27.         var button = buttonObject.AddComponent<Button>();
    28.         button.targetGraphic = image;
    29.         button.onClick.AddListener(() => Debug.Log(Time.time));
    30.  
    31.         var textObject = new GameObject("Text");
    32.         textObject.transform.parent = buttonObject.transform;
    33.         var text = textObject.AddComponent<Text>();
    34.         text.rectTransform.sizeDelta = Vector2.zero;
    35.         text.rectTransform.anchorMin = Vector2.zero;
    36.         text.rectTransform.anchorMax = Vector2.one;
    37.         text.rectTransform.anchoredPosition = new Vector2(.5f, .5f);
    38.         text.text = "Привет, мир!";
    39.         text.font = Resources.FindObjectsOfTypeAll<Font>()[0];
    40.         text.fontSize = 20;
    41.         text.color = Color.yellow;
    42.         text.alignment = TextAnchor.MiddleCenter;
    43.     }
    44. }
     
    marinedzl likes this.
  10. JasonBooth

    JasonBooth

    Joined:
    Jan 27, 2014
    Posts:
    649
    I've been using uGui in out project for a while, but am still using the old gui system for some UI's that are much easier to construct with code. If you just want a big list of sliders, GUILayout.BeginVertical() has a nice workflow and doesn't requite all the messy hookup/objects of uGui..

    Tonight I thought I'd play with an idea; a class which allows you to construct uGUI controls the same way you would with the old gui system. The problem I'm having is that it doesn't seem like you can create a control and set it's position right away; if I print out the positions on Update(), they are different than what I set. If I wait a frame before setting them, then things work as expected. Why would that be? Does an internal layout function blow away my values?

    The interesting code is here:

    Code (CSharp):
    1.     public static RectTransform BeginSubControl()
    2.     {
    3.         GameObject go = new GameObject();
    4.         RectTransform t = go.AddComponent<RectTransform>();
    5.         if (subControls.Count > 0)
    6.         {
    7.             t.parent = subControls.Peek();
    8.         }
    9.         subControls.Push(t);
    10.         t.anchoredPosition = Vector2.zero;
    11.         t.anchorMin = new Vector2(0, 1);
    12.         t.anchorMax = new Vector2(0, 1);
    13.         t.offsetMax = Vector2.zero;
    14.         t.offsetMin = Vector2.zero;
    15.         t.pivot = currentPosition;
    16.    
    17.         t.localPosition = new Vector3(currentPosition.x, currentPosition.y, 0);
    18.         return t;
    19.     }
    20.  
    However, when printing those values in Update(), anchor position is set to 0, -1244.9, causing the control to appear in the wrong position.


    Full code of the layout class idea posted below:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine.UI;
    5.  
    6. // like GUILayout, but for uGui. Allows you to construct editors from prefab'd controls quickly
    7.  
    8.  
    9. public class uGuiLayout
    10. {
    11.     private static Stack<RectTransform> subControls = new Stack<RectTransform>();
    12.  
    13.     private static Vector2 currentPosition = new Vector2(0,0);
    14.  
    15.     public enum Mode
    16.     {
    17.         Horizontal,
    18.         Vertical
    19.     }
    20.  
    21.     public static Stack<float> positionCache = new Stack<float>();
    22.     public static Stack<Mode>  modeCache = new Stack<Mode>();
    23.  
    24.     public static void BeginHorizontal()
    25.     {
    26.         positionCache.Push(currentPosition.x);
    27.         modeCache.Push(Mode.Horizontal);
    28.         RectTransform t = BeginSubControl();
    29.         t.gameObject.AddComponent<HorizontalLayoutGroup>();
    30.  
    31.     }
    32.     public static void EndHorizontal()
    33.     {
    34.         currentPosition.x = positionCache.Pop();
    35.         modeCache.Pop();
    36.         EndSubControl();
    37.     }
    38.     public static void BeginVertical()
    39.     {
    40.         BeginSubControl();
    41.         positionCache.Push(currentPosition.y);
    42.         modeCache.Push(Mode.Vertical);
    43.         RectTransform t = BeginSubControl();
    44.         t.gameObject.AddComponent<VerticalLayoutGroup>();
    45.     }
    46.     public static void EndVertical()
    47.     {
    48.         currentPosition.y = positionCache.Pop();
    49.         modeCache.Pop();
    50.         EndSubControl();
    51.     }
    52.    
    53.     public static RectTransform BeginSubControl()
    54.     {
    55.         GameObject go = new GameObject();
    56.         RectTransform t = go.AddComponent<RectTransform>();
    57.         if (subControls.Count > 0)
    58.         {
    59.             t.parent = subControls.Peek();
    60.         }
    61.         subControls.Push(t);
    62.         t.anchoredPosition = Vector2.zero;
    63.         t.anchorMin = new Vector2(0, 1);
    64.         t.anchorMax = new Vector2(0, 1);
    65.         t.offsetMax = Vector2.zero;
    66.         t.offsetMin = Vector2.zero;
    67.         t.pivot = currentPosition;
    68.    
    69.         //t.localPosition = new Vector3(currentPosition.x, currentPosition.y, 0);
    70.         return t;
    71.     }
    72.  
    73.     public static void EndSubControl()
    74.     {
    75.         subControls.Pop();
    76.     }
    77.  
    78.     public static void AddChild(RectTransform trans)
    79.     {
    80.         trans.parent = subControls.Peek();
    81.         trans.anchoredPosition = currentPosition;
    82.     }
    83.  
    84.     public static Text Label(string text, string name = "Text")
    85.     {
    86.         GameObject go = new GameObject(name);
    87.         Text t = go.AddComponent<Text>();
    88.         t.text = text;
    89.         AddChild(t.rectTransform);
    90.         return t;
    91.     }
    92.  
    93.     //public static void Slider(float value, float min = 0.0f, float max = 0.0f);
    94. }
    95.  
    and the test code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TestGuiLayout : MonoBehaviour {
    5.  
    6.     // Use this for initialization
    7.  
    8.     RectTransform root;
    9.     void Start ()
    10.     {
    11.         root = uGuiLayout.BeginSubControl();
    12.         root.parent = GetComponent<Canvas>().transform;
    13.  
    14.         uGuiLayout.BeginVertical();
    15.  
    16.         uGuiLayout.Label("My Label");
    17.  
    18.         uGuiLayout.EndVertical();
    19.         uGuiLayout.EndSubControl();
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         Debug.Log (root.anchoredPosition + "   " + root.anchorMin + "    " + root.anchorMin + "   " + root.offsetMin + "    " + root.offsetMax
    25.                    + "    " + root.pivot + "   " + root.sizeDelta + "    " + root.localPosition);
    26.     }
    27.  
    28. }
    29.  
     
    JakubNei likes this.
  11. StephanieRowlinson

    StephanieRowlinson

    Joined:
    Jul 23, 2014
    Posts:
    137
    @slipster216

    A wrapper class does seem like a good idea. Perhaps a set of "empty" prefabs in combination with a framework that allows you to easily create them in code would be the best way to go. Looks like transitioning from the old GUI system to new one will take some thinking.
     
  12. JasonBooth

    JasonBooth

    Joined:
    Jan 27, 2014
    Posts:
    649
    I'm actually interested in completely creating controls via code. For instance, wouldn't it be nice to be able to create a combo box and have a single object/api to interact with? Right now, you have to set up half a dozen objects in an interconnected ball of tar with no central interface. Yes, you can prefab it, but if you want to, say, prefab the panel it's on, then the prefab connections will all be lost on your combo box, breaking any way for you to centrally update things.

    The other thing this allows is easy dynamic interfaces - the current model is great for fixed UIs, but as soon as you need to dynamically create the UI based on some data, it's not particularly usable.
     
  13. senritsu

    senritsu

    Joined:
    Dec 12, 2012
    Posts:
    37
    @slipster216
    From how it sounded, when the sources are released (or you feel like decompiling) you can look at how the built in components like Button, Slider, etc. are implemented and use a similar approach to make your own. There should be hardly any limitations this way for complex custom controls.
     
  14. StephanieRowlinson

    StephanieRowlinson

    Joined:
    Jul 23, 2014
    Posts:
    137
    Hmm, I see your point. I think that you could still use prefabs for dynamic GUIs only you'd have to create really low level ones. So you have button prefab, a slider prefab etc at which point I guess you might as well just create them from code.

    This is actually one of the things I run into with Unity for time to time, a lot of the design choices have been made with fixed levels and a pretty linear flow in mind. So it can be tricky to set up stuff like terrain or in this case the uGUI in a way that allows you to use it in a more dynamic environment.
     
  15. JasonBooth

    JasonBooth

    Joined:
    Jan 27, 2014
    Posts:
    649
    Thought I'd write an update on this in case anyone cares. Before really being able to tackle programatic layouts, I needed to make the creation/skinning/reuse of complex controls easier.

    Right now if you want something like a combo box, it's about 8 objects with a ton of components on them, plus at least one object per item in the list. This is a royal pain to manage. Even a simple button with text is two objects, which means you need to programmatically look up the text component from the button reference, etc.

    I'm not a big fan of this. I want my controls to be encapsulated. I like that they can be made of simple components, but I don't want to HAVE to make them from this mess every time, because it's extremely error prone and finicky.

    So, here's what I'm doing for my combo box:

    Installed in the UI menu is a ComboBox option. It creates a RectTransform with my "StyledComboBox" component on it. This component has two public fields, one for a ComboBoxPrefab and another for a prefab for the items which will populate the combo box. When the component is created (or the prefabs are changed in the editor), the component instantiates the prefab and stretches the prefab to fill the current rect. All the internal objects are hidden from the user - you only see the original ComboBox object you created in the hierarchy window.

    The StyledComboBox component acts as a single API for the entire system. I can get/set/add/remove items from it, and it will handle new instances as well as passing the data to the items inside of it. For instance, our combo box's item prefab might use the StyledImageText component. When it gets instantiated, it's Populate(object o) function is called on it, and it can see if o is a text, image, or both. So populating the combo box looks like so:

    Code (CSharp):
    1.  
    2.         // just text
    3.         comboBox.AddItems("Test1", "Test2", "Test3", "F***", "I", "Don't", "Believe", "This", "S***", "Isn't", "Included");
    4.  
    5.         // text + images
    6.         comboBox.AddItems(new StyledComboBox.Data("Text", myTexture));
    7.  
    Now, if one of my artists decides they'd like to skin the combo box, or the items inside it, all they have to do is duplicate the prefab and set it up the way they want. Then they can drag the prefab onto any combo box they want to use the new style.

    This gives me styling, smaller project files (since none of the controls are stored in the file, rather instantiated on the fly), and I can prefab my panels (since again, it's not really storing the prefab in the scene - just an object which knows how to instantiate it).

    Overall, I'll likely wrap every control this way - even a button with a label is two objects, and I want one API/Pointer to deal with on every control type. I still haven't gotten the combo box to work correctly - it currently populates the control and it's items correctly, but there seem to be numerous masking bugs and such that prevent it from fully working correctly.

    Honestly, I really wish I didn't have to write this kind of stuff - I spend approximately 20% of my time working on my game, and the bulk of the time making Unity robust enough to actually ship a large project with. If prefab's could a) be nested, and b) hide objects/properties from the user of the prefab (encapsulation!), then none of this would be necessary. Sigh..
     
    rakkarage likes this.
  16. senritsu

    senritsu

    Joined:
    Dec 12, 2012
    Posts:
    37
    Correct me if i'm wrong, but isn't it actually possible to hide objects in the hierarchy?
    http://docs.unity3d.com/ScriptReference/HideFlags.HideInHierarchy.html
    And hiding properties from the inspector of course works too, unless you mean something different by that.

    Nested prefabs are direly needed though, at least they are confirmed for some 5.x version i think. Still too far off for my taste D:
     
  17. JasonBooth

    JasonBooth

    Joined:
    Jan 27, 2014
    Posts:
    649
    Yes, I currently hide them in the hierarchy. I have noticed that I seem to crash unity a lot if I use hideAndDontSave though, which is the flag I really want to use since there's no advantage to saving the data in the file. I have to think there's some issue with references not being destroyed correctly when you use that flag, or perhaps I have to be careful not to serialize anything which might contain a reference to the objects. Not sure, but I've submitted several bugs about it so hopefully they'll get fixed or an error thrown if it's due to something under my control.
     
  18. sz-Bit-Barons

    sz-Bit-Barons

    Joined:
    Nov 12, 2013
    Posts:
    150
    Just wanted to show my solution for the problem (I didn't read the whole thread, but it looks like there wasn't any good solution yet).

    I made a little helper class to store the transformation data and revert the transformation afterwards to that values:
    Code (CSharp):
    1.     public class RectTransformInfo
    2.     {
    3.         public Vector3 LocalPosition, LocalScale;
    4.         public Quaternion LocalRotation;
    5.         public Vector2 AnchorMin, AnchorMax, AnchoredPosition, SizeDelta, Pivot;
    6.  
    7.         public RectTransformInfo(RectTransform transform)
    8.         {
    9.             LocalPosition = transform.localPosition;
    10.             LocalScale = transform.localScale;
    11.             LocalRotation = transform.localRotation;
    12.  
    13.             AnchorMin = transform.anchorMin;
    14.             AnchorMax = transform.anchorMax;
    15.             AnchoredPosition = transform.anchoredPosition;
    16.             SizeDelta = transform.sizeDelta;
    17.             Pivot = transform.pivot;
    18.         }
    19.      
    20.         public void CopyTo(RectTransform transform)
    21.         {
    22.             transform.localPosition = LocalPosition;
    23.             transform.localScale = LocalScale;
    24.             transform.localRotation = LocalRotation;
    25.  
    26.             transform.anchorMin = AnchorMin;
    27.             transform.anchorMax = AnchorMax;
    28.             transform.anchoredPosition = AnchoredPosition;
    29.             transform.sizeDelta = SizeDelta;
    30.             transform.pivot = Pivot;
    31.  
    32.         }
    33.     }
    how to use it:
    Code (CSharp):
    1.         GameObject go = GameObject.Instantiate(myPrefab) as GameObject;
    2.      
    3.         RectTransformInfo tmpTransform = new RectTransformInfo(go.transform as RectTransform);
    4.         go.transform.parent = myCanvas.transform;
    5.         tmpTransform.CopyTo(go.transform as RectTransform);
     
  19. keiranlovett

    keiranlovett

    Joined:
    May 9, 2013
    Posts:
    16

    Have you figured out the positioning solution? I'm interested in this method and I'm unable to find a solution myself.
     
  20. QI

    QI

    Joined:
    Oct 27, 2012
    Posts:
    229
    Here's the code how UI's menuitem creating canvas.
    Code (CSharp):
    1. static public GameObject GetOrCreateCanvasGameObject()
    2.         {
    3.             GameObject selectedGo = Selection.activeGameObject;
    4.  
    5.             // Try to find a gameobject that is the selected GO or one if its parents.
    6.             Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
    7.             if (canvas != null && canvas.gameObject.activeInHierarchy)
    8.                 return canvas.gameObject;
    9.  
    10.             // No canvas in selection or its parents? Then use just any canvas..
    11.             canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas;
    12.             if (canvas != null && canvas.gameObject.activeInHierarchy)
    13.                 return canvas.gameObject;
    14.  
    15.             // No canvas in the scene at all? Then create a new one.
    16.             return MenuOptions.CreateNewUI();
    17.         }
    18.  
    19.         static public GameObject CreateNewUI()
    20.         {
    21.             var root = new GameObject("Canvas");
    22.             root.layer = LayerMask.NameToLayer(kUILayerName);
    23.             Canvas canvas = root.AddComponent<Canvas>();
    24.             canvas.renderMode = RenderMode.ScreenSpaceOverlay;
    25.             root.AddComponent<CanvasScaler>();
    26.             root.AddComponent<GraphicRaycaster>();
    27.             Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);
    28.  
    29.             CreateEventSystem(false, null);
    30.             return root;
    31.         }
    32.  
    33.         private static void CreateEventSystem(bool select, GameObject parent)
    34.         {
    35.             var esys = Object.FindObjectOfType<EventSystem>();
    36.             if (esys == null)
    37.             {
    38.                 var eventSystem = new GameObject("EventSystem");
    39.                 GameObjectUtility.SetParentAndAlign(eventSystem, parent);
    40.                 esys = eventSystem.AddComponent<EventSystem>();
    41.                 eventSystem.AddComponent<StandaloneInputModule>();
    42.                 eventSystem.AddComponent<TouchInputModule>();
    43.  
    44.                 Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
    45.             }
    46.  
    47.             if (select && esys != null)
    48.             {
    49.                 Selection.activeGameObject = esys.gameObject;
    50.             }
    51.         }
    Just call GetOrCreateCanvasGameObject when you need to access active canvas, and it will create one if not a single one exists.
     
  21. Sortest

    Sortest

    Joined:
    Mar 4, 2015
    Posts:
    3
    Thanks! Very useful!
     
  22. TerQ

    TerQ

    Joined:
    Jan 28, 2016
    Posts:
    2
    You can also use my Procedural UI package. You wouldn't need to worry about elements instancing and positioning. Windows are scalable and movable, and they require just a few lines of code to work :)
    Assetstore link here