Search Unity

Unable to bind unity event to dynamic function

Discussion in 'Editor & General Support' started by kurifodo, Oct 22, 2019.

  1. kurifodo

    kurifodo

    Joined:
    Jan 17, 2019
    Posts:
    33
    Hi,

    I'm trying to use events to communicate between my game objects. Following various tutorials online, I arrived at what I thought was a solution, but I'm not quite there. The main architecture I'm trying to achieve is summarized at https://unity3d.com/how-to/architect-with-scriptable-objects.

    To reiterate my goal, I'm trying to raise an event with a custom data type in one game object, and then handle processing said data type in game objects listening for the event.

    I have attached a trimmed down Unity project with my attempt. The issue I'm facing is when trying to bind the function to call on the listener: (a) I do not see my method in the inspector, and (b) I expected to see a dynamic version of my method as well.

    If someone can help unravel where I'm going wrong, I'd appreciate it greatly.

    Note, I'm using Unity version 2018.4.11f1, but have also tried 2019.2.9f1 and 2019.3.0b7 with no success.

    EDIT:
    I noticed the "Unity Event Response()" header does not contain my custom data type. I expected it to say, "Unity Event Response(MyEventData)" instead. See picture below. This hints to me that something is wrong with my listener (?), but I'm not sure what yet.




    Code (CSharp):
    1. public interface IGameEventListener<T>
    2. {
    3.     void OnEventRaised( T eventData );
    4. }
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public abstract class GameEvent<T> : ScriptableObject
    5. {
    6.     readonly List<IGameEventListener<T>> eventListeners = new List<IGameEventListener<T>>();
    7.  
    8.     public void Raise( T item )
    9.     {
    10.         for ( int i = eventListeners.Count - 1; i >= 0; i-- )
    11.         {
    12.             eventListeners[i].OnEventRaised( item );
    13.         }
    14.     }
    15.  
    16.     public void RegisterListener( IGameEventListener<T> listener )
    17.     {
    18.         if ( !eventListeners.Contains( listener ) )
    19.         {
    20.             eventListeners.Add( listener );
    21.         }
    22.     }
    23.  
    24.     public void UnregisterListener( IGameEventListener<T> listener )
    25.     {
    26.         if ( eventListeners.Contains( listener ) )
    27.         {
    28.             eventListeners.Remove( listener );
    29.         }
    30.     }
    31. }
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3.  
    4. public abstract class GameEventListener<T, E, UER> : MonoBehaviour, IGameEventListener<T>
    5.     where E : GameEvent<T>
    6.     where UER : UnityEvent<T>
    7. {
    8.     [SerializeField]
    9.     E gameEvent;
    10.  
    11.     public E GameEvent
    12.     {
    13.         get
    14.         {
    15.             return this.gameEvent;
    16.         }
    17.  
    18.         set
    19.         {
    20.             this.gameEvent = value;
    21.         }
    22.     }
    23.  
    24.     [SerializeField]
    25.     UER unityEventResponse = default;
    26.  
    27.     void OnDisable()
    28.     {
    29.         if ( this.gameEvent == null )
    30.         {
    31.             return;
    32.         }
    33.  
    34.         this.gameEvent.UnregisterListener( this );
    35.     }
    36.  
    37.     void OnEnable()
    38.     {
    39.         if ( this.gameEvent == null )
    40.         {
    41.             return;
    42.         }
    43.  
    44.         this.gameEvent.RegisterListener( this );
    45.     }
    46.  
    47.     public void OnEventRaised( T item )
    48.     {
    49.         if ( this.unityEventResponse != null )
    50.         {
    51.             this.unityEventResponse.Invoke( item );
    52.         }
    53.     }
    54. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu( fileName = "New MyEvent", menuName = "MyEvent" )]
    4. public class MyEvent : GameEvent<MyEventData> { }
    Code (CSharp):
    1. public class MyEventListener : GameEventListener<MyEventData, MyEvent, MyUnityEvent> { }
    Code (CSharp):
    1. using System;
    2. using UnityEngine.Events;
    3.  
    4. [Serializable]
    5. public class MyUnityEvent : UnityEvent<MyEventData> { }
    Code (CSharp):
    1. public class MyEventData
    2. {
    3.     public int[] FieldA;
    4.  
    5.     public float FieldB;
    6. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TestHandler : MonoBehaviour
    4. {
    5.     public void OnMyEvent( MyEventData myEvent )
    6.     {
    7.         Debug.Log( "FieldA: " + string.Join( ", ", myEvent.FieldA ) );
    8.         Debug.Log( "FieldB: " + myEvent.FieldB );
    9.     }
    10. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TestRaiser : MonoBehaviour
    4. {
    5.     [SerializeField] MyEvent MyEvent;
    6.  
    7.     void Start()
    8.     {
    9.         MyEvent.Raise( new MyEventData()
    10.         {
    11.             FieldA = new int[] { 1, 2, 3 },
    12.             FieldB = 1.1f,
    13.         } );
    14.     }
    15. }
     

    Attached Files:

    Last edited: Oct 22, 2019
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    This works in 2018.3.3, but not in 2018.4.1f. Then it works again in 2019.2. Seems like you've run into a regression bug that unfortunately only affects 2018.4!

    Edit to be more precise: Affects at least 2018.4.11f1, 2019.2.9f1, and 2019.3.0b7.
     
    Last edited: Oct 22, 2019
  3. kurifodo

    kurifodo

    Joined:
    Jan 17, 2019
    Posts:
    33
    @Madgvox, thanks for the heads-up. Just to be clear, you downloaded my sample repro and ran it successfully in those different versions of Unity?

    I have tried these versions of Unity but had no success:
    2018.4.11f1
    2019.2.9f1
    2019.3.0b7​

    You mentioned it working in 2019.2. What was your exact version? The above versions are all I'm able to download using Unity Hub. Not sure how to get a working version at this point.

    Any suggestions?
     
  4. kurifodo

    kurifodo

    Joined:
    Jan 17, 2019
    Posts:
    33
    I finally found a version of Unity that works: 2019.2.4f1

    The latest 2019.2 and 2019.3 versions are both broken as of now... sad. I filed a bug.
     
    Last edited: Oct 22, 2019
  5. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    My exact version was 2019.2.0a13.
     
  6. edwarddewolf

    edwarddewolf

    Joined:
    May 14, 2017
    Posts:
    6
    I need to script/code adding an event listener to a gameobject. Adding the component is easy, seeting the gamevent also, but I cannot figure out how to add the unity event reponse by means of coding. Has anyone managed to do this already? Thx !
     
  7. FuzzyShan

    FuzzyShan

    Joined:
    Jul 30, 2012
    Posts:
    182
    we have ran into the same problem
     
  8. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    You don't need to add listeners to unityEventResponse, since it's used only as an interface to expose OP's GameEvent ScriptableObject to the editor. If you're adding the event in code, you can add it to the GameEvent directly using
    GameEvent.RegisterListener()
    .