Why can I add function taking 0 argument To UnityEvent taking 1 argument In the Editor

I have this class Scrap that contains a UnityEvent named “myUnityEvent”. This event should be invoked with one argument. I write a code that will invoke this event when the spacebar is pressed.

using UnityEngine;
using UnityEngine.Events;

[System.Serializable]
public class UnityEventTakingOneArgument : UnityEvent<int>{}

public class Scrap : MonoBehaviour{
	public UnityEventTakingOneArgument myUnityEvent;

	void Awake(){
		//myUnityEvent.AddListener(funcTakingNoArgument);
		//Oops! Cannot do this, so let's do it in the inspector instead!
	}
	void Update(){
		if(Input.GetKeyDown(KeyCode.Space))
			myUnityEvent.Invoke(42);
	}
	public void funcTakingNoArgument(){
		Debug.Log("Ahem! I don't take argument, but I get called!");
	}
}

But I can go to the Editor and add a function taking no argument to this UnityEvent (There are even functions taking string argument for you to choose):

175626-addingfunctakingnoargument2.png
Then when I press spacebar, this function taking no argument actually gets called.

So my questions are

  1. Why does Unity allows me to add function taking no argument or wrong type argument to my UnityEvent via the Editor?
  2. As I cannot add function taking no argument to UnityEvent taking 1 argument via code, how does Unity do it?
  3. When this happens and my UnityEvent gets invoked, what exactly happens to my argument (42).

I tried to look for documentation, but haven’t found clear explanation about this. So I would also appreciate links to relavant documentation.

You can add the callbacks you want when subscribing to an event. The Unity serializer is limited by the number and the types of arguments though.

If the signature of the callback matches the signature of the event, you can do this:

 [System.Serializable]
 public class UnityEventTakingOneArgument : UnityEvent<int>{}

 void Awake(){
     myUnityEvent.AddListener(funcTakingOneIntArgument);
 }
 public void funcTakingOneIntArgument(int arg){
     Debug.Log(arg);
 }

If the signature does not match, you can still add a new “fake” function with the correct signature whose sole purpose is to call the function you really want to call, and I guess, this is what Unity does behind the hood when you provide a function in the “Static parameter” list.

 [System.Serializable]
 public class UnityEventTakingOneArgument : UnityEvent<int>{}

 void Awake(){
     myUnityEvent.AddListener(fakeFunction);
 }
 public void fakeFunction(int arg){
     realFunction();
 }
 public void realFunction(){
     Debug.Log("Ahem! I don't take argument, but I get called!");
 }

Which can be shortened (but has the main drawback of not giving you the possibility to remove the listener easily)

 [System.Serializable]
 public class UnityEventTakingOneArgument : UnityEvent<int>{}

 void Awake(){
     myUnityEvent.AddListener(arg => realFunction());
 }
 public void realFunction(){
     Debug.Log("Ahem! I don't take argument, but I get called!");
 }

In this case, your argument is passed, but simply not used.