Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Mono.CSharp.Evaluator

Discussion in 'Scripting' started by ufo, Aug 26, 2011.

  1. ufo

    ufo

    Joined:
    Aug 6, 2011
    Posts:
    13
    Hello,

    I need to parse some code during a dialog.

    working:
    Code (csharp):
    1. public class Data
    2. {
    3.      public static int n = 0;
    4.      public static GameObject go = null;
    5. }
    6.  
    7. Mono.CSharp.Evaluator.Init(new string[] {} );
    8. Assembly a = Assembly.GetExecutingAssembly();
    9. Mono.CSharp.Evaluator.ReferenceAssembly(a);
    10.  
    11. Mono.CSharp.Evaluator.Run("Data.n=Data.n+5;");
    12. Debug.Log(Data.n); //5
    not working:
    Code (csharp):
    1. Mono.CSharp.Evaluator.Run("using UnityEngine;");
    2. Debug.Log(Mono.CSharp.Evaluator.Run("Data.go=GameObject.FindGameObjectWithTag(\"Player\");")); //true
    3. Debug.Log(Data.go); //null
    4.  
    What's wrong with it?
     
  2. ufo

    ufo

    Joined:
    Aug 6, 2011
    Posts:
    13
    Code (csharp):
    1.  
    2. public class Data
    3. {
    4.      public static int n = 4;
    5.      public static GameObject go = null;
    6.    
    7.     public static void getGO(string str)
    8.         {
    9.         Data.go=GameObject.FindGameObjectWithTag(str);
    10.         }
    11. }
    12.  
    13. Debug.Log(Mono.CSharp.Evaluator.Run("Data.getGO(\"Player\");"));
    14. Debug.Log(Data.go);
    15.  
    Well, it seems that you have to prepare all functions. i wanted to avoid that. i don't understand how the evaluator works and why you can not access the classes. what i want to accomplish is simple one liners to have on array of answers

    ["answer1","answer2","answer3"];

    and one array of actions

    [
    "GameObject.Find(\"Door1\").getComponent<DoorScript>.open();",
    "GameObject.Find(\"Door2\").getComponent<DoorScript>.open();",
    "GameObject.Find(\"GUI\").getComponent<GUIScript>.sale.open();"
    ]

    I can live with that for the moment.
    You will need the .dll to make use of the evaluator.
     

    Attached Files:

  3. ufo

    ufo

    Joined:
    Aug 6, 2011
    Posts:
    13
    the c# evaluator is real pain and useless.

    I created a new JS File in the Plugins Folder.
    Plugins/Evil.js
    Code (csharp):
    1.  
    2. public static function uate (string:String):Object
    3.     {
    4.     eval(string);
    5.     }
    6.  
    in c#
    Evil.uate("GameObject.Find(\"Door1\").GetComponent(\"Door\").open();Debug.Log(\"do not do this!!!\");");

    that works like a charm
     
  4. japanitrat

    japanitrat

    Joined:
    Jul 7, 2011
    Posts:
    2
    Your C# example with the GameObject does actually work if you also reference the UnityEngine assembly. Here is an example for referencing all loaded assemblies:

    Code (csharp):
    1. Mono.CSharp.Evaluator.Init(new string[] {} );
    2. foreach(System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
    3.     Mono.CSharp.Evaluator.ReferenceAssembly(assembly);
     
  5. pakfront

    pakfront

    Joined:
    Oct 6, 2010
    Posts:
    551
    I realize I am necro-ing this thread, but I did get it working after some digging and figured it was worth sharing since this thread shows up high in search:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using Mono.CSharp;
    4. using System;
    5.  
    6. public class EvalManager : MonoBehaviour
    7. {
    8.     public static EvalManager instance;
    9.     string cmd = "typeof(GameObject);";
    10.    
    11.     void Awake ()
    12.     {
    13.         instance = this;
    14.     }
    15.    
    16.     void Start ()
    17.     {
    18.         int cnt = 0;
    19.         while (cnt < 2) {
    20.             // this needs to be run twice, as the references fail the first time through
    21.             foreach (System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
    22.                 if (assembly == null) {
    23.                     Debug.Log ("Null Assembly");
    24.                     continue;
    25.                 }
    26.                 Debug.Log (assembly);
    27.                 try {
    28.                     Mono.CSharp.Evaluator.ReferenceAssembly (assembly);
    29.                 } catch (NullReferenceException e) {
    30.                     Debug.Log ("Bad Assembly");
    31.                 }
    32.             }
    33.             Mono.CSharp.Evaluator.Evaluate ("1+2;");
    34.             cnt++;
    35.         }
    36.         Mono.CSharp.Evaluator.Run("using UnityEngine;");
    37.         Debug.Log (Mono.CSharp.Evaluator.GetUsing ());
    38.     }
    39.    
    40.     public object Run (string cmd)
    41.     {
    42.         //Run executes the code, and returns true if it was succesful and false if it did not parse
    43.         // for example GameObject.Find("MyGameObject").transform.Translate( new Vector3(0, 2, 0));
    44.         Debug.Log ("Run:"+cmd);
    45.         object result = Mono.CSharp.Evaluator.Run (cmd);
    46.         Debug.Log (result);
    47.         return result;
    48.     }
    49.    
    50.     public object Eval (string cmd)
    51.     {
    52.         // Evaluate requires a value as the last statement;
    53.         // So you can do "typeof(GameObject);", but not "var a = typeof(GameObject);"
    54.         Debug.Log ("Eval:"+cmd);
    55.         object result = Mono.CSharp.Evaluator.Evaluate (cmd);
    56.         Debug.Log ("Result:"+result);
    57.         return result;
    58.     }
    59.    
    60.     public int DrawGUI (int y)
    61.     {
    62.         cmd = GUI.TextField (new Rect (85, y, 400, 60), cmd);
    63.         if (GUI.Button (new Rect (10, y, 80, 20), "Eval:")) {
    64.             Eval (cmd);
    65.         }
    66.         if (GUI.Button (new Rect (10, y+20, 80, 20), "Run:")) {
    67.             Run (cmd);
    68.         }
    69.         y += 60;
    70.         return y;
    71.     }
    72.    
    73.     void OnGUI() {
    74.         int y = Screen.height - 60;
    75.         y = EvalManager.instance.DrawGUI(y);
    76.     }
    77. }
    78.  
     
    EZaca likes this.
  6. marcoantap

    marcoantap

    Joined:
    Sep 23, 2012
    Posts:
    215
    Any ideas on how to make this work in the WebPlayer? It throws a MethodAccessException.
     
  7. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    @pakfront, can you explain what steps are needed to make that code compile? I did discover that I need to go into Player Settings and change the API Compatibility Level to ".NET 2.0" to avoid an error on Mono.CSharp itself.

    But, even after doing that, I'm still getting this error:

    Other sources on the net seem to suggest that I need to somehow include the gmcs.exe in my project. But I don't know how to do that in Unity. Can anyone point me in the right direction?
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    This seems clever — but when I try it, I get this cryptic error:

    My google-fu is not strong enough to decipher this one. Any ideas what I'm doing wrong?
     
  9. tgouala-wellfiredLtd

    tgouala-wellfiredLtd

    Joined:
    Jun 8, 2013
    Posts:
    99
    Hi JoeStrout,

    I cannot explain to you why it cannot compile as my knowledge in Javascript are limited, but I can tell you that we had the same error on our side, and to fix it we removed all the '#pragma strict' in any other javascript files to allow the compilation to happen.
     
  10. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    That's really not a fix so much as "allowing bad things to happen"- you REALLY need to find an alternative. Also, this thread is really quite freakishly old.
     
    JoeStrout likes this.