Variable functions

Hello,

As I posted in the showcase section of the forum, I’m currently working on a in-game console. [Click Here]
I’ve got the basics pretty good i think but there’s one problem; I have a variable with the name of the function of each command and I know I can call this function using this:

gameObject.SendMessage (variableFunction,variableToPass);

The problem is that with this function I only can use 1 variable in the function. What I could do is hash all the variables together, pass them to the function and then dehash them but I don’t prefer this method.

If I remember correctly I used variable functions before with another method but I can’t find it back on google or in my projects…

Does anyone know a way that allows me to use more variables in the functions?

Greetings,
Peter

SendMessage can only use one variable. Calling a function directly doesn’t have that limitation. You can make a custom class which contains multiple elements, and pass a single variable made with that class.

–Eric

I thought it would be something like that, but when I try that I get an error…

InvalidCastException: Cannot cast from source type to destination type.

This is the function that handles the commands:

function HandleConsoleCommands () {
	if(pressedEnter){
		AddFeedback(consoleInput);
		var inputArray : Array = consoleInput.Split(" "[0]); // Split the text where there is a space
		if(consoleCommandsMatch.length >= 1){
			if(inputArray[0] == consoleCommands[consoleCommandsMatch[0]]){
				//Debug.Log("Handle: " + inputArray[0]);
				
				// Create String with variables
				/*var tVariables : String = "";
				for(var i : int = 1; i < inputArray.length; i++){
					if(i >= 2){
						tVariables += ",";
					}
					tVariables += inputArray[i];
				}*/
				
				if(inputArray.length >= 2){
					//gameObject.SendMessage (consoleCommandsFunction[consoleCommandsMatch[0]], inputArray[1]);
					consoleCommandsFunction[consoleCommandsMatch[0]](inputArray[1]);
				}
				else {
					gameObject.SendMessage (consoleCommandsFunction[consoleCommandsMatch[0]]);
				}
			}
			else {
				AddFeedback("Error: Unknown function");
			}
		}
		else {
			AddFeedback("Error: Unknown function");
		}
		consoleInput = "";
	}
	pressedEnter = false;
}

Use reflection to find wanted method and send it to all nodes recursively

I’m afraid I don’t really understand what you mean…
Could you explain it a bit more?

You can do something like this

MethodInfo method = typeof(SomeType).GetMethod("SomeMethod");
method.Invoke(someObject, new object[] { methodParams });

Hmm I can’t get it to work…

First of all it took me some time to find out you’re using C# in your example :stuck_out_tongue:
The method Invoke can only have 2 variables:

MonoBehaviour.Invoke  
function Invoke (methodName : String, time : float) : void

So Invoke should not be able to do this right?

This is different Invoke. I am talking about MethodInfo.Invoke

	var info = typeof(MyClass).GetMethod("A");
	var params : System.Object[]; 
	info.Invoke(myObject, params);

calls method A that exists in class MyClass on object myObject (of type MyClass or inherited from it) and sends defined params

I’m still not getting it to work…

When I try this:

var info = typeof(ConsoleController).GetMethod(consoleCommandsFunction[consoleCommandsMatch[0]]);
var params : System.Object[]; 
params.Push(inputArray[1]);
info.Invoke(gameObject, params);

I get this error:

MissingMethodException: Method not found: 'ConsoleController.GetMethod'.

And when I try to do this:

//var info = typeof(ConsoleController).GetMethod(consoleCommandsFunction[consoleCommandsMatch[0]]);
var params : System.Object[]; 
params.Push(inputArray[1]);
this.Invoke(gameObject, params);

I get this error:

Assets/Scripts/ConsoleController.js(148,52): BCE0017: The best overload for the method 'UnityEngine.MonoBehaviour.Invoke(String, float)' is not compatible with the argument list '(UnityEngine.GameObject, Object[])'.

Btw, I can’t find any unity documentation about “MethodInfo.Invoke”

It’s not Unity, it’s .NET, and you can find all the .NET docs on MSDN. (Technically it’s Mono, but the .NET docs are better than the Mono docs.)

–Eric

I think you are being led down the wrong path here. There’s no need to use reflection for what you are trying to do.

Eric has already given you the answer. You can pass an Array, a List, an Object… whatever you want to that method using sendMessage(methodName,params). If you have a bunch of strings you could just pass the entire Array to the function.

But the problem is that i’m sending an array then… I want to be able to call a function like this:

NewFunction (tString1 : String, tString2 : String) {

}

As I said in my first post I do not want to send a array and then need to dehash it… I could do this but its better if I could do it as I want it to :slight_smile: Because it’s going to be a lot of functions I can call with this script…

You can do that fine if you call the function directly. If you use SendMessage, you can only use one argument.

–Eric

Oke let me explain it again:

I’m making a in-game console http://forum.unity3d.com/threads/114786-In-game-Console
In this console I have a textfield where I type into. When I press enter I cut this string in to 1 or more parts where ever there is a space.

So when I type this:

QualitySettings.Quality Fastest

I get the variable inputArray becomes this:
(“QualitySettingsQuality”,“Fastest”)

Then I call the QualitySettingsQuality function is called with one argument (“Fastest”).

The problem is, I can only use 1 argument right now… I want to be able to pass as many arguments as the inputArray is long -1.

To give a better view; this is the function I use to call the variable functions:

function HandleConsoleCommands () {
	if(pressedEnter){
		AddFeedback(consoleInput);
		var inputArray : Array = consoleInput.Split(" "[0]); // Split the text where there is a space
		if(consoleCommandsMatch.length >= 1){
			if(inputArray[0] == consoleCommands[consoleCommandsMatch[0]]){
				//Debug.Log("Handle: " + inputArray[0]);
				
				// Create String with variables
				/*var tVariables = new Array ();
				for(var i : int = 1; i < inputArray.length; i++){
					tVariables.Push(inputArray[i]);
				}*/
				
				if(inputArray.length >= 2){
					gameObject.SendMessage (consoleCommandsFunction[consoleCommandsMatch[0]], tVariables);
					//consoleCommandsFunction[consoleCommandsMatch[0]](tVariables);
					//Invoke(consoleCommandsFunction[consoleCommandsMatch[0]], 0,inputArray[1]);
					//var info = typeof(ConsoleController).GetMethod(consoleCommandsFunction[consoleCommandsMatch[0]]);
					//var params : System.Object[]; 
					//params.Push(inputArray[1]);
					//this.Invoke(gameObject, params);
				}
				else {
					gameObject.SendMessage (consoleCommandsFunction[consoleCommandsMatch[0]]);
				}
			}
			else {
				AddFeedback("Error: Unknown function");
			}
		}
		else {
			AddFeedback("Error: Unknown function");
		}
		consoleInput = "";
	}
	pressedEnter = false;
}

If you really need your function to have that signature, then just make another function that accepts the array, then calls the other function

FunctionThatAcceptsArray (stringArray:Array) {
   FunctionThatExpectsArguments(stringArray[0],stringArray[1],stringArray[2]);
}

FunctionThatExpectsArguments(str1:String,str2:String,str3:String) {
//do stuff
}