Hey,
I am trying to pass Dictionary entries as method calls. Currently, a member on these boards suggested I used System.Action, which is great for methods that don’t take any parameters. In my case, my methods have parameters.
I am creating a Dictionary in order to check what is going to happen upon collision of two objects, instead of using an extensive switch. Thus, I have an IEnumerator which checks the distance between the two objects. Once it exits, it will invoke the appropriate method, by making a match from the string I am passing. This string is then matched with the Dictionary’s entries and invokes the corresponding method.
private Dictionary<string, System.Action> moveUnitActions = new Dictionary <string, System.Action> ();
public void RemoveUnit (GameObject whichUnit) {
Destroy (whichUnit);
}
public IEnumerator MoveUnitTowardsUnit (GameObject whichUnit, GameObject whereTo, float speed, string collisionEvent) {
while (Vector3.Distance (whichUnit.transform.position, whereTo.transform.position) > 15f) {
whichUnit.transform.position = Vector3.MoveTowards (whichUnit.transform.position, whereTo.transform.position, Time.deltaTime * speed);
yield return null;
}
//block that checks for the proper action
}
moveUnitActions ["destroy"] = () => RemoveUnit(); //PROBLEM here.
I am aware that the line indicated as “PROBLEM here.” is wrong. I tried so many different syntax combinations with lambda expressions that I no longer remember the original. In order to point the “destroy” entry to the RemoveUnit() method, I need a GameObject argument (because this is how the said method works). However, the gameobject will vary, depending on the unit I wish to destroy.
According to what I have seen, there are also Func<> and Action<>, with which I am not experienced. Is Action<> indeed the answer to my problem here and how do I modify the lambda expression? Finally, how will I invoke the method, once I find a match in the Dictionary? As simple as RemoveUnit(myUnit);?
Cheers
I guess you want something like that?:
public void RemoveUnit(GameObject whichUnit)
{
Destroy(whichUnit);
}
private Dictionary<string, System.Action<GameObject>> moveUnitActions = new Dictionary<string, System.Action<GameObject>>();
private void populate()
{
moveUnitActions["destroy"] = RemoveUnit;
}
public void helloWorld()
{
GameObject obja = new GameObject();
//make sure that you have populated your dictionary before calling that:
moveUnitActions["destroy"](obja);
}
P.S. Here is an example for your updated question:
public void RemoveUnit(object whichUnit)
{
Destroy((GameObject)whichUnit);
}
private int someInt = 0;
public void AddIntegerAndPostString(object pass)
{
Tuple<List<int>, string> iInt = (Tuple<List<int>, string>)pass;
foreach (int o in iInt.Item1)
{
someInt += o;
}
Debug.Log(iInt.Item2);
}
private Dictionary<string, System.Action<object>> moveUnitActions = new Dictionary<string, System.Action<object>>();
private void populate()
{
moveUnitActions["destroy"] = RemoveUnit;
moveUnitActions["addPrint"] = AddIntegerAndPostString;
}
public void helloWorld()
{
GameObject obja = new GameObject();
//make sure that you have populated your dictionary before calling that:
moveUnitActions["destroy"](obja);
List<int> ilist = new List<int>();
ilist.Add(1);
ilist.Add(5);
Tuple<List<int>, string> iInt = new Tuple<List<int>, string>(ilist, "helloWorld");
moveUnitActions["addPrint"](iInt);
}
If you want to see a parameters as they are then you should create a custom Class/Interface (depending on the case) instead of adding functions to Dictionary.
If you need a returnable value from function then use:
Func<object, object>
instead of:
Action<object>
Func and Action are delegates, thus function pointers.
You can embed a function’s property into a variable.
Action returns void and Func returns the last parameter of the Func thus
Func<int, bool>
takes an int and returns a bool.
I think you need something as simple as this
Dictionary<string, Action> moveUnitActions = new Dictionary <string, Action> ();
void RemoveUnit(GameObject whichUnit)
{
moveUnitActions["objectName"] = () => Destroy(whichUnit);
}