17
\$\begingroup\$

Looking to dynamically change the value in the button OnClick and slider On Value Changed example 1 example 2.

If I had to guess on how this was done, get a reference to the button/gui element. Next get the Button script component and access that list of function calls. However I'm not sure how to modify that list. Anyone have any ideas?

More Details that might help:

  • The function being called is apart of a custom script component
  • Using the 'dynamic' variable option for the sliders
  • Could be used to create dynamic buttons
\$\endgroup\$
23
\$\begingroup\$

There's a super simple way to change events:

EDIT

See my other answer for the quick and easy way to add an event for the OnClick event only. For other events, like OnDrag see below.


Additionally, if you need more than just the events provided by default, I'd suggest instead attaching a EventTrigger to your game object. This gives us access to the BaseEventData object returned from the event, telling us stuff like the object that created the event. Then you can do something like:

//Create an event delegate that will be used for creating methods that respond to events
public delegate void EventDelegate(UnityEngine.EventSystems.BaseEventData baseEvent);

Then we can create a method for handling events, the signature must match that of our delegate. So, it needs to return void and accept BaseEventData as its first and only parameter:

public void DropEventMethod(UnityEngine.EventSystems.BaseEventData baseEvent) {
    Debug.Log(baseEvent.selectedObject.name + " triggered an event!");
    //baseEvent.selectedObject is the GameObject that triggered the event,
    // so we can access its components, destroy it, or do whatever.
}

Finally, to dynamically add the event:

//Get the event trigger attached to the UI object
EventTrigger eventTrigger = buttonObject.GetComponent<EventTrigger>();

//Create a new entry. This entry will describe the kind of event we're looking for
// and how to respond to it
EventTrigger.Entry entry = new EventTrigger.Entry();

//This event will respond to a drop event
entry.eventID = EventTriggerType.Drop;

//Create a new trigger to hold our callback methods
entry.callback = new EventTrigger.TriggerEvent();

//Create a new UnityAction, it contains our DropEventMethod delegate to respond to events
UnityEngine.Events.UnityAction<BaseEventData> callback =
    new UnityEngine.Events.UnityAction<BaseEventData>(DropEventMethod);

//Add our callback to the listeners
entry.callback.AddListener(callback);

//Add the EventTrigger entry to the event trigger component
eventTrigger.delegates.Add(entry);

If you're using version 5.3.3 or above, use this line instead instead of the last line above, delegates is depreciated:

eventTrigger.triggers.Add(entry); 
\$\endgroup\$
  • \$\begingroup\$ It seems that when you dynamically add a handler it doesn't seem to appear in the inspector. Drawer still shows "Empty list" for the delegates \$\endgroup\$ – vexe Dec 6 '14 at 16:13
  • \$\begingroup\$ That's correct. Handlers added from code are separate from the "persistent" handlers shown in the inspector; moreover, you are responsible for cleaning these handlers up (unlike the persistent ones, which Unity takes care of for you). \$\endgroup\$ – Joe Strout Jan 23 '17 at 15:31
11
\$\begingroup\$

The word is that the delegate{} syntax found in my previous answer is obsolete, there is another way of doing this using lambda notation:

void buttonSetup(Button button) {
    //Remove the existing events
    button.onClick.RemoveAllListeners();
    //Add your new event using lambda notation
    button.onClick.AddListener (handleButton);
}

void handleButton() {
    Debug.Log("Button pressed!");
}

Or you can pass the button along to make things a little more dynamic:

void buttonSetup(Button button) {
    button.onClick.RemoveAllListeners();
    //Add your new event
    button.onClick.AddListener(() => handleButton(button));
}

void handleButton(Button b) {
    Debug.Log("Button '" + b.name + "' pressed!");
}
\$\endgroup\$
  • \$\begingroup\$ Keep in mind, this strategy is only for the OnClick event. In order to dynamically add other events, you need to follow the instructions in my other answer. \$\endgroup\$ – MichaelHouse Feb 21 '15 at 3:22
0
\$\begingroup\$

Create a new script, along the lines of:

public class EventHandler : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData)
    {
        Debug.Log("Element: " +
                   eventData.selectedObject.name +
                   " was clicked at " +
                   eventData.position.ToString());
    }
}

This script implements in the interface IPointerClickHandler (among many other available interfaces). Simply attaching this script to a UI element will allow this script to intercept click events (or whatever event your implement the interface for).

The next step is to simply dynamically add this script as a component to the UI element you want:

myButton.AddComponent<EventHandler>();

This will add the script as a component to myButton and the next time I click the button, I'll get information about which button was clicked, and where the click took place.

This provides the most information about the event compared to my other answers.

\$\endgroup\$
0
\$\begingroup\$

How unity implements the UI is just like any other unity components. You add GameObject and attach UI components to it. Once you have the game object you can get the UI components from it and change the properties.

API reference for UI can be found under UnityEngine.UI namespace, API reference for BUtton is http://docs.unity3d.com/ScriptReference/UI.Button.html

See the post http://blog.trsquarelab.com/2015/03/new-ui-implementation-using-c-scripts.html for more information on accessing UI from C# scripts

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.