Problem using an external JS library in Unity

Hi,

I am trying to establish a connection between my serious game (developed in unity’s javascript) and a remote learning recording system.

For that I was intending to use the TinCanJS library, which is coded in JavaScript, but when i add the TinCanJS scripts to my assets folder, i start getting a lot of syntax errors.

Is there any way for me to import the library, so i can just call the library functions from my unity scripts?

Thank you

Unity’s “JavaScript” is not JavaScript. It’s not even close. There is no common ground between JS and what Unity’s using that will allow you to import JavaScript code into Unity.

If you want to use a JS library, you’ll have to get it running in a JS engine somewhere, and then communicate with it over some protocol (like Json). You could also make a web app that lives between the remote learning system and your game, which uses your library.

The “JavaScript” Unity uses has been dubbed UnityScript by the community (and Unity uses the name internally now). It’s a .NET-language (like C#), which has been made to “look like” JavaScript. It has a bunch of anti-features, and should never be used for anything.

1 Like

JavaScript in Unity is not real JavaScript. It’s a .NET language with superficial similarities to JavaScript.

You are going to have to treat the real JavaScript as a seperate program and set up communication stuff and all that. You can’t use it out of the box.

http://wiki.unity3d.com/index.php/UnityScript_versus_JavaScript

I swear, this is like one of the weirdest things IMO… not even Unity themselves can follow any name consistency, jumping back and forth between calling it unityscript and javascript.

And yet, it’s NOT javascript.

Like it’s as if their marketing team is pushing them to call it javascript because it’s attractive to new comers who are familiar with what javascript is, so they can dig their hands in easier and not be scared of having to learn a scary new language like unityscript!

Despite them still having to learn said new language, because it’s not actually javascript.

Ughhhhhhhh

1 Like

Hi again, and thanks for your fast reply.
I have read in http://wiki.unity3d.com/index.php/Head_First_into_Unity_with_UnityScript#Use_.23pragma_strict that “3rd Party .NET libraries (e.g. XML-RPC.net) can be used by importing the .dll file as a new asset.”

There is a tincan.dll for the same library i was talking about, could that work for me somehow?

As you can see, I’m quite new to unity, so any help is appreciated.

Thanks

is ‘tincan.dll’ a .net library?

dll doesn’t necessarily mean it’s .net

also it has to be .Net 3.5 or earlier

Is it this library?

If so… yes, that’s .Net, and it says it uses .Net 3.5, so that should work (because unity actually uses a modified version of the mono framework that targets .net 2.0, but contains a lot of 3.5 in it, some parts are missing… they usually aren’t an issue, but the might bite you when importing some libraries… but give it a try, you’ll know if it fails or not when you actually use it).

Yes, that is the library i was talking about!

But since it is a C# library, i guess i should be calling its functions from a c# script, am I right or did i get something wrong?

Thanks!

As long as you’re importing the dll as a plugin, no, you don’t need to access it from C#. It can be accessed from either C# or Unityscript/JS.

There’s only one issue with accessing C# from US/JS and vice versa, and that’s got to do with unity compilation order. Your custom C# and JS scripts are compiled into separate dll’s, so they can’t access one another until they’ve been compiled, but if the compile order has one compiling after another, than you can’t access it since it’s not compiled yet.

See:

(see, see, in that there they refer to it as unityscript… come on guys, make up your damn mind!)

But this library is already compiled. So, no worries.

Ok, i understand. So, here’s what I’ve done. I go to assets->import new asset and i select the TinCan.dll file (i imagine this could be done just by dragging the file into unity). The file gets placed in the Standard Assets folder, which acording to the link you gave me is the first to get compiled.
Then in one of my scripts (placed outside of the Standard Assets folder, so it should get compiled afterwards) i have typed “import TinCan;” (the file is named TinCan.dll), but i still get an error in the console “Namespace TinCan not found, maybe you forgot to add an assembly reference?”
I have also tried import TinCan.RemoteLRS, because this is the class i’d like to use first, with the same result.

Any idea?

Thanks a lot, you have no idea how much i appreciate your help!

TinCan.dll is a dll, it’s ALREADY compiled.

You don’t need to import it using assets->import new asset, you can just drop it in a folder. Heck you could just drop it in the root Assets folder.

Also, where did you get TinCan.dll, are you 100% certain that it’s for that project?

Also, rebuild your project, or refresh your project files (Assets->Refresh), make sure that the new dll is referenced by the visualstudio/monodevelop project files.

I tried the .dll from the top of here, and can import it just fine if I put the dll under standard Assets. I dragged the file into Unity. Are you getting any error messages when you select the .dll?

If you want to import only one class from a namespace, the syntax is:

using put_whatever_here = SomeNamespace.SomeClass;

So in your case,

using RemoteLRS = TinCan.RemoteLRS;

It’s very seldom any good reason to do that - the syntax is generally used to avoid name conflicts (such as between System.Random and UnityEngine.Random)

Edit: If you’re using UnityScript, this might be failing because the language is fundamentally broken, and has probably made up it’s own syntax for imports or have made them crash on Wednesdays or whatever.

I used exactly the same dll as Baste did. I drag it into the assets folder, or standard assets folder. The difference is i am trying to reference it from a unityscript not a c#, so shouldnt i be doing imports instead of using?

Thanks!

One thing i see is the TinCan.dll file doesn’t appear in my MonoDevelop file tree. All my scripts are there, but the .dll isn’t where i placed it. I see it on the unity gui but not on MonoDevelop’s.

Here’s how my project looks like. The TinCan.dll is in the Standard Assets folder (i dragged it in there)

Then in the MyScripts folder i have a script called LRSCommunication.js, which looks like this:

And in the console i can read an error in red:
“Assets/My Scripts/LRSCommunication.js(2,8): BCE0021: Namespace ‘TinCan’ not found, maybe you forgot to add an assembly reference?”

I’ve read in some other unity3D threads that import is the unityscript equivalent of using, so that’s why i tried this way.

Hi again!

So, here’s the summary on what i’ve been doing:

I am using the tincan.dll (by dropping it in my assets folder) from the top of Releases · RusticiSoftware/TinCan.NET · GitHub, and if i create a C# script and type “using TinCan” it throws no error in the unity console.

The problem is i am working on an existing project coded in unityscript so it would be very helpful if I could use the library from a unityscript. I have read that “import library” is the equivalent in unityscript to “using library” in C#, but when I do type the “import TinCan” line, i get the following error in unity console “Assets/My Scripts/LRSCom.js(3,8): BCE0021: Namespace ‘TinCan’ not found, maybe you forgot to add an assembly reference?”.

I have also tried placing the .dll in the Plugins folder, and Standard Assets folder, but i get the same error.

Is there anything that I am doing wrong, or should I assume that this combination (using the .dll library from a unityscript) won’t work, and move on to another aproach?

Thank you!

I honestly have no idea how you make importing work in UnityScript. My default advice (never use UnityScript ever) won’t help you.

I checked the same thing, and it seems like the import statement isn’t finding the TinCan dll. It might be that UnityScript’s importing works differently.

What I did manage to work was to grab the TinCan stuff from a C# script, and then use that in UnityScript. I put this C# script next to the .dll in the Standard Assets folder:

using TinCan;

public static class TinCanBridge {

    public static RemoteLRS GetRemoteLRS() {
        return new RemoteLRS();
    }
}

Which made this UnityScript work fine:

#pragma strict

function Start () {
    var lrs = TinCanBridge.GetRemoteLRS();
}

Which means that if you just wrap everything you need from TinCan in a C# method, then you can use it. It might be that there’s a way to successfully import stuff in UnityScript, but I think just straight up switching to C# is a better use of your time.

Really, UnityScript is a bad language, Unity seems to regret that they made it, and it doesn’t exist outside of Unity. None of the forum regulars (the ones of us you’ll be asking questions if you get stuck) knows the language well, so if you run into bugs, you’ll probably be on your own unless somebody’s waiting for their build to finish and can take time to investigate.

2 Likes

put that dll in Assets/Plugins, though also why use UnityScript, it is a terrible language especially when their is C# available to use that also has many more resources available to it.

The reason I am using unityscript is because I am working on an already existing project (not mine), which is fully coded in unityscript , so I was trying to keep it that way. It’s not that I decided to use unityscript at any point.

Nevertheless, the TinCanBridge solution looks like the best option for me, so I’m going to give it a try.

Thanks a lot to all of you!

Hello again, I’m back!
The TinCanBridge solution Baste posted is working just fine, but I’ve come to trouble a few steps ahead in the process.

Instead of using an static class, i’ve decided to go for a more object oriented solution, so here’s how my “TinCanBridge” class looks like right now.

public class TinCanInterface{

    private string endpoint;
    private string user;
    private string pass;

    private RemoteLRS lrs = null;

    public TinCanInterface(string endpoint, string user, string password){
        this.endpoint = endpoint;
        this.user = user;
        this.pass = password;
    }

    public void SetupLRS(string endpoint, string user, string password){
        lrs = new RemoteLRS (endpoint, user, password);
    }

    public void SendStatement(){
       
        StatementLRSResponse lrsResponse = this.lrs.SaveStatement (new Statement ());
   
    }
}

Meanwhile, I am intending to use this from the follwing unityscript:

function Start () {

    var lrsConnection = new TinCanInterface();
    lrsConnection.SetupLRS(lrsAddress, lrsUser, lrsPass);
    lrsConnection.sendStatement();
}

function Update () {

}

As you can see, the idea is just to send an empty statement to check the connection is stablished.

The thing is i am getting an error in the unity console that i don’t understand at all. I think it has something to do with the Statement type internally using JSON, but i don’t get it. Here’s the full error drop:
Error

Unhandled Exception: System.TypeLoadException: Could not load type ‘TinCan.Json.JsonModel’ from assembly ‘TinCan, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’.

at (wrapper managed-to-native) System.MonoType:GetMethodsByName (string,System.Reflection.BindingFlags,bool,System.Type)

at System.MonoType.GetMethods (BindingFlags bindingAttr) [0x00000] in :0

at Mono.CSharp.MemberCache.AddMethods (BindingFlags bf, System.Type type) [0x00000] in :0

at Mono.CSharp.MemberCache.AddMethods (System.Type type) [0x00000] in :0

at Mono.CSharp.MemberCache…ctor (IMemberContainer container) [0x00000] in :0

at Mono.CSharp.TypeHandle…ctor (System.Type type) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetTypeHandle (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetMemberCache (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeManager.LookupMemberCache (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeHandle…ctor (System.Type type) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetTypeHandle (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetMemberCache (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeManager.LookupMemberCache (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeHandle…ctor (System.Type type) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetTypeHandle (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeHandle.GetMemberCache (System.Type t) [0x00000] in :0

at Mono.CSharp.TypeManager.MemberLookup_FindMembers (System.Type t, MemberTypes mt, BindingFlags bf, System.String name, System.Boolean& used_cache) [0x00000] in :0

at Mono.CSharp.TypeManager.RealMemberLookup (System.Type invocation_type, System.Type qualifier_type, System.Type queried_type, MemberTypes mt, BindingFlags original_bf, System.String name, IList almost_match) [0x00000] in :0

at Mono.CSharp.TypeManager.MemberLookup (System.Type invocation_type, System.Type qualifier_type, System.Type queried_type, MemberTypes mt, BindingFlags original_bf, System.String name, IList almost_match) [0x00000] in :0

at Mono.CSharp.Expression.MemberLookup (Mono.CSharp.CompilerContext ctx, System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, MemberTypes mt, BindingFlags bf, Location loc) [0x00000] in :0

at Mono.CSharp.Expression.MemberLookupFinal (Mono.CSharp.ResolveContext ec, System.Type qualifier_type, System.Type queried_type, System.String name, MemberTypes mt, BindingFlags bf, Location loc) [0x00000] in :0

at Mono.CSharp.New.DoResolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec, ResolveFlags flags) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Argument.Resolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Arguments.Resolve (Mono.CSharp.ResolveContext ec, System.Boolean& dynamic) [0x00000] in :0

at Mono.CSharp.Invocation.DoResolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec, ResolveFlags flags) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Assign.DoResolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.SimpleAssign.DoResolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec, ResolveFlags flags) [0x00000] in :0

at Mono.CSharp.Expression.Resolve (Mono.CSharp.ResolveContext ec) [0x00000] in :0

at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.BlockContext ec) [0x00000] in :0

at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.BlockContext ec) [0x00000] in :0

at Mono.CSharp.Block.Resolve (Mono.CSharp.BlockContext ec) [0x00000] in :0

at Mono.CSharp.ToplevelBlock.Resolve (Mono.CSharp.FlowBranching parent, Mono.CSharp.BlockContext rc, Mono.CSharp.ParametersCompiled ip, IMethodData md) [0x00000] in :0

Internal compiler error at Assets/Standard Assets/TinCanInterface.cs(21,21):: exception caught while emitting MethodBuilder [TinCanInterface::SendStatement]
The following assembly referenced from D:\Facultat\TFG\Entrega PFG\src\Project\Virtual PC\Assets\Standard Assets\TinCan.dll could not be loaded:
Assembly: Newtonsoft.Json (assemblyref_index=1)
Version: 8.0.0.0
Public Key: 30ad4fe6b2a6aeed
The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (D:\Facultat\TFG\Entrega PFG\src\Project\Virtual PC\Assets\Standard Assets).

Could not load file or assembly ‘Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed’ or one of its dependencies.

I am sorry that i have to come to you again, but any help will do.

Thanks a lot.