Search Unity

UI Button create by script C#

Discussion in 'UGUI & TextMesh Pro' started by Korigoth, Dec 16, 2014.

  1. Korigoth

    Korigoth

    Joined:
    Jul 21, 2014
    Posts:
    105
    I'm dissapointed that i find no documentation for creating the UI from script....

    i tried Instantiate... failed.... create Canvas.gameObject.addComponent<Button>.... nothing happennned.....

    what do i need to do to create a button.............

    Why the new UI system need to be harder than the previous one.....
    i agree the old one was so crappy ..... but now that we evolved .... no documentation on How to script what was previously so easy....


    How can we create a simple button in our canvas....?

    i found 10000 post about listenner.... it was easy to understand but.... it didnt tell how to create the button from script.... :(
     
    a_m_pdr and ChatAttack like this.
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,413
    The easiest way is to make a prefab of a button, then use Instantiate to make a copy of it, and then attach the copy to your canvas, or some other element.

    I haven't tried it yet, but if you want to make it from scratch I assume you make a new GameObject, change its parent to your canvas or whatever, add a RectTransform, then set all the values up.
     
    dylanboots and rakibj56 like this.
  3. Korigoth

    Korigoth

    Joined:
    Jul 21, 2014
    Posts:
    105
    its not working ....


    i can instantiate the button prefab....
    i can put the prefab in his parent.... NICE!

    but their F***ing function that SET the position of the rect... is just not working at alll....
    so my button appear
    Left -41
    Top 562
    ... so nice i got the Transform of the Canvas that doesnt exist!!! yay
    Why they were not able to put the rectTransform as parent...
     
  4. Korigoth

    Korigoth

    Joined:
    Jul 21, 2014
    Posts:
    105
    i got it finaly....

    SOLUTION 4.6

    var button = Instantiate(RoomButton, Vector3.zero, Quaternion.identity) as Button;
    var rectTransform = button.GetComponent<RectTransform>();
    rectTransform.SetParent(Canvas.transform);
    rectTransform.offsetMin = Vector2.zero;
    rectTransform.offsetMax = Vector2.zero;
    button.onClick.AddListener(SpawnPlayer);

    thx for ur help Darkcoder
     
  5. Korigoth

    Korigoth

    Joined:
    Jul 21, 2014
    Posts:
    105
    helper method to create the button in his anchor possition

    should create a helper method to easily change anchor position if u want to create a list of button

    here is my create button helper cause i hate seeing 6 line for 1 object creation!

    public static Button CreateButton(Button buttonPrefab, Canvas canvas, Vector2 cornerTopRight, Vector2 cornerBottomLeft)
    {
    var button = Object.Instantiate(buttonPrefab, Vector3.zero, Quaternion.identity) as Button;
    var rectTransform = button.GetComponent<RectTransform>();
    rectTransform.SetParent(canvas.transform);
    rectTransform.anchorMax = cornerTopRight;
    rectTransform.anchorMin = cornerBottomLeft;
    rectTransform.offsetMax = Vector2.zero;
    rectTransform.offsetMin = Vector2.zero;
    return button;
    }
     
    Last edited: Dec 16, 2014
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Or you just let the layout elements do the positioning for you.

     
    FelipeCoronado, Kekaku and RemDust like this.
  7. _MGB_

    _MGB_

    Joined:
    Apr 24, 2010
    Posts:
    74
    I found the CRITICAL way to get this working was to use worldPositionStays = false in the SetParent call:

    var btn = (GameObject)Instantiate(Resources.Load("MyButton"));
    <set pos here>
    btn.transform.SetParent(InfoPanel.transform, false);
     
    Last edited: Dec 17, 2014
    NetoColina, S3rD4n73 and madeye92 like this.
  8. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Because this is still a top hit on Google, and no-one had answered correctly (I knew there was a correct answer, but the name of the API is so badly named that it's imposible to find unless you already know the name):

    Unity provides an API call that creates each UnityUI thing directly from script, with all the required pieces, exactly as if you'd made it in Editor, sparing you from a *lot* of easy-to-make mistakes that lead to difficult-to-tract bugs in your code:
    https://docs.unity3d.com/Packages/com.unity.ugui@1.0/api/UnityEngine.UI.DefaultControls.html

    For a button:

    If you're going to customise the button image, this is fine,
    otherwise use my longer version below: https://forum.unity.com/threads/ui-button-create-by-script-c.285829/#post-9149029

    Code (CSharp):
    1.  
    2. Assumes you'll add a custom background image to the button
    3.  
    4. GameObject var newButton = DefaultControls.CreateButton(
    5. new DefaultControls.Resources()
    6. );
    7. newButton.transform.SetParent(canvas.transform, false);
    8.  
    NB: this works great for simple examples. For complex examples ... Unity broke some of the more complex UI controls in some versions of the Editor (I logged bugs against it, with 1-line-of-code reproductions that showed someone at Unity had broken the API, but Unity's QA team don't know how to read code (!) and kept rejecting it, eventually I gave up reporting it. I think it's working again in latest versions)
     
    Last edited: Jul 15, 2023
  9. philipecarter

    philipecarter

    Joined:
    Nov 5, 2022
    Posts:
    2
    This worked for me, but since this was posted before TextMeshPro existed, it created a legacy Button. To create a TMP button:
    TMP_DefaultControls.Resources resources = new TMP_DefaultControls.Resources();
    GameObject button = TMP_DefaultControls.CreateButton(resources);
     
    a436t4ataf and DaMahdi03 like this.
  10. klosterj

    klosterj

    Joined:
    Nov 4, 2022
    Posts:
    2
    I'm still extremely new to Unity and C#, so I'm sorry if this is a dumb question. Let's say that I'm trying to make a loop to create a new button based on data being pulled in from an outside source (reading from a database or a file). Do you have any suggestion on how to incorporate this into a loop, like each line read in file, create button per info. Also, When you write the SetParent line, what if the script is placed into the Parent I already want? As in, I have a scrollable window with a grid layout group, and the script is under that.
     
  11. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Off-topic, but ... if you want all buttons to be identical, nothign more than e.g. change the text on each one, then you'd find it easier to make a Prefab, and then use it like a 'stamp' to create many new buttons (see the Instantiate() method - used very widely in Unity) -- this is the 'normal' way of doing UI in Unity, although the docs have traditionally been weak at telling people this. A *lot* of UnityUI basically requires you to know that this is the 'expected' approach.

    HOWEVER. This thread is more for when you need to make changes/customizations to each and every button -- so that you'd need to make 10x prefabs, or 100x prefabs, instead of just one, which is way too much effort -- so instead: you do the customizations in script, and then you can use just one prefab (or none!) and have the script do all the hard work. But that requires you to be able to 'create new button via a script'.

    ...

    After all that, no matter which option you choose, you need a layout system to control how your new buttons get positioned + sized. I am enormously biased, and tell everyone to use my asset :D (2023 version about to go on asset store, you can read about it here in the next few days when the website goes live: https://flexbuilder.ninja/) - or you have to use the built-in UnityUI layout system and learn the details of LayoutGroups, ContentSizeFitters, etc -- and their many *many* bugs and gotchas.

    OR ... you can use UIToolkit (which isn't quite production ready yet - and is missing a lot of features/has bugs compared to my asset (they both use Flexbox, but Unity's version of Flexbox they admit is incomplete, and they plan to rewrite it later this year/next year I believe - once they rewrite it, sometime in 2024, it will be great))
     
  12. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Returning to add some missing code that most people probably want/need...

    If you want a fully default standard button there's a little bit more you have to do. My original example was fine if you want to customize the background image, but if you want a default BG image from Unity, you need this instead:


    Code (CSharp):
    1.  
    2. DefaultControls.Resources uiResources = new DefaultControls.Resources();
    3. foreach(Sprite sprite in Resources.FindObjectsOfTypeAll<Sprite>())
    4. {
    5.   if( sprite.name == "UISprite" )
    6.   {
    7.     uiResources.standard = sprite;
    8.     break;
    9.   }
    10. }
    11. GameObject var NewButton = DefaultControls.CreateButton(uiResources);
    12. newButton.transform.SetParent(canvas.transform, false);
    13.  
    Note: if you're going to do this thousands of times in a single frame then you should cache the reference to uiResources and not re-create it for each one - you only need it to refresh it when Editor reloads assemblies etc. But for most cases you'll only call this once every few minutes or similar and won't notice the cost/won't care.
     
    AvatharBehemoth likes this.