Tasharen Entertainment Forum

Support => NGUI 3 Documentation => Topic started by: ArenMook on November 20, 2013, 10:39:58 PM

Title: UIButton
Post by: ArenMook on November 20, 2013, 10:39:58 PM
Overview

Button is a simple component designed to receive hover, pressed and click events, and change the color of a remote sprite. You can also optionally attach an Image Button component to the same game object to get sprite swapping functionality as well.

(http://www.tasharen.com/ngui/button.jpg)

A button can be anything. It doesn't have to be a widget. You can put a Button component on anything that has a collider. Regardless, you will most commonly be using the Button component in your UI hierarchy -- generally alongside a UI Sprite or on the game object directly above it.

In order for the button to work, the camera that's drawing the object where you place the Button component must have a UICamera script attached, as that's what sends out events. You must also have "Raycast Hit Triggers" turned on in the Physics Settings in your project.

Button works by receiving mouse over, press and click events, and translates them into appropriate color-changing actions on your the object specified in your Target field. This will most commonly be a widget (sprite, label, or texture), but can also be an object with a Light, or even a Renderer.

If you want to trigger a remote function when you click on the button, drag & drop the target game object into the "Notify" field, then choose the function from the drop-down list. Note that in order for the function to show up, it must be of "public void FuncName (void)" type. For example:
  1. public void MyClickFunction()
  2. {
  3.     Debug.Log("I was clicked!");
  4. }
Built-in components, such as tweens, have an assortment of pre-made functions for you to choose from (for example: PlayForward).

Pro-Tip #1

It's generally a good idea to put the Button component on the same game object as the button's background sprite. Hit ALT+SHIFT+C to quickly create a collider, and check the "Box Collider" option on the sprite so that the box collider auto-updates as you resize the sprite.

Pro-Tip #2

UIButton comes with only an OnClick notification. If you want OnPress, OnHover, OnSelect, OnDoubleClick, and/or others -- attach UIEventTrigger script to your button (or any other object for that matter).

Class Documentation

http://tasharen.com/ngui/docs/class_u_i_button.html

If you have a question regarding this component or would like me to clarify something, just post a reply here.
Title: Re: UIButton
Post by: christianschulze on January 15, 2014, 06:47:11 AM
The new On Click Box is awesome! Is it possible to get an On Press, too? It would be nice to have for touch input because buttons seem more responsive with OnPress events. I know there's still the Button Message script, but with that a function name has to be provided and can't be chosen from a dropdown. So this is just a comfort question ;) Thanks!
Title: Re: UIButton
Post by: christianschulze on January 15, 2014, 10:35:46 AM
Never mind! I extended the UIButton Message script and have the following:

UIButtonMessageExtended.cs
  1. //----------------------------------------------
  2. //            NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2014 Tasharen Entertainment
  4. //----------------------------------------------
  5.  
  6. using UnityEngine;
  7. using System.Collections.Generic;
  8.  
  9. /// <summary>
  10. /// Sends a message to the remote object when something happens.
  11. /// </summary>
  12.  
  13. [AddComponentMenu("NGUI/Interaction/Button Message Extended")]
  14. public class UIButtonMessageExtended : MonoBehaviour
  15. {
  16.         public enum Trigger
  17.         {
  18.                 OnClick,
  19.                 OnMouseOver,
  20.                 OnMouseOut,
  21.                 OnPress,
  22.                 OnRelease,
  23.                 OnDoubleClick,
  24.         }
  25.  
  26.         //public GameObject target;
  27.         //public string functionName;
  28.         public Trigger trigger = Trigger.OnPress;
  29.         //public bool includeChildren = false;
  30.  
  31.         static public UIButtonMessageExtended current;
  32.         public List<EventDelegate> eventDelegates = new List<EventDelegate>();
  33.  
  34.         bool mStarted = false;
  35.  
  36.         void Start () { mStarted = true; }
  37.  
  38.         void OnEnable () { if (mStarted) OnHover(UICamera.IsHighlighted(gameObject)); }
  39.  
  40.         void OnHover (bool isOver)
  41.         {
  42.                 if (enabled)
  43.                 {
  44.                         if (((isOver && trigger == Trigger.OnMouseOver) ||
  45.                                 (!isOver && trigger == Trigger.OnMouseOut))) {
  46.                                 //Send();
  47.                                 current = this;
  48.                                 EventDelegate.Execute(eventDelegates);
  49.                                 current = null;
  50.                         }
  51.                 }
  52.         }
  53.  
  54.         void OnPress (bool isPressed)
  55.         {
  56.                 if (enabled)
  57.                 {
  58.                         if (((isPressed && trigger == Trigger.OnPress) ||
  59.                                 (!isPressed && trigger == Trigger.OnRelease))) {
  60.                                 //Send();
  61.                                 current = this;
  62.                                 EventDelegate.Execute(eventDelegates);
  63.                                 current = null;
  64.                         }
  65.                 }
  66.         }
  67.  
  68.         void OnSelect (bool isSelected)
  69.         {
  70.                 if (enabled && (!isSelected || UICamera.currentScheme == UICamera.ControlScheme.Controller))
  71.                         OnHover(isSelected);
  72.         }
  73.  
  74.         void OnClick () {
  75.                 if (enabled && trigger == Trigger.OnClick) {
  76.                         //Send();
  77.                         current = this;
  78.                         EventDelegate.Execute(eventDelegates);
  79.                         current = null;
  80.                 }
  81.         }
  82.  
  83.         void OnDoubleClick () {
  84.                 if (enabled && trigger == Trigger.OnDoubleClick) {
  85.                         //Send();
  86.                         current = this;
  87.                         EventDelegate.Execute(eventDelegates);
  88.                         current = null;
  89.                 }
  90.         }
  91.         /*
  92.         void Send ()
  93.         {
  94.                 if (string.IsNullOrEmpty(functionName)) return;
  95.                 if (target == null) target = gameObject;
  96.  
  97.                 if (includeChildren)
  98.                 {
  99.                         Transform[] transforms = target.GetComponentsInChildren<Transform>();
  100.  
  101.                         for (int i = 0, imax = transforms.Length; i < imax; ++i)
  102.                         {
  103.                                 Transform t = transforms[i];
  104.                                 t.gameObject.SendMessage(functionName, gameObject, SendMessageOptions.DontRequireReceiver);
  105.                         }
  106.                 }
  107.                 else
  108.                 {
  109.                         target.SendMessage(functionName, gameObject, SendMessageOptions.DontRequireReceiver);
  110.                 }
  111.         }
  112.         */
  113. }
  114.  

UIButtonMessageExtendedEditor.cs (needs to be placed in a Folder named "Editor")
  1. //----------------------------------------------
  2. //            NGUI: Next-Gen UI kit
  3. // Copyright © 2011-2014 Tasharen Entertainment
  4. //----------------------------------------------
  5.  
  6. using UnityEngine;
  7. using UnityEditor;
  8.  
  9. [CanEditMultipleObjects]
  10. [CustomEditor(typeof(UIButtonMessageExtended))]
  11. public class UIButtonMessageExtendedEditor : UIWidgetContainerEditor
  12. {
  13.  
  14.         private bool argFoldout = true;
  15.  
  16.         public override void OnInspectorGUI ()
  17.         {
  18.                 NGUIEditorTools.SetLabelWidth(80f);
  19.                 UIButtonMessageExtended buttonMessage = target as UIButtonMessageExtended;
  20.  
  21.                 GUILayout.Space(6f);
  22.  
  23.                 buttonMessage.trigger = (UIButtonMessageExtended.Trigger)EditorGUILayout.EnumPopup("Trigger", buttonMessage.trigger);
  24.  
  25.                 GUILayout.Space(3f);
  26.  
  27.                 NGUIEditorTools.DrawEvents(buttonMessage.trigger.ToString(), buttonMessage, buttonMessage.eventDelegates);
  28.  
  29.                 argFoldout = EditorGUILayout.Foldout(argFoldout, "Arguments");
  30.                 if(argFoldout) {
  31.                         buttonMessage.intArg = EditorGUILayout.IntField("Integer", buttonMessage.intArg);
  32.                         buttonMessage.floatArg = EditorGUILayout.FloatField("Float", buttonMessage.floatArg);
  33.                         buttonMessage.strArg = EditorGUILayout.TextField("String", buttonMessage.strArg);
  34.                 }
  35.  
  36.                 if(GUI.changed) {
  37.                         UnityEditor.EditorUtility.SetDirty(buttonMessage);
  38.                 }
  39.         }
  40. }
  41.  

Seems to work :)
Title: Re: UIButton
Post by: ArenMook on January 15, 2014, 10:13:35 PM
Yup, nice job. :)
Title: Re: UIButton
Post by: dyego_s on January 16, 2014, 01:23:05 PM
Never mind! I extended the UIButton Message script and have the following:

Your script doesn't work with new NGUI
Title: Re: UIButton
Post by: christianschulze on January 16, 2014, 01:41:51 PM
I'm using version 3.0.8 f7. What error message do you get? Have you tried to put the Editor script UIButtonMessageExtendedEditor.cs into a Folder named "Editor"?
Title: Re: UIButton
Post by: dyego_s on January 16, 2014, 02:12:56 PM
I'm using version 3.0.8 f7. What error message do you get? Have you tried to put the Editor script UIButtonMessageExtendedEditor.cs into a Folder named "Editor"?

Sorry, I didn't know that. I put it in the right place and...your script works fine. :) if you want to support, when I try to call UIButton.current.name with your script I get null exception.
Title: Re: UIButton
Post by: christianschulze on January 17, 2014, 04:24:50 AM
I updated the script above to the current state, but you're right. current is null and not set. I copied the code for this from UIButton where current is set to null after the event execution "EventDelegate.Execute(...);" and I don't have a solution, yet.
Title: Re: UIButton
Post by: AbsurdInteractive on January 23, 2014, 03:22:01 PM
If you want to make a UIImageButton, do you attach a UIButton script and UIImageButton script to the same gameobject? Or do you just attach the UIImageButton script?
Title: Re: UIButton
Post by: ArenMook on January 24, 2014, 10:44:19 AM
Just UIImageButton. UIButton will do the coloring, UIImageButton will do the sprite swap. Up to you what you want.
Title: Re: UIButton
Post by: sintua on February 05, 2014, 02:35:24 PM
What determines if the button should be set to the Disabled color?
Also, is the event system that needed "void MethodName(gameObject ClickedButton)" no longer being used?
Title: Re: UIButton
Post by: ArenMook on February 05, 2014, 04:44:29 PM
If the collider is disabled, so is the button.

Button OnClick notification is an NGUI EventDelegate, which has a "void FuncName()" signature. To get the button that was clicked, use UIButton.current.
Title: Re: UIButton
Post by: PoN on February 07, 2014, 05:43:43 AM
How to set Notify field by code ? And why UIButton component being disabled after Play Unity ? I would like set Notify field to instantiated GameObject with UIButton component.
Title: Re: UIButton
Post by: sintua on February 07, 2014, 01:22:04 PM
If the collider is disabled, so is the button.

Button OnClick notification is an NGUI EventDelegate, which has a "void FuncName()" signature. To get the button that was clicked, use UIButton.current.

Hm, I've tried disabling the collider, and while the button was disabled in functionality, the color did not change to disabled unless I directly changed the "isEnabled" property on UIButton.

And I meant the UIEventListener.Get(btn).OnClick still uses the void method(Gameobject obj) format, while the *other* onclick on the button is the void method() with UIButton.current. Is there a reason these use different calls? is UIEventListener going to be updated to use the parameterless void method and UIButton.current as well, or is there a reason it still has the gameobject parameter?
Title: Re: UIButton
Post by: ArenMook on February 08, 2014, 01:33:17 PM
@PoN: Button script will disable itself if there is nothing for it to color. You get a warning about it in the console log. You must give it something to work with.

@sintua: EventListener is different from UIButton. EventListener uses system delegates, while everything else uses NGUI delegates (which can be set via inspector). System delegates are a tiny bit faster, and UIEventListener was created long before NGUI delegate system was added, so it wouldn't make sense for me to break backwards compatibility to modify the UIEventListener to use NGUI calls.
Title: Re: UIButton
Post by: sintua on February 09, 2014, 09:31:55 PM
Thanks for clarifying! I wasn't sure why the difference was there, helpful to know.
Title: Re: UIButton
Post by: PoN on February 09, 2014, 10:17:38 PM
Aren thanks, but how could i use OnPress on my component ? before i used :
  1.         void OnPress (bool pressed)
  2.         {
  3.                 if (enabled && pressedSprite != null)
  4.                 {
  5.                         pressedSprite.depth = (pressed)?11:7;
  6.                 }
  7.         }
  8.  

And how implements this now, with new EventDelegate ?
Title: Re: UIButton
Post by: ArenMook on February 11, 2014, 09:02:06 PM
You can still use the same OnPress function. Nothing has changed that. Event functions work as they did before. NGUI sends events, your scripts can receive them if they implement the appropriate functions, such as your "void OnPress (bool pressed)".

Now, if you wanted to have OnPress on some object trigger your own function elsewhere, consider looking at UIEventTrigger if you want it to be settable from inspector.

If not, UIEventListener.Get(targetGameObject).onPress += YourPressFunction; -- but this will expect your function to be "void YourPressFunction (GameObject go, bool pressed);"
Title: UIButton bug report
Post by: zf223669 on March 04, 2014, 10:04:11 PM
 in version 3.5.3,in UIButton Component,when I has chosen a sprite in Hover popup,now i want to delete it ,but it do not worK
Title: Re: UIButton
Post by: nzen on March 05, 2014, 04:53:32 PM
After clicking a button with the mouse, how do we stop Joystick Button 0 from pressing it after?

Right now, I have to click the button, then click away from it to lose focus so the Xbox A button won't press it after.
Title: Re: UIButton
Post by: ArenMook on March 06, 2014, 12:15:43 PM
@zf223669: Choose the same sprite as "Normal". I've added the delete button in 3.5.4, so you will see it when it goes live.

@nzen: Disable Controller Input on your UICamera.
Title: Re: UIButton
Post by: SamK on April 04, 2014, 12:50:46 AM
Hi ,
I can't find the UIEventTrigger script anywhere in the project. Neither in the interaction folder nor anywhere else.
I have NGUI 3.07 f3.
I need to perform some action on button press. OnPress
can you help in this regard ?
Title: Re: UIButton
Post by: ArenMook on April 04, 2014, 10:47:40 PM
You need to update NGUI. In the future always update before posting.
Title: Re: UIButton
Post by: Nikul on April 06, 2014, 03:50:58 PM
Hi, I'm using the UIEventTrigger on a button to initiate a bullet fire function via OnPress, then stop the function via OnRelease. The problem is if I drag my finger off the button(mobile), the UIButton script switches the button to normal, not pressed and the function continues to run because my finger is still down. Can we have an OnDragOut option in UIEventTrigger so we can end a button press if the finger is moved off the button but still pressed on the screen?
Title: Re: UIButton
Post by: yahodahan on April 06, 2014, 07:51:33 PM
So, the click can still call a function, and (I don't precisely remember how this was done), pass the button object as a parameter, right? If I use the "UIEvent..." option, that is. Could I be reminded of how to get that object?

Any way to also pass through some value, which would be set (theoretically) on the button via inspector?

For example, a I have a big scrolly list of "map" thumbnails. I click on a map, that click needs to tell a "manager" script to swap the game to that map, base on what was clicked. I'd love to just pass an int, use it as an index in my maps array, etc.

Just being able to pass the Button Object itself will be workable, though :)

Thanks!
Title: Re: UIButton
Post by: ArenMook on April 08, 2014, 01:22:14 AM
@Nikul: Certainly. I'll add it to the next update.

@yahodahan: You can pass anything you like via event delegates as of 3.5.6.
Title: Re: UIButton
Post by: Kevin Nguyen on May 12, 2014, 08:57:46 PM
Pro-Tip #2

UIButton comes with only an OnClick notification. If you want OnPress, OnHover, OnSelect, OnDoubleClick, and/or others -- attach UIEventTrigger script to your button (or any other object for that matter).

I can't find it! :(
Title: Re: UIButton
Post by: ArenMook on May 13, 2014, 09:17:59 AM
If you can't find the Event Trigger, then you are not on the latest NGUI version.
Title: Re: UIButton
Post by: ababilinski on May 25, 2014, 12:39:30 PM
To all who want to access the notify field in another script  :D! You gave to add an EventDelegate.
  1. EventDelegate Event = new EventDelegate();
  2. Event.set("The Code You Want To Set","The Function You Want To Call(As A String")
  3. UIButtonObject.GetComponent<UIButton>().onClick.Add(Event);
  4.  

Hope it helps people,
ababilinski :)
Title: Re: UIButton
Post by: PoN on May 29, 2014, 03:34:23 AM
Example pls ? don't understand what is first param in Set method;
Title: Re: UIButton
Post by: ArenMook on May 29, 2014, 08:24:06 AM
  1. void Start ()
  2. {
  3.     UIButton btn = GetComponent<UIButton>();
  4.     EventDelegate.Add(btn.onClick, MyFunction);
  5. }
  6.  
  7. public void MyFunction ()
  8. {
  9.     Debug.Log("Clicked!");
  10. }
Title: Re: UIButton
Post by: PoN on July 14, 2014, 10:10:14 PM
Aren , Why this component doesn't have a text property , which set a text on a UILabel component of control button ? i think that is right logic for the UIButton component, like in other languages, for example .NET WindowForms - Button class or JavaFX. so what do you think ?
Title: Re: UIButton
Post by: ArenMook on July 15, 2014, 01:00:40 AM
How often would something like this be needed? I don't like cluttering the inspector window with seldom-used functionality. For something like that simply write a new script that would change the specified label's text in its OnHover / OnPress functions.
Title: Re: UIButton
Post by: justkevin on July 19, 2014, 01:06:09 PM
How do I set the default color of a button in script?

If I change defaultColor, the change doesn't show up until the next time the user interacts with the button (e.g., by hovering).

The documentation talks about UpdateColor in the the parent class, but that method doesn't seem to exist?
Title: Re: UIButton
Post by: ArenMook on July 20, 2014, 11:50:04 AM
UIButton.normalColor
Title: Re: UIButton
Post by: Cyphermage on August 11, 2014, 03:24:18 AM
Hi guys, I'm working out UIButtons at the moment. I've set a UISprite on the same element as my UIButton, and set the colours (for normal, hover, pressed, disabled) in UIButton.

The colours/states work if I put a Box Collider on the object, but not if I use a Box Collider 2D.  Is there a reason UIButton needs to have a non-2D collider?  It seems strange to me.  Am I doing something wrong, or have I misunderstood some functionality?
Title: Re: UIButton
Post by: ArenMook on August 12, 2014, 07:33:31 AM
UICamera type events define what kind of raycasts are done -- either 3D, or 2D.
Title: Re: UIButton
Post by: vikti on August 28, 2014, 11:38:50 AM
I have a function here attached to a Sprite :

  1.         public void OnPress(bool isPressed){
  2.                 if(isPressed) {
  3.                         Debug.Log("Down");
  4.                 }
  5.                 else{
  6.                         Debug.Log("Up");
  7.                 }
  8.  
  9.         }
  10.  

In a UIbutton I drag the sprite in the On Press -> Notify of a UIEvent trigger component.
I select the Sprite/OnPress function but it asks me for an argument. Where do I find the "bool isPressed" ?
Title: Re: UIButton
Post by: ArenMook on August 28, 2014, 09:45:18 PM
Don't try to do this. OnPress is a regular event that gets sent out by NGUI's event system. You can attach this script as-is to any collider, and it will receive your press events. Nothing else is necessary.
Title: Re: UIButton
Post by: HeavensSword on November 04, 2014, 09:00:38 AM
Hello, I have a dynamic table of UIButtons. If I change the text value of the button's UIlabel to something that is larger than a single line of text I find that the buttons will overlap in the table, but calling execute on the table in the Unity editor will reposition everything just fine.

What I am doing in my code when creating the buttons and setting their text is:

  1. labelComponent.text = question;
  2. abelComponent.MarkAsChanged();
  3.  

After all buttons are added I call:

  1. questionTable.repositionNow = true;
  2.  

I'm not seeing the buttons properly positioned though, and I'm wondering if the reposition is occurring before the UILabel has had a chance to re-calculate its bounds. I was wondering what the best way to go about this would be.
Title: Re: UIButton
Post by: ArenMook on November 04, 2014, 10:56:48 AM
You need to call UITable's Reposition() function, not set its repositionNow value.
Title: Re: UIButton
Post by: HeavensSword on November 04, 2014, 11:37:20 AM
Thanks for the response; I changed repositionNow to Reposition(), but I'm still seeing the overlap. I've also tried changing the MarkAsChanged() call to ProcessText().
Title: Re: UIButton
Post by: ArenMook on November 06, 2014, 02:20:41 AM
Thinking about it, label's dimensions won't update until later -- not unless you call panel.Refresh() to do it early.
Title: Re: UIButton
Post by: stevej on November 07, 2014, 11:08:53 PM
Noticed that if you have both Click and Double-Click notifications assigned, then a double-click actually fires 3 events: click, click, double-click.

Any way to suppress that so you just get a single event for click and single event for double-click?
Title: Re: UIButton
Post by: ArenMook on November 09, 2014, 09:31:19 PM
No, it's intentional like that. Click and double click and separate events. Double click is a result of a click happening soon after another click. It's the same as a click event is a result of OnPress(true) and OnPress(false) being fired on the same object -- different events.
Title: Re: UIButton
Post by: hairyconiption on November 10, 2014, 03:05:44 PM
I created an object to use as a prefab for all the items in my inventory. It works fine except the prefabs UIButton lose there target parameter when I create them. I am using
ItemObject = NGUITools.AddChild (ParentObject, ItemPrefab);
To create them, and I can modify all the values to be what they should be and place it fine in my scroll view.... What is going on? Why does the target get lost?
Title: Re: UIButton
Post by: ArenMook on November 10, 2014, 10:21:02 PM
Prefabs can't reference anything outside the prefabs. Think about it, they don't exist as a part of your scene.
Title: Question: UIButton
Post by: nagbharat92 on April 13, 2015, 08:28:23 AM
I've set onHover state to play a scale tween on a button. When i hit play on the unity game view, the buttons default (start state) is onHover. it comes scaled up already without me hovering over it. Any suggestions where i would have messed up? Sorry im fairly new to NGUI.
Title: Re: UIButton
Post by: ArenMook on April 16, 2015, 07:42:45 AM
You need to disable the tween component. If you leave it enabled, it will start tweening as soon as you hit Play.
Title: Re: UIButton
Post by: The-Arrival on January 27, 2016, 05:32:45 AM
How do i only trigger the pressed state of a UIButton, when i click the left mousebutton?

by default a button and it´s remote method gets triggered by all onClick events which happens to be left, right and middle mousebutton clicks. I can easily make the remote trigger only on a left click using this:

  1. public void Button()
  2.     {
  3.         if (UICamera.currentTouchID == -1)
  4.         {
  5.             doStuff();
  6.         }
  7.        
  8.     }


But i have no idea how to trigger the UIButton components colorchange for "pressed" only for a specific pressed mousebutton, without changing the UIButton class itself.
Title: Re: UIButton
Post by: ArenMook on January 28, 2016, 11:06:47 PM
This is already like that by default in the latest version of NGUI in the Pro repository (3.9.7). It's basically a matter of checking what the current touch ID. I modified the UIButton to do it, like so:
  1.         protected virtual void OnClick ()
  2.         {
  3.                 if (current == null && isEnabled && UICamera.currentTouchID != -2 && UICamera.currentTouchID != -3)
  4.                 {
  5.                         current = this;
  6.                         EventDelegate.Execute(onClick);
  7.                         current = null;
  8.                 }
  9.         }
Title: Re: UIButton
Post by: The-Arrival on February 02, 2016, 05:31:10 AM
Awesome. Thanks. I´ll wait until the changes are pushed to the Assets Store to update.
Title: Re: UIButton
Post by: jezzurp on May 11, 2016, 05:11:01 AM
Hi all, I'm new to this so appologies if I'm asking a stupid question...

When using a sprite with button component attached, and a label for the button nested as a child... is there an obvious way of making the label text hover in the same way that the sprite/ button BG has options for hover colour/active colour etc? I'm not sure if I'm being stupid and missing something obvious, or if it's something that's more difficult to do than I would expect?

Any help would be massively welcome, thanks
Title: Re: UIButton
Post by: ArenMook on May 14, 2016, 07:03:45 PM
You can attach multiple UIButton / UIButtonColor components.