- Home /
Can you make an array of functions?
Hey,
My problem is that I want to randomly call a function from an array of functions.
What I have at the moment is a stripped down version of a shuffle bag (I think) where each value in the array is a string, which is then used to call the function once it is selected.
However, I'd like to cut out this unnecessary step, which could be possible if functions can be assigned to a value in an array. I have little to no computer science experience so I'm not sure if this is possible. Whilst looking on the internet I've found references to something called 'Delegates' but I'm struggling to understand it, and therefore work out if it is useful to me.
Here are the relevant parts of the script I have at the moment:
// Shuffle Bag Variables
var shuffleBag = new Array ();
var idx : int;
var pick : boolean = true;
// Set up the shuffle bag
shuffleBag[0] = "Crouch";
shuffleBag[1] = "StretchArms";
shuffleBag[2] = "ScratchHead";
shuffleBag[3] = "RollHead";
shuffleBag[4] = "Wave";
// Shufflebag procedure
function WhichMovement (){
if(pick == true){
idx = Random.Range(0, shuffleBag.length);
var movement = shuffleBag[idx];
shuffleBag.RemoveAt(idx);
if(movement == "Crouch"){
Debug.Log("Crouch");
pick = false;
Crouch();
}
else if(movement == "StretchArms"){
Debug.Log("StretchArms");
pick = false;
StretchArms();
}
else if(movement == "ScratchHead"){
Debug.Log("ScratchHead");
pick = false;
ScratchHead();
}
else if(movement == "RollHead"){
Debug.Log("RollHead");
pick = false;
RollHead();
}
else if(movement == "Wave"){
Debug.Log("Wave");
pick = false;
Wave();
}
}
}
As you can see, if there is a possibility to put functions into an array, and call them from the array I can get rid of the horrible if/else if stuff.
Any help would be appreciated.
also consider using a switch-case ins$$anonymous$$d of a cluster of if statements :
switch( movement )
{
case "Crouch" :
//do stuff
break;
case "StretchArms" :
//do stuff
break;
case "ScratchHead" :
//do stuff
break;
// etc etc
}
Answer by Loius · Nov 30, 2012 at 05:12 PM
You can do this with Javascript (it's "safer", type-wise, in C#).
[side note: Never use Array. It's horrible at everything. Use List. or [] arrays instead]
The type of a function is 'Function' (yay), and you call the function by adding () to the end of the variable:
var functions : Function[] = new Function[ 10 ];
...
functions[0] = StrechArms;
functions[1] = Wave;
// etc
...
function DoFunctionInSlot( slot : int ) {
functions[slot]();
}
Note that a Function can represent any function of any return type and any parameters, while a C# delegate is 'strictly typed' to a specific set of return type & parameters - so be careful not to put multiple 'types' of Function into the same array - I've never tried that, no idea what would happen. :)
Not quite; the strictly-typed function type is "function(typeOrTypes):type". So this would create an error:
function Start () {
var blah : function(int):String = Foo;
print ( blah(42) );
}
function Foo (x : int) : int {return x;}
function Bar (x : int) : String {return x.ToString();}
Changing it to
var blah : function(int):String = Bar;
will work, since the types match. The idea of the Function[] type is that it is indeed a collection of any kind of function, so it's quite O$$anonymous$$ to put different "types" of functions into the same array, though I think you wouldn't normally do that, since it's obvious the many ways that could fail (and at runtime, rather than compile time). ;)
Ha! I didn't know Function came in a strongly-typed variety. Time to go fix up my code AGAIN. :)
The reason why I was using Array was because the array gets resized as I remove items from it. I thought you could not do that with [] arrays. However, I don't know anything about lists so I'll go look that up.
Lists are surprisingly easy to implement and use once you know how. Here is a useful link : http://wiki.unity3d.com/index.php?title=Which_$$anonymous$$ind_Of_Array_Or_Collection_Should_I_Use?
Scroll down to Generic List. Here are my footnotes :
// to use List
import System.Collections.Generic;
// declare
var inRangeList : List.< GameObject > = new List.< GameObject >();
// Add object to list :
inRangeList.Add( theItem );
// length
inRangeList.Count;
// from position
inRangeList[ v ]
// empty list
inRangeList.Clear();
// send to builtin array
inRangeList.ToArray();
Yeah I've actually ended up using a list of strings and the using Invoke as suggested by Jordan. It's not the prettiest was to do do it, but it gets the job done which is all I really need.
Answer by Landern · Nov 30, 2012 at 05:07 PM
Sure you can, then use Invoke to execute the method:
The performance won't be as good as a direct call to the method/function.