Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Use of Arguments like in JS?

Discussion in 'Scripting' started by littlelingo, Dec 12, 2006.

  1. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    Is there a way to do something like this in Unity JS?

    Calling a function from another function:

    Code (csharp):
    1. function test(){
    2.      test2(arg1, arg2, arg3);
    3. }
    4.  
    5. function test2(){
    6.      print (arguments[0]);
    7.      print (arguments[1]);
    8.      print (arguments[2]);
    9. }
    10.  
    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.

    Any ideas?

    Thanks.

    -- Clint
     
  2. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    In C# you can pass an array to a function using params:

    Code (csharp):
    1.  
    2. public void Test(params int[] myArray)
    3. {
    4.   int a = myArray[0];
    5. }
    6.  
    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.

    -Jeremy
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,777
    Yeah, the same thing can be done in JS:

    Code (csharp):
    1. function test(){
    2.      test2([arg1, arg2, arg3]);
    3. }
    4.  
    5. function test2(arguments : Object[]){
    6.      print (arguments[0]);
    7.      print (arguments[1]);
    8.      print (arguments[2]);
    9. }
    At least, that -should- work, I haven't tried it with the generic Object class, only an array of strings.
     
  4. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    That is not quite the same thing... the params keyword in C# will eat up the arguments and automatically convert them to an array.

    Boo does support a similar construct, but I am afraid the fature has not made it into javascript yet.
     
  5. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    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
     
  6. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    Could IQuackfu be used to automaitcally wrap getcomponents so I could do

    MyComponent.myVector.x = 1

    instead of

    GetComponent (MyComponent).myVector.x = 1

    ?
     
  7. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    Sadly, you have to reference a ducktyped variable at the start of the statement. MixupGO does something similar, so you can do:
    Code (csharp):
    1. me.MyComponent.myVector.x = 22;
    2. me.OtherComponent.text = "yehaw";
    Or even, if the property/field names are unique*):
    Code (csharp):
    1. me.myVector.x = 22;
    2. 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 :D :twisted:
     
  8. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    Thanks for the input all!

    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?

    Thanks.

    -- Clint
     
  9. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    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.
     
  10. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    Ah, okay I see now.

    Thanks for the clarification freyr!

    Regards.

    -- Clint
     
  11. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    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.
     
  12. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    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.)

    Code (csharp):
    1. //MonoBehaviourEx.js -- use this as a base class instead of normal MonoBehaviour
    2. import System.Reflection;
    3.  
    4. class MonobehaviourEx extends MonoBehaviour, Boo.Lang.IQuackFu {
    5.     protected var arguments : Object[] = [];
    6.  
    7.     function QuackInvoke(name : String, args : Object[]) : Object {
    8.         var t : System.Type = this.GetType();
    9.         var at = new System.Type[args.Length];
    10.         for (var i=0;i<args.Length;i++)
    11.             at[i]=args[i].GetType();
    12.        
    13.         arguments=args; // Allows accessing the arguments array from the function
    14.        
    15.    
    16.         // First test if the method is defined with arguments defined
    17.         var mi : MethodInfo = t.GetMethod(name, at);
    18.  
    19.         if(mi) {
    20.             var result= mi.Invoke(this, args);
    21.             arguments = []; // Clear the arguments array
    22.             return result;
    23.         }
    24.  
    25.         // Then if there is one without any arguments
    26.         mi = t.GetMethod(name, []);
    27.         if(mi) {
    28.             var result= mi.Invoke(this, []);
    29.             arguments = []; // Clear the arguments array
    30.             return result;
    31.         }
    32.  
    33.         // If not -- throw an error.
    34.         var s = "(";
    35.         for (var j=0;j<at.Length;j++)
    36.             s+=at[j]+((j<at.Length-1)?", ":"");
    37.         s+=")";
    38.        
    39.         throw System.MissingMethodException("Method '"+name+s+"' not found in class "+this.GetType());
    40.     }
    41.    
    42.     function QuackGet(name : String) : Object {
    43.         var t : System.Type = this.GetType();
    44.         var fi : FieldInfo = t.GetField(name);
    45.        
    46.         // First test if the field is defined statically
    47.         if (fi) {
    48.             return fi.GetValue(this);
    49.         }
    50.         throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
    51.     }
    52.    
    53.     function QuackSet(name : String, value : Object) : Object {
    54.         var t : System.Type = this.GetType();
    55.         var fi : FieldInfo = t.GetField(name);
    56.        
    57.         // First test if the field is defined statically
    58.         if (fi) {
    59.             fi.SetValue(this, value);
    60.             return value;
    61.         }
    62.         throw System.MissingMethodException("Field '"+name+"' not found in class "+this.GetType());
    63.     }
    64.  
    65. }
    Then use it like this
    Code (csharp):
    1.  
    2. class Mybeaviour extends MonoBehaviourEx{
    3.    
    4.   function test(){
    5.      this.test2(arg1, arg2, arg3); // Note explicit this. required to let DuckTyping kick in
    6.   }
    7.  
    8.   function test2(){
    9.      print (arguments[0]);
    10.      print (arguments[1]);
    11.      print (arguments[2]);
    12.   }
    13.    
    14. }
    15.  
     
  13. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    That is excellent freyr! I will give it a go...

    I gotta learn more about Boo and IQuackFu because there seems to be some cool things you can do with it!

    Appreciate the help!

    -- Clint
     
  14. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    You're welcome. My middle name will henceforth be known as IQuackFu.

    --
    Keli IQuackFu Hlodversson :p
     
  15. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    :)

    I am running into a problem with this line:

    Code (csharp):
    1. class MonobehaviourEx extends MonoBehaviour, Boo.Lang.IQuackFu {
    The compiler is freaking on the comma between MonoBehaviour, Boo.Lang.IQuackFu

    I am not sure how to even extend this way... Any ideas?

    Thanks.

    -- Clint
     
  16. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    I'm not sure either. I was betting on the comma. Either leave out the comma or replace it with another "extends".

    Edit: Just read some specs... it's supposed to read
    Code (csharp):
    1. class MonoBehaviourEx extends MonoBehaviour implements Boo.Lang.IQuackFu {
     
  17. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    I tried without the comma and with an additional extends with no luck... :-(

    Any other thoughts?

    Thanks,

    -- Clint
     
  18. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    The spec says "class classname extends base_class implements interface1, interface2, .... {"
     
  19. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    The implements is throwing an error in the compiler:

    "Unexpected token : implements."

    I am also getting an Unexpected token error for "protected" which is also in the spec. :-(

    hhhmmmm...

    -- Clint
     
  20. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    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.
     
  21. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    Crap. ;-)

    Okay, I'll see if I can do the conversion... It will be sweet once it gets working...

    Thanks for all the help!

    -- Clint
     
  22. littlelingo

    littlelingo

    Joined:
    Jul 18, 2006
    Posts:
    372
    Okay. Not having any luck and with the tight timeframe I have... I am gonna have to find some other not as elegant solution.

    Thanks again for the time and I'll need to try and figure out all the errors I am getting in the conversion at some other time.

    Regards.

    -- Clint