Is there a way to do something like this in Unity JS?
Calling a function from another function:
function test(){
test2(arg1, arg2, arg3);
}
function test2(){
print (arguments[0]);
print (arguments[1]);
print (arguments[2]);
}
The thought here is to blindly pass arguments and then decompose them from an arguments array that is passed along with a function call. In Javascript this was really nice when working with AddEventListener etc.
In C# you can pass an array to a function using params:
public void Test(params int[] myArray)
{
int a = myArray[0];
}
I don’t know if something like that is possible in JS, but I don’t think so.
But as for your example of sending arguments without creating your own array, I doubt it as it would be a lot slower if Unity JS had to figure out what you were doing.
If you are adventurous, you could use ducktyping and IQuackFu to implement something aking to the arguments feature. Take a look at ExpandoObject and MixupGO on the UnifyWiki to see examples on how to implement IQuackFu
Or even, if the property/field names are unique*):
me.myVector.x = 22;
me.text = "yehaw";
Not quite the same, but similar. (me.xxx is shorter than GetComponent(xxx))
*) It will in fact use the first component attached that has a property or field with the given name, so it even works with ambiguous names… You can’t just know which property you will be modifying :twisted:
Though I am not sure I am asking the question correctly. I am not asking about passing an array and I do think the params example from C# is close.
The thing I am really looking for is to pass parameters to a function without them having to be identified as arguments of the function. In normal Javascript you can use the arguments property of a function which will contain a list of the arguments passed.
That MixUpGo looks promising. One of the things I am looking to do is write a class that would Extend GameObject so that I could do something like:
GameObject.addListener(“blah”);
If I am reading correctly, this is what MixUpGo will do… Is that correct?
Not quite. You can’t extend GameObject directly. What MixupGO does is that it wraps it up in another object that proxies all calls to the game object or its components.
To be completely clear, I was not suggesting that using MixupGO directly would solve your problem, but only as an example on how you could use IQuackFu.QuackInvoke, which in your case could be used to implement a function that takes an arbitrary number of arguments.
Here’s some code you could use to simulate the arguments variable in Javascript: (As always 100% untested and guaranteed to include bugs and even syntax errors.)
//MonoBehaviourEx.js -- use this as a base class instead of normal MonoBehaviour
import System.Reflection;
class MonobehaviourEx extends MonoBehaviour, Boo.Lang.IQuackFu {
protected var arguments : Object[] = [];
function QuackInvoke(name : String, args : Object[]) : Object {
var t : System.Type = this.GetType();
var at = new System.Type[args.Length];
for (var i=0;i<args.Length;i++)
at[i]=args[i].GetType();
arguments=args; // Allows accessing the arguments array from the function
// First test if the method is defined with arguments defined
var mi : MethodInfo = t.GetMethod(name, at);
if(mi) {
var result= mi.Invoke(this, args);
arguments = []; // Clear the arguments array
return result;
}
// Then if there is one without any arguments
mi = t.GetMethod(name, []);
if(mi) {
var result= mi.Invoke(this, []);
arguments = []; // Clear the arguments array
return result;
}
// If not -- throw an error.
var s = "(";
for (var j=0;j<at.Length;j++)
s+=at[j]+((j<at.Length-1)?", ":"");
s+=")";
throw System.MissingMethodException("Method '"+name+s+"' not found in class "+this.GetType());
}
function QuackGet(name : String) : Object {
var t : System.Type = this.GetType();
var fi : FieldInfo = t.GetField(name);
// First test if the field is defined statically
if (fi) {
return fi.GetValue(this);
}
throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
}
function QuackSet(name : String, value : Object) : Object {
var t : System.Type = this.GetType();
var fi : FieldInfo = t.GetField(name);
// First test if the field is defined statically
if (fi) {
fi.SetValue(this, value);
return value;
}
throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
}
}
Then use it like this
class Mybeaviour extends MonoBehaviourEx{
function test(){
this.test2(arg1, arg2, arg3); // Note explicit this. required to let DuckTyping kick in
}
function test2(){
print (arguments[0]);
print (arguments[1]);
print (arguments[2]);
}
}
I guess this is a missing feature in the compiler then. You could get around it by translating MonoBehaviourEx into C# or Boo. You should still be able to use it from Javascript.
Btw. The error on “protected” is probably due to the compiler being confused after seeing the “implements” keyword.