AddListener to OnPointerDown of Button instead of onClick

I'd like to register a callback to the OnPointerDown and OnPointerUp events of the UnityEngine.UI.Button(s) in my game to trigger two different sounds for down and up click. However, only the onClick event is exposed. Is there any clean method to get these properties through code? I'd rather not add the UnityEngine.EventTrigger component to every button individually and set them up in the scene, because of the amount of buttons in my project and I might want to change behaviour while testing, and therefore rather do it from one central location in code.

I was expecting this to be built into the Unity button component, because it's such a common thing to ask for when assigning sounds to buttons and also the button must use it's OnPointerDown event internally to trigger sprite transitions etc. Why wouldn't they just expose these callback publicly like onClick already is?

Anyway, here is my code that got it working:

  1. EventTrigger trigger = buttons[i].gameObject.AddComponent<EventTrigger>();
  2. var pointerDown = new EventTrigger.Entry();
  3. pointerDown.eventID = EventTriggerType.PointerDown;
  4. pointerDown.callback.AddListener((e) => AkSoundEngine.PostEvent(downEvent, gameObject));
  5. trigger.triggers.Add(pointerDown);

For every button that needs additional listeners, I add an EventTrigger component and the appropriate PointerDown EventTriggerType. This has much more overhead than I wanted it to have, but it still works better than adding sound components to 20 buttons manually.

PS: Of course, I'd still be interested in seeing a better solution than mine.

Edit - Custom UI Button

I just figured, that I could also subclass the existing Unity Button to add my desired functionality. I keep forgetting that the UI source is extendable. This works very well and feels much cleaner. Just to spread community knowledge, here is my button extension, which I use to later add two different click sounds for down and up.

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEngine.Events;
  4. using UnityEngine.EventSystems;
  5. using System;
  6. // Button that raises onDown event when OnPointerDown is called.
  7. [AddComponentMenu("Aeronauts/AeButton")]
  8. public class AeButton : Button
  9. {
  10. // Event delegate triggered on mouse or touch down.
  11. [SerializeField]
  12. ButtonDownEvent _onDown = new ButtonDownEvent();
  13. protected AeButton() { }
  14. public override void OnPointerDown(PointerEventData eventData)
  15. {
  16. base.OnPointerDown(eventData);
  17. if (eventData.button != PointerEventData.InputButton.Left)
  18. return;
  19. _onDown.Invoke();
  20. }
  21. public ButtonDownEvent onDown
  22. {
  23. get { return _onDown; }
  24. set { _onDown = value; }
  25. }
  26. [Serializable]
  27. public class ButtonDownEvent : UnityEvent { }
  28. }

To make the ButtonDownEvent also show up in the inspector, you will need to subclass the according ButtonEditor as well.

  1. using UnityEditor;
  2. using UnityEditor.UI;
  3. [CustomEditor(typeof(AeButton), true)]
  4. public class AeButtonEditor : ButtonEditor
  5. {
  6. SerializedProperty _onDownProperty;
  7. protected override void OnEnable()
  8. {
  9. base.OnEnable();
  10. _onDownProperty = serializedObject.FindProperty("_onDown");
  11. }
  12. public override void OnInspectorGUI()
  13. {
  14. base.OnInspectorGUI();
  15. EditorGUILayout.Space();
  16. serializedObject.Update();
  17. EditorGUILayout.PropertyField(_onDownProperty);
  18. serializedObject.ApplyModifiedProperties();
  19. }
  20. }

ref :

+ Recent posts