Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Inconvenince with the Event System

Discussion in 'UGUI & TextMesh Pro' started by vexe, Aug 31, 2014.

  1. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Hi all, so I was messing a bit with the event system and I noticed a couple of things:

    1. If you want to have a handler for say, a pointer enter event for a button, your handler must take a BaseEventData as an argument as opposed to PointerEventData otherwise the functions list won't detect it - So say you wanted to fetch the pointerId or anything related, you'd have to cast it down to a PointerEventData. Redundant, and not very intuitive IMHO.
    2. I'm not quite sure how to receive right/middle mouse buttons. The OnPointerClick/Up/Down don't seem to catch anything but left clicks.
    Appreciate a response, thanks.
     
  2. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    556
    I don't know about 1. but as for midde/ right clicks: this is a confirmed bug on Unity's end and will be solved ASAP.
     
  3. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Thanks for the reply. Just to elaborate more on 1: here's how I have to write my handler if I want to subscribe to a OnPointerXXX

    Code (csharp):
    1.  
    2.     public void OnClickHandler(BaseEventData e)
    3.      {
    4.        var real = e as PointerEventData;
    5.        log("clicked with: " + real.pointerId);
    6.      }
    7.  
    As opposed to:

    Code (csharp):
    1.  
    2.     public void OnClickHandler(PointerEventData e)
    3.      {
    4.        log("clicked with: " + e.pointerId);
    5.      }
    6.  
    Definitely counter-intuitive. If you go to Selectable you'll notice that all OnPointerXXX take PointerEventData and not BaseEventData.

    This is probably an issue with how they're picking up the functions in their Unity Events (I had a similar issue when I wrote my uFaction)
     
  4. orb

    orb

    Joined:
    Nov 24, 2010
    Posts:
    3,033
    This annoyed me too. Looks like the one using BaseEventData is probably an old version they forgot to update. The fun of betas!
     
  5. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    What is this OnClickHandler?

    We only have:
    public virtual void OnPointerClick(PointerEventData eventData) implemented in IPointerClickHandler

    There should be no downcasting or anything here...
     
  6. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @Tim C OnClickHandler is just my custom event handler.

    I think you miss-understood, I'm talking about the event system via EventTrigger.

    Here's a step by step:
    1- Create a UI Button
    2- Add EventTrigger component to it
    3- Add any kind of pointing event to the event list (OnPointerUp/Down etc)
    4- Write a MonoBehaviour with a handler to that pointer event that takes a PointerEventData argument (just like the OnClickHandler ^)
    5- Try to add that handler to the EventTrigger's event list, and it won't pick it up i.e. It won't find my handler from my MonoBehaviour.
    6- The way to fix that is to change the handler's argument to take a BaseEventData instead of PointerEventData.
     
    rakkarage likes this.
  7. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    Can you attach a simple project so I can have a look at this?
     
  8. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    @Tim C it's very easy to replicate

     
  9. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    Can you attach a project that I can just load up and check? I don't want to make a mistake recreating the issue.
     
  10. vexe

    vexe

    Joined:
    May 18, 2013
    Posts:
    644
    Mistake? it's very straight forward... anyways here's a project.
     

    Attached Files:

  11. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,181
    Ah I see.

    So with the EventTrigger component we are currently keeping things very simple. With this component everything that is sent uses a BaseEventData. There are few reasons for this:
    • Dramatically increases code required to manage serialisation
    • We see EventTrigger as a helper class for prototyping (it's slow as it will always receive all events)
    The recommended way of doing what you want is adding the specific interface that you want to the Handler. That being said if you want to do forwarding like you describe it is pretty east to accomplish. Here is a 'PointerEventTrigger' that should work like you want:

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections.Generic;
    4. using UnityEngine.Events;
    5. using UnityEngine.EventSystems;
    6. using UnityEngine;
    7.  
    8. public enum PointerEventTriggerType
    9. {
    10.     PointerEnter,
    11.     PointerExit,
    12.     PointerDown,
    13.     PointerUp,
    14.     PointerClick
    15. }
    16.  
    17. [AddComponentMenu("Event/Pointer Event Trigger")]
    18. public class PointerEventTrigger :
    19.     MonoBehaviour,
    20.     IPointerEnterHandler,
    21.     IPointerExitHandler,
    22.     IPointerDownHandler,
    23.     IPointerUpHandler,
    24.     IPointerClickHandler
    25. {
    26.     [Serializable]
    27.     public class PointerTriggerEvent : UnityEvent<PointerEventData>
    28.     {
    29.     }
    30.  
    31.     [Serializable]
    32.     public class Entry
    33.     {
    34.         public PointerEventTriggerType eventID = PointerEventTriggerType.PointerClick;
    35.         public PointerTriggerEvent callback = new PointerTriggerEvent ();
    36.     }
    37.  
    38.     public List<Entry> delegates;
    39.  
    40.     protected PointerEventTrigger()
    41.     {
    42.     }
    43.  
    44.     private void Execute<T>(PointerEventTriggerType id, T eventData) where T : PointerEventData
    45.     {
    46.         if (delegates != null)
    47.         {
    48.             for (int i = 0, imax = delegates.Count; i < imax; ++i)
    49.             {
    50.                 Entry ent = delegates[i];
    51.                 if (ent.eventID == id && ent.callback != null)
    52.                     ent.callback.Invoke (eventData);
    53.             }
    54.         }
    55.     }
    56.  
    57.     public virtual void OnPointerEnter(PointerEventData eventData)
    58.     {
    59.         Execute (PointerEventTriggerType.PointerEnter, eventData);
    60.     }
    61.  
    62.     public virtual void OnPointerExit(PointerEventData eventData)
    63.     {
    64.         Execute (PointerEventTriggerType.PointerExit, eventData);
    65.     }
    66.  
    67.     public virtual void OnPointerDown(PointerEventData eventData)
    68.     {
    69.         Execute (PointerEventTriggerType.PointerDown, eventData);
    70.     }
    71.  
    72.     public virtual void OnPointerUp(PointerEventData eventData)
    73.     {
    74.         Execute (PointerEventTriggerType.PointerUp, eventData);
    75.     }
    76.  
    77.     public virtual void OnPointerClick(PointerEventData eventData)
    78.     {
    79.         Execute (PointerEventTriggerType.PointerClick, eventData);
    80.     }
    81. }
    82.  
     
  12. Ghopper21

    Ghopper21

    Joined:
    Aug 24, 2012
    Posts:
    170
    Hey @Tim C -- thanks for this! I had the same question as vexe. Would be great to add what you said here to the documentation on EventTrigger.
     
  13. TechSupportIncoming1

    TechSupportIncoming1

    Joined:
    Mar 13, 2014
    Posts:
    4
    Hey @Tim C Thanks for directing Vexe and us to the right way :p

    Though I am really confused on how to handle Keyboard input using the new EventSystem (StandaloneInputModule)...

    For mouse input, I am implementing the interfaces I need like IBeginDragHandler, IPointerDownHandler etc... as you described and it went quite smooth.

    But I have no clue how to handle keyboard events! Using Update to detect keyboard input (e.g. Input.GetKey and other variations ) is producing problems and requiring lots of maintenance for the goal I am trying to achieve. Especially when trying to do keyrepeat...

    With the old GUI I used to implement keyboard events using OnButtonDown or OnButtonUp but as I transitioned to uGUI I got stuck with detecting keyboard input from Update().

    My question is:
    What interfaces should I implement or what should I do in order to detect keyboard buttons being pressed in a way similar to Old GUI's OnButtonDown and OnButtomUp?