Hey everyone. Long story short, I have a huge amount of code written on top of Cocos2d JS that we want to put into Unity. I wrote some complicated regex stuff to do the bulk of the necessary changes (outside of API changes), but I’m currently stumped on one thing: bind() and call().
I noticed these are actually defined functions in Unityscript, with or without a capital letter, but I’m not sure how they’re supposed to function. Does anyone have good advice on how they work, or what I should do instead? The closest to existing code the better, since like I said this is a massive codebase.
The specific things we use bind for:
To make sure a function is in the correct scope.
To inject parameters into the function (usually to handle potential closure issues).
Example:
var callbackFunction = function( insertedParameter, errorCode )
{
if (errorCode)
{
this.doSomethingWhatever(insertedParameter);
}
};
this.sendServerMessage( "doAThingy", callbackFunction.bind( this, "my useful string" ) );
We don’t actually have any server stuff in our game, but I used one as an example because it’s a common case where JS people use callbacks / anonymous functions. So the gist in the above is that we have an anonymous function defined that can handle an error that might be sent as a result of a server call. We want the function to basically be considered a part of “this”, treated as a member of it, for the sake of scope. We ALSO want to be able to send insertedParameter through, even though sendServerMessage() is expecting to only send a single param, the errorCode, through. Any parameters inserted with bind() go before the “actual” parameters of the function.
So… how can I do this in Unityscipt? FYI, we sometimes don’t want the scope to be bound to “this”, it may be any object.
Thank you!
PS - Are there are docs on exactly how Unityscript works and its syntax? Like a full API search? I can’t find anything really.
Not entirely, at least nothing that’s clean and concise. There’s a reason that pretty much the whole Unity sphere is shifting over to C#.
I don’t know what the syntax is in Unityscript (I’m not 100% certain it’s even supported), but I think the magic word you’re looking for is ‘delegate’. They’re commonly used for callbacks and for event triggers in C#. I assume that’s what call() and bind() do.
Additionally. both, Unity JS and C# are based at Mono. What works with C# should also work with Unity JS. When you search for stuff that you cannot find in the Unity API then you may find it in the C# docs.
Yeah, I also do Unity projects on the side and always use C#, which is documented very well. The problem is I can’t even properly Google how to do stuff in JS because normal JS options usually show up, not whatever Unity uses.
Google will not lead you to your goal here. Unity JS is a Unity language only. As told, the place to look is the Unity Manual and the Unity API. And when unsure, this forum here, including Unity Answers.
wiki.unity3d.com has a page under Programming called UnityScript vs JavaScript (can’t link, forum broken on my phone) It touches some of the things I think you’re asking about here, like the fundamental difference in the this keyword, which from what i read bind() seems to tinker with (never javascripted myself couldnt quite get the concept). from what i understand unityscript is pretty much the c# language with javascript syntax. never seen the functions asked about discussed in this forum nor in any unityscript code i looked at. Leads me to believe those concepts are not supported. Id dont know.
I know you’re trying to help, Tiles, but it’s not there, and I did read it. Yes, it says JS has no delegate system. It says you use anonymous functions for that, which is exactly what I have. It says nothing, however, about possible ways to inject parameters, or what exactly happens to the scope with anonymous functions. Which are the two big questions I’m asking.
:facepalm: What does method overloading have to do with this at all? If you can’t be helpful then don’t post; and being mildly condescending to someone when you clearly don’t have a good grasp of what’s being asked isn’t helpful.
The general pattern for this in C# would be to pass an Action or Func to whatever method needs to use the callback. AFAIK these are available to UnityScript but I honestly couldn’t say what the syntax would be and I don’t believe it can handle lambda expressions (although you don’t need them). So it’d be something like this
void Foo(Action<string> callback)
{
string s = GetAString();
if (callback != null) callback(s);
}
Action<string> cb = s => Debug.Log("got a callback: " + s);
Foo(cb);
// or
Foo(delegate(string s) { Debug.Log("got a callback: " + s); });
I’m not sure what you mean when you say inject parameters. Delegates are called with whatever arguments you pass to them. Do you mean optional arguments? In terms of scope, anonymous functions follow the same scope rules of any other closure.
I’m hesitant to mention it with @Tiles on the thread. But this resource does not exist. One of the key reasons UnityScript is slowly dying is lack of proper documentation. And with user numbers so low, and mostly noob coders, Unity isn’t about to put any effort into documenting how to implement advanced .NET features.
The elephant in the room is if you want good, detailed documentation you might want to consider jumping to C#.
Yep I might try to replace everything with C#. Which would potentially be a bigger task but JS is annoying.
By inject parameters, I mean basically this:
You pass a callback function to something, say a server response, that expects to pass in just one “error” parameter.
Later, you create an anonymous function as the callback. But you want this function to actually use 2 parameters, just because of the use case you have. Maybe you want to pass in “callerIdentifier” or something. Anything that you want your anonymous function work with.
The server response is expecting a function with only one parameter, and that’s basically what it gets. “error” is passed into your callback, no problem.
Because you created the anonymous function with an additional injected parameter (“callerIdentifier”), when the callback function actually gets called, it has 2 parameters: the error, that the server response passed in, and the callerIdentifier, which you injected.
Trying to explain it, this sounds completely insane to me and an anti-pattern. Unfortunately, it’s one of the many common things you do in real JS to try to corral some of the stuff you get in a good object oriented language. Well, really any good language.
Because the value of a local variable outside of an anonymous function can’t always be relied upon, it’s good practice to insert a parameter with bind. Another common way people do it in JS is like the example here. But bind() is more reliable since you could accidentally shadow “self” or something down the line. Or it could have a different value if its value is changed before the function resolves.
//common way of doing stuff in JS, avoiding parameter injection or scope change with bind()
var self = this;
var callerIdentifier ="example";
var callbackFunction = function(error)
{
self.doSomething(callerIdentifier, error);
};
server.doThing(value, otherValue, callbackFunction);
@KelsoMRK - I’ll check out Actions. I just made an empty Unity project and am trying random options out, will post findings here as a sort of documentation.
You’re talking about dependency injection that a lot of JS frameworks provide.
There are IOC frameworks out there in C# (obviously) and a few people have tried to get them working in the context of Unity but it hasn’t really caught on and I don’t know how good the UnityScript support was for them (but I can guess).
It’s really comes down to a fundamental difference in how ECMAScript JS is designed. (ie - functions are actually objects and therefore don’t really care how many arguments they get)