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

How can I get the argument of Function called by Button onClick?

Discussion in 'Scripting' started by KILEYI2015, Jan 11, 2018.

  1. KILEYI2015

    KILEYI2015

    Joined:
    Sep 5, 2015
    Posts:
    9
    panel.png
    This is what I wrote in the Button,those function called with argument.

    The problem is I don't know how to visit those argument.Didn' find any function to call to get this.

    But in Debug mode,I do see what I need.

    panel_db.png

    So is there any way to get this argument?

    The function name can get like this

    btn.onClick.GetPersistentMethodName

    but the argument...well, I did'nt find anything useful.
     
    Qhuhuit and mdrunk like this.
  2. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
  3. sirdudalot

    sirdudalot

    Joined:
    Nov 22, 2015
    Posts:
    6
    Hey, I'm also trying to get the parameter value for the onclick method (from script if that isn't obvious). No offense, but that video is was not useful. Did either of you ever figure it out?

    Thanks in advance.
     
  4. Jichaels

    Jichaels

    Joined:
    Dec 27, 2018
    Posts:
    237
    I'd really like a way to access this myself, as I need to be able to export/import unityevents as strings... If ayone achieved this, I'd much much appreciate it !
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,711
    Please don't reply to 3-year-old posts. Make a new one for yourself... it's FREE!

    When you do, keep this in mind: how to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    ALSO: work through some basic UI tutorials (start with the one linked above). This stuff is super-trivial easy setup and it is easily covered by any Unity UI tutorials.
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    Well, since several people seem to have the need to access the stored closure like parameters of Unity's UnityEvent class, I'd like to clear up some of the confusion:


    First of all: No, there is no built-in way to access those stored parameters. This is a pure feature of the editor / property drawer for those events. So it's only meant to be edited in the inspector and the only place where you can access those parameters is in the actual method call where this parameter is passed along.

    However it's of course possible to use reflection or the SerializedObject / SerializedProperty functionality to access those values. However due to the nature how the argument cache is designed it's a pain to dig through to the actual values, As you can already see from the debug view they are buried in several layers of internal classes. So when using reflection you would need to walk each layer manually.

    Using reflection you would need to read the m_PersistentCalls field which contains an instance of the internal PersistentCallGroup class. This class again has a private field called m_Calls which is a List of PersistentCall instances. Each of those PersistentCall instance has again a private field named m_Arguments which is of type ArgumentCache. Finally the internal class ArgumentCache has several different typed fields for the different supported argument types. Which of those fields are actually used depends on the actual parameter type of the method / event. This information is stored in the m_Mode variable of the PersistentCall instance. You can see it in use here in the actual calling method of the PersistentCall class.

    As I said it's a horrible walk through several layers of classes. Since all those classes are internal or private you don't have direct access to them. So even reading the persistent call List instances gets more difficult because you can not cast the value stored in m_Calls to the actual List type since we don't have access to the PersistentCall class.

    You may have more success using Unity's JsonUtility as it can serialize pretty much anything Unity itself can serialize (besides object references). Once serialized as json you could parse the json which would be much simpler. Note that the JsonUtility can not serialize UnityEngine.Object references. So the target field or any UnityEngine.Object parameter reference can not be serialized that way. If you need to extract them as well, your only choice is using reflection or SerializedObject / SerializedProperties.

    Keep in mind that those hidden classes are an implementation detail that is not documented. So you should not rely on this architecture as this implementation could change in the future without notice.
     
    PraetorBlue likes this.
  7. Jichaels

    Jichaels

    Joined:
    Dec 27, 2018
    Posts:
    237
    It's also free to answer to a thread that ask the exact same question, what's your point ?

    It's definitely not super trivial nor in any UI tutorial, did you even read the thread ? All solution are using reflection/hacky stuff because it is not even supported.

    Well, honestly I was looking for an easier way to get this working, as it's simply for a tool for a client that will just gain a bit of time, we'll probably just not do it and only work from the editor. Thanks for your answer
     
  8. Qhuhuit

    Qhuhuit

    Joined:
    Feb 17, 2018
    Posts:
    39
    As you said, using reflection is hard to do in this case.

    I came to this conclusion because I would like to find a way to debug the listeners and their callbacks of a Scriptable Object Unity Event. (basically it's a Scriptable Object containing a list of listeners who have UnityEvents, there is a good description here of why it's awesome)

    So far reflection was too hard to achieve. I ended up creating a wrapper class referencing the listener object and its UnityEvent and use this as the list of listeners. This is somewhat a viable solution, I can see all UnityEvents in the SO inspector.

    Did someone faced a similar problem and found an other solution ?

    Here is a simplified version of the code:
    Code (CSharp):
    1. public class EventSO : ScriptableObject
    2. {
    3.     public List<UnityEventAndHolder> listeners;
    4. }
    5.  
    6. [System.Serializable]
    7. public class UnityEventAndHolder
    8. {
    9.     public Object holder;
    10.     public UnityEvent unityEvent;
    11. }
    12.  
    13. public class EventListener : MonoBehaviour
    14. {
    15.     public EventSO eventSO;
    16.     public UnityEvent callbacks;
    17.  
    18.  
    19.     void OnEnable()
    20.     {
    21.         eventSO.listeners.Add(new UnityEventAndHolder(this, callbacks));
    22.     }
    23. }
    With a bit of sugar-coating (using Odin Inspector, but its not mandatory) here is the inspector of an Event Scriptable Object
     
    Last edited: Apr 18, 2022