Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by JeffreyBennett · Jun 14, 2020 at 08:51 PM · js-c#-together

Use C# Script to Call JavaScript Function/Method

I'm doing something wrong and I don't know what, so maybe if I detail my process someone can point to my error.

I'm using information in the documentation from here > https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html

Step 1 From that page I just copy and paste the entire first section of code into a JavaScript editor file, then save it as a Javascript library and name it something like js_test.jslib:

Code Sample:

 mergeInto(LibraryManager.library, {
 
   Hello: function () {
     window.alert("Hello, world!");
   },
 
   HelloString: function (str) {
     window.alert(Pointer_stringify(str));
   },
 
   PrintFloatArray: function (array, size) {
     for(var i = 0; i < size; i++)
     console.log(HEAPF32[(array >> 2) + i]);
   },
 
   AddNumbers: function (x, y) {
     return x + y;
   },
 
   StringReturnValueFunction: function () {
     var returnStr = "bla";
     var bufferSize = lengthBytesUTF8(returnStr) + 1;
     var buffer = _malloc(bufferSize);
     stringToUTF8(returnStr, buffer, bufferSize);
     return buffer;
   },
 
   BindWebGLTexture: function (texture) {
     GLctx.bindTexture(GLctx.TEXTURE_2D, GL.textures[texture]);
   },
 
 });

Step 2 In my Unity project I go into my Assets folder and create a folder named Plugins. so that is Assets > Plugins.

Step 3 I put the js_test.jslib file into that Plugins folder.

Step 4 In my Unity project, under Assets > Scripts I create a new C# script and name it something like cs_js_test.cs.

Step 5 I go back to the Unity documents and copy the entire second section of code, pasting it into that C# script, so it looks like:

Code Sample:

 using UnityEngine;
 using System.Runtime.InteropServices;
 
 public class NewBehaviourScript : MonoBehaviour {
 
     [DllImport("__Internal")]
     private static extern void Hello();
 
     [DllImport("__Internal")]
     private static extern void HelloString(string str);
 
     [DllImport("__Internal")]
     private static extern void PrintFloatArray(float[] array, int size);
 
     [DllImport("__Internal")]
     private static extern int AddNumbers(int x, int y);
 
     [DllImport("__Internal")]
     private static extern string StringReturnValueFunction();
 
     [DllImport("__Internal")]
     private static extern void BindWebGLTexture(int texture);
 
     void Start() {
         Hello();
         
         HelloString("This is a string.");
         
         float[] myArray = new float[10];
         PrintFloatArray(myArray, myArray.Length);
         
         int result = AddNumbers(5, 7);
         Debug.Log(result);
         
         Debug.Log(StringReturnValueFunction());
         
         var texture = new Texture2D(0, 0, TextureFormat.ARGB32, false);
         BindWebGLTexture(texture.GetNativeTextureID());
     }
 }

Step 6 In my Unity project, I drag that C# script and place it on the camera (because that is a game object that is active at the beginning of the game).

Step 7 I attempt to play the game (Play button in the Unity Editor).

My Result The console shows the following error: EntryPointNotFoundException: Hello cs_js_test.cs.Start() (at Assets/Scripts/cs_js_test.cs:27)

Line 27, where the error is, is the first call to a function, the Hello() function in the JavaScript library file.

My question is this: I don't see how the C# script is supposed to "know" that there is a JavaScript library named js_test.jslib, even if it is in the Plugins folder. In the C# script are calls to import a dynamic link library, such as at line 7 - [DllImport("__Internal")] , however I don't see any way to reference my exact .jslib file, which is named js_test.jslib.

Surely that is the reason for the "I can't find the function named "Hello()" error I'm getting, because it doesn't know to look in that file. Shouldn't there be something in the C# script that says "go to Assets > Plugins and open the file named js_test.jslib?"

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jun 14, 2020 at 09:08 PM

A jslib is a native javascript library. Of course that only works in a build webgl application. When you test your game inside the Unity editor you can not run native javascript code. So of course when you test inside the editor those methods do not exist and the extern linking fails.


The name of your js lib is irrelevant. The actual js lib contains code that actuall merges the content of your lib into the js lib manager so the methods are available "globally" from the virtual machine environment in which your game code runs in.


As already mentioned you can not make the javascript code to work inside the editor. However you can provide an alternative implementation when testing inside the editor (or when the target platform isn't webgl). A common solution is what I did in my URLParameters script. The actual js lib is included in that cs script and is auto-extracted by some editor code. The actual extern definitions are here, though are placed inside pre-processor tags so they are only included in an actual webgl build. When testing inside the editor those alternative methods are used which are essentially stubs / mocks which allows testing of the usage without the actual methods being available.


Any "extern" method definition is essentially a runtime linked method. So if the actual implementation is available or not is not known at compile time. So an error is thrown when you try to call such a method and no implementation was found. When you test your example in an actual WebGL build it should just work fine. However I would always recommend to use pre-processor tags and provide stub methods for all other platforms (including in-editor-testing).

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jun 14, 2020 at 09:20 PM 0
Share

Note that the same limitations hold for native plugins for other targetplatforms which are not compatible with the editor platform. So you can not "test" native iOS or Android plugins inside the Unity editor. Likewise when you develop on a windows machine with a windows Unity editor but your target platform is linux and you include native linux libraries you can't test them inside the editor.

avatar image
0

Answer by JeffreyBennett · Jun 15, 2020 at 05:01 PM

I really appreciated your reply!

I've cut this down to only the jslib and c# script, but the the build to WebGL is failing - This is in Unity 2019.3.0f6

I've opened a brand new project, which does have Standard Assets from the Unity Asset Store, and the FPSController from the Standard Assets is in the scene, replacing the default camera.

I normally get an error or two when I first bring in the Standard Assets to a new project, but those have been cleared. The game plays in the editor with no errors or warnings.

After ensuring that runs with no issues, I've brought in the jslib and the C# script as described above, and then tried to build in WebGL.

So basically all that is in the game now is:

  • The FPSController from the Standard Assets

  • A cube

  • A plane

  • A directional light

  • The js library is in the Assets > Plugins folder.

  • The C# script to interact with that library is in Assets > Scripts.

Building to WebGL fails and gives the following warnings and errors:

  • Warning - CS0618 - 'Texture.GetNativeTextureID()' is obsolete: 'Use GetNativeTexturePtr instead.' - This was coming from lines 39&40 of the jslib copied from the documents, so I commented those out and the warning is gone on subsequent builds.

  • Error - Failed running python -E "/Applications/Unity/2019.3.0f6/PlaybackEngines/...long path.../Assets/Temp/emcc_arguments.resp"

  • Error - Exception: Failed building WebGL Player. - UnityEditor.WebGL.ProgramUtils.StarProgramChecked (System.Diagnostics....)...long path...WebGL.extensions/ProgramUtils.cs:48

  • Error - Build completed with a result of 'Failed' - UnityEngine.GUIUtilityProcessEvent(Int32, IntPtr)(at /Users/builduser/...long path...IMGUI/GUIUtility/:cs:187)

  • Error - UnityEditor.BuildPlayerWindow - BuildMethodExceptions: 3 errors at UnityEditor.BuildPlayerWindow+DefaultBuildMethods...long path..:cs:191

So, with nothing in the project to speak of, the game will not build to WebGL using just the jslib from the documents section. So is this an issue with my version of Unity (an update is available, to 2019.4.f01), with something in the jslib / c# script I copied and pasted in from the Documentation, or (more likely) something I'm forgetting to do / add?

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JeffreyBennett · Jun 15, 2020 at 05:32 PM 0
Share

Ok, updating to 2019.4.0f1 did NOT fix the issue.

The build to WebGL gave the same result. For what it may be worth, the Scripting window with the progress bar that shows while it is building gets about 90% done, and it says Compile Web Assembly $$anonymous$$odule, then it goes poof and the errors show up in the console.

I get the same four red octagons as before.

avatar image JeffreyBennett JeffreyBennett · Jun 15, 2020 at 07:00 PM 0
Share

Update:

Removing the C# script from Assets > Scripts, as well as the jslib from Assets > Plugins allows a successful build to WebGL.

avatar image JeffreyBennett JeffreyBennett · Jun 15, 2020 at 07:28 PM 0
Share

Update 2 - The following worked! Huzzah!

In Assets > Plugins - A jslib file named js_test03.jslib >

// JavaScript Document mergeInto(Library$$anonymous$$anager.library, { Hello: function () { window.alert("This is a string written in a Javascript Function."); }, });

In Assets > Scripts - A C# file named js_test03.cs (probably should have named these differently, because they're potentially confusing, but whatever...) >

using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Runtime.InteropServices; public class js_test03 : $$anonymous$$onoBehaviour { [DllImport("__Internal")] private static extern void Hello(); // Start is called before the first frame update void Start() { Hello(); } / // Update is called once per frame void Update() {

 }
 */

}*

So basically what was wrong was two things:

  • I wasn't actually building the thing and testing it in Firefox from the build folder, but rather trying to test it with the play button in the Editor. Don't do that! Build it and test it in the browser.

  • I was assu$$anonymous$$g that the example files given in the documentation would work correctly as written. They didn't. But when I significantly reduced that stuff down to just a window alert, it at least builds and works when tested in the browser.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

127 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Using C# and Javascript in a project 1 Answer

Is there a way to reference a variable in another script if it's a different type of script? 2 Answers

Compilation Order Quandaries - Cross Language Game-To-Library Communication 1 Answer

Reference a JS script in a C# script? 2 Answers

Unity Scorm WebGl integration ? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges