Search Unity

onClick.AddListener do no works

Discussion in 'Scripting' started by Tempest74, Aug 10, 2019.

  1. Tempest74

    Tempest74

    Joined:
    May 17, 2017
    Posts:
    133
    Hey, in every scene I have an object called "ButtonSound". I have a sound manager which do not destroy on load. I want to access all gameobjects called "ButtonSound" and assign them a function, but the function AddListener do no work. any help?
    Code (CSharp):
    1. void Awake()
    2.     {
    3.         SceneManager.sceneLoaded += PopulateButtonsArray;
    4.         if (instance == null)
    5.             instance = this;
    6.         else if (instance != this)
    7.             Destroy(gameObject);
    8.  
    9.         GameObject.DontDestroyOnLoad(gameObject);
    10.     }
    11.  
    12.     void PopulateButtonsArray(Scene scene, LoadSceneMode mode)
    13.     {
    14.         Debug.Log("a");
    15.         List<CRGTSpriteToggle> goList = new List<CRGTSpriteToggle>();
    16.         foreach (CRGTSpriteToggle go in Resources.FindObjectsOfTypeAll(typeof(CRGTSpriteToggle)))
    17.         {
    18.             if (go.gameObject.name == "ButtonSound")
    19.             {
    20.                 goList.Add(go);
    21.                 Debug.LogError("added");
    22.                 go.GetComponent<Button>().onClick.AddListener(() => SetSoundOnOff(mute));
    23.             }
    24.         }
    25.         Buttons = goList.ToArray();
    26.         UpdateVolume();
    27.     }
     
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    First, don't register a delegate to sceneLoaded if you aren't sure if you're going to destroy the current GameObject or not. Put the above SceneManager.sceneLoaded line above **after** the DontDestroyOnLoad, and make the script return if it's going to be destroyed rather than keep going and potentially creating issues.
    Code (CSharp):
    1. private void Awake()
    2. {
    3.     if (instance != null)
    4.     {
    5.         Destroy(gameObject);
    6.         return;
    7.     }
    8.     instance = this;
    9.  
    10.     GameObject.DontDestroyOnLoad(gameObject);
    11.     SceneManager.sceneLoaded += PopulateButtonsArray;
    12. }
    Also, FindObjectsOfTypeAll returns every single object in the project, including prefabs and things in the project files that aren't in the current scene. That means if you have a prefab with the component CRGTSpriteToggle attached and named "ButtonSound", it'll return that too, and potentially create an issue. There's an example in the documentation that shows exactly how to get all objects just in the current scene which will make this a little more predictable so bugs don't pop up in the future (use the preprocessor directive to find if you're in the Editor, then check EditorUtility.IsPersistent on the root GameObject in its object hierarchy).

    AddListener should work fine though- I can't think of a reason why it wouldn't from the information provided. Keep in mind that the delegate will fire in a new scene after Awake and OnEnable have been run on all newly loaded GameObjects, but before Start has run for any of them. My advice is just to create debug logs and breakpoints until you can narrow down exactly where the problem happens.
     
    Last edited: Aug 10, 2019
  3. Tempest74

    Tempest74

    Joined:
    May 17, 2017
    Posts:
    133
    Code (CSharp):
    1.  void Awake()
    2.     {
    3.         if (instance == null)
    4.             instance = this;
    5.         else if (instance != this)
    6.             Destroy(gameObject);
    7.  
    8.         GameObject.DontDestroyOnLoad(gameObject);
    9.         SceneManager.sceneLoaded += PopulateButtonsArray;
    10.     }
    11.  
    12.     void PopulateButtonsArray(Scene scene, LoadSceneMode mode)
    13.     {
    14.         List<CRGTSpriteToggle> goList = new List<CRGTSpriteToggle>();
    15.         StoreGameObjectsThatCanBeIncative storage = GameObject.FindGameObjectWithTag("Storage").GetComponent<StoreGameObjectsThatCanBeIncative>();
    16.         Buttons = storage.soundButtons;
    17.         foreach (CRGTSpriteToggle go in Buttons)
    18.         {
    19.             go.GetComponent<Button>().onClick.AddListener(() => SetSoundOnOff(mute));
    20.             Debug.Log(go.GetComponent<Button>().onClick);
    21.         }
    22.         UpdateVolume();
    23.     }
    24.  
    @Lysander I change it, but it does not work at all, I do not find any function that can return the number of listeners so I have no idea how to check them.
     
  4. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Functionally, you can't. Don't Debug.Log the listeners themselves, just Debug.Log ("Successfully added listener!") or something instead to see if it's getting to that specific part of the code.

    I can't really offer any more suggestions from the information given- add more Debug.Logs and try to track down EXACTLY where the problem is occurring- is it really not adding the listeners (again, you don't need to list the listeners, just Debug.Log to say that that part of the code is being reached is all), is it adding but not firing the function, or is firing the function but just not doing anything noticeable.

    In Play Mode, go around to the objects in the scene and check their buttons in the inspector, turn on Debug in the inspector options if you need to, and make sure there's an entry for the event.