- Home /
How do you add an UI EventTrigger by Script ?
The new Unity 4.6 System comes with an EventTrigger System. From the editor this is easy to use but how does one add a trigger, for example for PointerClick, by script (C#) ?
Let's say i have a function called Foo() in a class called ExampleAction on the a child of the gameObject that contains the event trigger. How do i assign now a PointerClick to call ExampleAction.Foo() on that childobject
Thanks!
Answer by Phles · Dec 14, 2014 at 04:38 PM
Hey there, I believe you're after something like this...
EventTrigger trigger = GetComponentInParent<EventTrigger>();
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = EventTriggerType.PointerClick;
entry.callback.AddListener( (eventData) => { Foo(); } );
trigger.delegates.Add(entry);
In researching this myself I noticed that EventTrigger will check every callback for all 12 event types, regardless of whether the callback handles a specific event. I know it's only responding to user initiated UI events so performance isn't critical but it still seems a poor (read inefficient) way to implement this.
Indeed, This behaviour is noted in the documentation for EventTrigger, "NOTE: Attaching this component to a GameObject will make that object intercept ALL events, and no event bubbling will occur from this object!"
I think the idea is that EventTrigger is supposed to be simple and easy to use from the inspector, If you want more performance and/or to have unhandled events bubble you can always create your own $$anonymous$$onoBehaviour derived class only implementing the interfaces for event types you actually are going to use... IPointerClickHandler, IPointerEnterHandler ...etc
$$anonymous$$or update to this answer: "delegates" has been deprecated; line 5 in the answer should now use "triggers" ins$$anonymous$$d:
trigger.triggers.Add(entry);
Something very important that is not precised: "GetComponentInParent()" will search for a component EventTrigger so there should be an EventTrigger on the object. Click on the object, then "Add Component", then add "Event Trigger" and let it empty, but from now on your code will work.
Answer by xCyborg · Jul 27, 2015 at 04:49 AM
No he means that:
newButton.GetComponent<Button>().onClick.AddListener(()=>TestScript());
or:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ClickableButton : MonoBehaviour, IPointerClickHandler {
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Left)
Debug.Log("Left click");
else if (eventData.button == PointerEventData.InputButton.Middle)
Debug.Log("Middle click");
else if (eventData.button == PointerEventData.InputButton.Right)
Debug.Log("Right click");
}
}
Answer by oferei · Aug 08, 2016 at 09:14 PM
Building on Phles's answer, here's pretty much the same code, neatly wrapped in a function:
public static void AddEventTriggerListener(EventTrigger trigger,
EventTriggerType eventType,
System.Action<BaseEventData> callback)
{
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventType;
entry.callback = new EventTrigger.TriggerEvent();
entry.callback.AddListener(new UnityEngine.Events.UnityAction<BaseEventData>(callback));
trigger.triggers.Add(entry);
}
You could use it like this, for example:
AddEventTriggerListener(
GetComponent<EventTrigger>(),
EventTriggerType.PointerClick,
OnClicked);
// Callback function
void OnClicked(BaseEventData eventData) {
PointerEventData pointerEventData = (PointerEventData)eventData;
Debug.Log("Click: pointerEventData=" + pointerEventData);
}
Just wondering if line 7 requires! entry.callback = new EventTrigger.TriggerEvent();
Not 100%. I see you've added a similar answer without it. So I guess not?
Apparently the following line is not necessary (line 7 in my original answer above):
entry.callback = new EventTrigger.TriggerEvent();
Answer by ben-rasooli · Dec 08, 2017 at 12:48 AM
I've made an extension method for it. Simply include this class somewhere in your project:
using UnityEngine.EventSystems;
public static class ExtensionMethods
{
public static void AddListener (this EventTrigger trigger, EventTriggerType eventType, System.Action<PointerEventData> listener)
{
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventType;
entry.callback.AddListener(data => listener.Invoke((PointerEventData)data));
trigger.triggers.Add(entry);
}
}
Then use it like this:
using UnityEngine;
using UnityEngine.EventSystems;
public class UIController : MonoBehaviour
{
void Start ()
{
EventTrigger myEventTrigger = GetComponent<EventTrigger> (); //you need to have an EventTrigger component attached this gameObject
myEventTrigger.AddListener (EventTriggerType.PointerClick, onClickListener);
}
void onClickListener (PointerEventData eventData)
{
//put your logic here...
}
}
Answer by MUGIK · Mar 01, 2021 at 07:41 PM
My realization of the extension method that takes into account if there is already such event type. Also, there are methods for removing listeners.
using UnityEngine.Events;
using UnityEngine.EventSystems;
public static class EventTriggerExtensions
{
public static void AddListener(this EventTrigger eventTrigger, EventTriggerType triggerType,
UnityAction<BaseEventData> call)
{
if (eventTrigger == null)
throw new ArgumentNullException(nameof(eventTrigger));
if (call == null)
throw new ArgumentNullException(nameof(call));
EventTrigger.Entry entry = eventTrigger.triggers.Find(e => e.eventID == triggerType);
if (entry == null)
{
entry = new EventTrigger.Entry {eventID = EventTriggerType.PointerClick};
eventTrigger.triggers.Add(entry);
}
entry.callback.AddListener(call);
}
public static void RemoveListener(this EventTrigger eventTrigger, EventTriggerType triggerType,
UnityAction<BaseEventData> call)
{
if (eventTrigger == null)
throw new ArgumentNullException(nameof(eventTrigger));
if (call == null)
throw new ArgumentNullException(nameof(call));
EventTrigger.Entry entry = eventTrigger.triggers.Find(e => e.eventID == triggerType);
entry?.callback.RemoveListener(call);
}
public static void RemoveAllListeners(this EventTrigger eventTrigger, EventTriggerType triggerType)
{
if (eventTrigger == null)
throw new ArgumentNullException(nameof(eventTrigger));
EventTrigger.Entry entry = eventTrigger.triggers.Find(e => e.eventID == triggerType);
entry?.callback.RemoveAllListeners();
}
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
PointerEventData.selectObject always null 2 Answers
GUI.RepeatButton funcionality with new Unity UI (4.6.x) 2 Answers