How can I add System.action to List with different parameter?

public class tester
{
public List<System.Action> Skill_List= new List<System.Action>();
void Start()
{
Skill_List.Add(skill1(transform,5,10f);
Skill_List.Add(skill2(transform,target.transform);
//I can not add the function to Skill_List
}
public static void skill1(Transform t, int line,float radius)
{
//BABABA
}
public static void skill2(Transform t,Transform target)
{
//BABABA
}

}

Thankyou for your reply^^

An expression like this:

skill1(transform,5,10f)

would actually execute your skill1 method directly and you try to store the return value inside your list which of course doesn’t make any sense.

What you need is what is called a closure. A closure is a compiler generated anonymous class which captures the variables you are using inside the closure body. What happens in the background is quite complex. Though the only important things you should remember:

  • closures are actually class instances which are generated whenever you create a closure.
  • A closure does not capture the value of a variable at the time it’s created but the variable / memory location itself.

In your specific case you can do:

Skill_List.Add(() => skill1(transform,5,10f));
Skill_List.Add(() => skill2(transform,target.transform));

Note that the => operator is the lambda operator which essentially just creates an anonymous method. The left side specifies the parameters of your anonymous method (in our case none) while the right side defines the method’s body. The lambda operator allows a very short syntax, especially for single statement / expression methods (so methods which only contain a single method call or that just evaluates to a value).

The following 3 examples are essentially equal:

Skill_List.Add(() => skill1(transform,5,10f));
Skill_List.Add(() => { skill1(transform,5,10f); });
Skill_List.Add(delegate() { skill1(transform,5,10f); });

Not relevant for your question but might help in other cases: The return type of the anonymous method is usually inferred / determined from the return value of your method body. Since skill1 has no return value (void) the anonymous method also has no return value. However imagine this:

int myMethod(int a, int b)
{
    return a + b;
}

System.Func<int> someFunc;
someFunc = () => myMethod(2, 3);

In this case our “someFunc” delegate is a method that doesn’t take any parameters but returns an int value. The equivalent syntax for the other 2 cases would be

someFunc = () => { return myMethod(2, 3); };
someFunc = delegate() { return myMethod(2, 3); };

Here’s another example with a method that takes a single int parameter and returns a string:

System.Func<int, string> action;
action = (a) => "Hello World " + a;
action = (a) => { return "Hello World " + a; };
action = (int a) => { return "Hello World " + a; };
action = delegate(int a) { return "Hello World " + a; };
action = a => "Hello World " + a;

All 5 examples are equal. Note that the last case is only possible when your lambda expression has only a single parameter. When you have more than one or zero parameters you have to use parentheses / brackets. Also note that a lambda expression can usually infer the parameter types based on what delegate type is expected. The older / explicit “delegate” syntax always requires you to specify the parameter types.

Finally I would recommend whenever you want to specify an actual method body block, use something like this:

Skill_List.Add(() => {
    skill1(transform,5,10f);
});

Usually you only want an explicit method body when you have more than one statement / expression. So it would become pure clutter to write everything in a single line.