Search Unity

C# and JavaScript working together

Discussion in 'Scripting' started by dkozar, Oct 12, 2010.

  1. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    I decided to post this example because I find it very usefull. It's for the people who are developing core stuff (frameworks etc.) using C#, and want to make it available to people that use JavaScript.

    This example includes:
    • using namespaces,
    • method input and output parameters
    • method overriding

    C# base class (extending MonoBehaviuor):

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. namespace Com.DankoKozar.Unity.Gui.Core.Behaviours
    4. {
    5.     public class CSharpClass : MonoBehaviour
    6.     {
    7.         protected virtual string Say(string word)
    8.         {
    9.             return "CSharp says: " + word;
    10.         }
    11.     }
    12. }
    Javascript class (extending C# class):

    Code (csharp):
    1. import Com.DankoKozar.Unity.Gui.Core.Behaviours; // import (using, include :))
    2.  
    3. class JavaScriptClass extends CSharpClass { // Javacript class extends C# class (which extends MonoBehaviour)
    4.    
    5.     function Update () { // classic Update
    6.     }
    7.  
    8.     function OnGUI() { // classic OnGUI
    9.         GUI.depth = 0;
    10.         if(GUI.Button(Rect(10, 10, 100, 100), "Click me")) {
    11.             Debug.Log(Say("Hello world!"));
    12.         }
    13.     }
    14.    
    15.     function Say(word:String):String { // OVERRIDES protected C# function
    16.         return "JavaScript says: "  + super.Say(word); // calls superclass        
    17.     }
    18. }
    Both classes are in the attach. Cheers! :p

    Tags: Unity3d Unity C# CSharp JavaScript override protected function import using include
     

    Attached Files:

  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    namespaces though are of no use as unity does not support them. you can talk to the classes directly and their name must be unique for the whole unity project.
     
  3. maglat

    maglat

    Joined:
    Jul 9, 2010
    Posts:
    111
    Very good work! Thats very handy for the futur :)
    Thank you!
     
  4. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    Dreamora, namespaces don't work only in class names of Unity scripts (which need to be attached to a game object). Every other way they work.

    Namespaces are very very usefull because two people can make two different classes with the same name. Also you got a better structure of your code (folder-like), which - in addition to a good programming IDE (talking about Visual Studio + ReSharper) - makes your work more professional.

    (btw UniSciTE intellisense doesn't display namespaces, but it has unusable intellisence already (just a list of ALL possible keywords in Unity))

    You can even extend MonoBehaviour, use your own namespace (see the code below), and then use something what I call a "namespace adapter", which adapts your class to something with no namespace, so it can be used as a script:

    Your class (with full-blown namespace usage, could be deep inside your .DLL):

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. namespace Com.DankoKozar.Unity.Gui.Core.Behaviours
    4. {
    5.     /// <summary>
    6.     /// MyMonoBehaviour inherits UnityEngine.MonoBehaviour
    7.     /// Cannot be attached to game object directly, because it is inside namespace
    8.     /// </summary>
    9.     public class MyMonoBehaviour : MonoBehaviour
    10.     {
    11.        
    12.     }
    13. }
    Namespace adapter:

    Code (csharp):
    1. public class MyMonoBehavour: Com.DankoKozar.Unity.Gui.Core.Behaviours.MyMonoBehavour // can be dragged to a game object
    2. {}
    This class ("MyMonoBehavour", no namespace) can then be dragged to a game object.

    Tags: Unity3d Unity C# CSharp JavaScript namespace
     
    Last edited: Oct 12, 2010
  5. Alex-Chouls

    Alex-Chouls

    Joined:
    Mar 24, 2009
    Posts:
    2,660
    Very cool! I'm curious about the adapter. Does the monobehaviour in the dll get initialized properly when the adapter is dragged to a game object? IOW, gameObject properly refers to its owner, it gets all monobehaviour events (Update, collision events etc.). It seems a little strange to have a MonoBehaviour that is never formally attached to a game object... I've been making wrapper classes that forward all that stuff to a regular class in the dll, but this sure would be easier...
     
  6. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    thats exactly the problem.
    If you drop the sources into unity exactly this part will NOT work.
    Class names and their script names must still be unique, independent on if you have a 10 level namespace overhead around them or not.
    at least thats how it used to be and I don't recall that it worked in the beta actually.
     
  7. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    True, scripts draged into stage got to have unique names. But, let's assume that you have to, say, use 2 DLLs in your project that have the same class name defined, like this:

    Code (csharp):
    1. namespace Foo {
    2.     class [B]HttpLoader[/B] : MonoBehaviour {
    3.     }
    4. }
    Code (csharp):
    1. namespace Bar {
    2.     class [B]HttpLoader[/B] : MonoBehaviour {
    3.     }
    4. }
    You can adapt them with adapters to remove namespaces:

    Code (csharp):
    1. class FooLoader : Foo.HttpLoader {}
    Code (csharp):
    1. class BarLoader : Bar.HttpLoader {}
    You can now attach those classes (scripts) to your game objects and they work.

    Note: Both class names are baked into DLLs that you have to use both in the project, and you have no way of manipulating the code inside :cool:
     
  8. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    Alex, the answer is "yes" to all your questions. I've been working this way more than a year now and it definitely works.

    My setup is:
    • I have a Visual Studio solution which hosts a few projects. Each project file is inside a folder with the same name.
    • One of those projects is named Unity, for convenience; inside there are standard VS project files + Unity project folders (Assets, Library and Temp).
    • The Assets folder is included into the project so scripts are being checked at compile-time. This way I know that scripts are OK straight from Visual Studio, before going into Unity.
    • The outputs of other projects in the solution (DLLs) are being copied into Unity/Assets/Libs folder with post build actions (see properties of VS project).
    • Core functionality that is re-used across projects is contained in DLLs. Only the stuff that is necessary to be in Unity/Assets project is there. Namely scripts (MonoBehaviours).
    • Inside the Visual Studio, the CTRL+SHIFT+B combination is what I use frequently :) This rebuilds the whole solution (compiling + post build copying).

    One side note: get ReSharper! It works great with VS + Unity setup. ;)
     
  9. Alex-Chouls

    Alex-Chouls

    Joined:
    Mar 24, 2009
    Posts:
    2,660
    Great setup - thanks for sharing!

    Do you have any tips for debugging DLL code with VS + Unity? I've been keeping a DLL/release version of the project and a non-DLL/debugging version and switching between the two, but this is kind of a pain...

    I'll definitely give ReSharper a try...

    Thanks again!
     
  10. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    Nope :( As everybody knows, no debugging (in a sense of breakpoints) is possible with Unity 2.6.1. But some people are trying using MonoDevelop with Unity. But only trying... for now - didn't see it working. The way I debug is using Debug.Log. :(

    btw if you have your code in DLL, you won't get line numbers logged where the exception occurs. Some people find it a good reason to do things in scripts/Unity VS project only.
     
  11. Alex-Chouls

    Alex-Chouls

    Joined:
    Mar 24, 2009
    Posts:
    2,660
    Oh well, figured... I'm actually using Unity 3, but not having a lot of luck with MonoDevelop debugging. Maybe because I'm writing editor classes... it just hangs when trying to launch Unity. Need to look into that more at some point.

    I tried the adapter method on EditorWindow classes that I'd like to put in a dll, and couldn't get it to work. I get the no such script error when calling GetWindow. Have you successfully used the adapter with EditorWindow classes?

    BTW, tryng out the trial version of ReSharper, and it is indeed great!
     
  12. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    Nope, with editor I've been using the script version only.
    And - yes - haven't tried this stuff with Unity 3 yet.
     
  13. dkozar

    dkozar

    Joined:
    Nov 30, 2009
    Posts:
    1,410
    After some testing, I found out interesting things regarding C# and Javascript in Unity 2.6.1:

    • There are no anonymous functions with JavaScript (function with no name) (with C# there are delegates for that purpose). Why is that important? Because you cannot code "handler inside handler inside handler..." Which is important for not loosing the caller's scope.
    • C# classes can be inside namespaces in Assets folder and C# recognizes them, but JavaScript doesn't (it works for both if classes inside namespaces are contained in another C# project (.DLL)
    • You cannot use type attributes with JavaScript (in Unity 3.0 it will be possible, using the ".<Type>" notation)
     
  14. cemC

    cemC

    Joined:
    Dec 23, 2010
    Posts:
    214
    Good work. And i want to ask specific question to you. if i have c,c++ or python scripts outside of the Unity3D , how can i speak c# script or javascript inside the Unity3D ? Any idea?
     
  15. fromium

    fromium

    Joined:
    Jun 7, 2013
    Posts:
    7
    I want to access the crossplatforminput stuff from a JS script. How do I include it so I can get the inputs?
     
  16. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    TaleOf4Gamers likes this.