- Home /
Is it possible to compile and run C# code on-the-fly on mobile?
Hi, all:
What I want to do here is to make a console in game, which is common in games with some script language like Lua.
And, as Unity uses C#, I think it might not be necessary to employ another script language, and also it could save some CSharp-Lua binding work.
After some experiments with CodeDomProvider, I could run up the console in PC setting, but I cannot figure out how to make it run on Android.
From the DDMS, I get this error log:
08-28 22:32:53.490: I/Unity(29077): SystemException: Error running gmcs: Cannot find the specified file
08-28 22:32:53.490: I/Unity(29077): at Mono.CSharp.CSharpCodeCompiler.CompileFromFileBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) [0x00000] in <filename unknown>:0
08-28 22:32:53.490: I/Unity(29077): at Mono.CSharp.CSharpCodeCompiler.CompileFromSourceBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] sources) [0x00000] in <filename unknown>:0
08-28 22:32:53.490: I/Unity(29077): at Mono.CSharp.CSharpCodeCompiler.CompileAssemblyFromSourceBatch (System.CodeDom.Compiler.CompilerParameters options, System.String[] sources) [0x00000] in <filename unknown>:0
08-28 22:32:53.490: I/Unity(29077): at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource (System.CodeDom.Compiler.CompilerParameters options, System.String[] fileNames) [0x00000] in <filename unknown>:0
08-28 22:32:53.490: I/Unity(29077): at InputScript._CompileCode (System.String code) [0x00000] in <filename unknown>:0
08-28 22:32:53.490: I/Unity(29077): at InputScript.OnGUI () [0x00000] in <filename unknown>:0
It looks like the compiler gmcs is not around on Android Mono Runtime(?)
So, does that mean Mono cannot compile C# code on-the-fly on mobile? And I still have to use Lua as the script?
Okay, it seems that $$anonymous$$ono.CSharp.Evaluator can run some C# code at runtime on mobile. I will try it further.
http://forum.unity3d.com/threads/102162-$$anonymous$$ono.CSharp.Evaluator http://blog.huazhihao.com/post/28611553484/scripting-c-with-mono
Answer by TMPxyz · May 25, 2013 at 11:08 AM
Some weird issues arise after switching from unity3.5 to unity4.1.3. With some trial & errors, finally I found a workaround, just skip referencing Mono.Cecil & UnityEditor, and it will be okay.
I post my code(modified) below in case someone is interested.
using UnityEngine;
using System.Collections;
using System;
using Mono.CSharp;
public class CmdConsole : MonoBehaviour/*Singleton<CmdConsole>*/
{
public KeyCode[] m_ShortcutKeys = new KeyCode[]{KeyCode.LeftAlt, KeyCode.F12}; //the keys used to open Console;
public bool m_IsConsoleOpen = false;
private string m_editstr = "";
private string m_result = "";
private int m_cmdId = 0; //used to identify cmd
// Use this for initialization
void Start () {
Mono.CSharp.Evaluator.Init(new string[] { });
foreach (System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
//Dbg.Log("refer: {0}", assembly.FullName);
if( assembly.FullName.Contains("Cecil") || assembly.FullName.Contains("UnityEditor") )
continue;
Mono.CSharp.Evaluator.ReferenceAssembly(assembly);
}
Evaluator.Run ("using UnityEngine;\n" +
"using System;"
);
}
void Update() {
//check if the console should be opened
if (m_IsConsoleOpen)
return;
bool bAllKeysDown = true;
foreach ( KeyCode kc in m_ShortcutKeys )
{
if( !Input.GetKey(kc) )
{
bAllKeysDown = false;
break;
}
}
if( bAllKeysDown )
{
m_IsConsoleOpen = true;
}
}
void OnGUI()
{
if (!m_IsConsoleOpen)
return;
m_editstr = GUI.TextArea(new Rect(10, 10, 400, 100), m_editstr);
if( GUI.Button(new Rect(420, 60, 100, 40), "Execute") )
{
++m_cmdId;
bool bSuccess = Run(m_editstr);
m_result = string.Format("{0}: {1}", m_cmdId, bSuccess ? "OK" : "Fail");
m_editstr = ""; //clear the script
}
if( GUI.Button(new Rect(530, 60, 100, 40), "Close") )
{
m_IsConsoleOpen = false;
}
if (m_result.Length > 0)
{
GUI.TextArea(new Rect(420, 10, 200, 30), m_result);
}
}
public bool Run(string cmd) {
return Evaluator.Run(cmd);
}
}
$$anonymous$$ono.CSharp won't work on iOS due to AOT; So, I guess, sometimes we still need to turn to old good Lua;
Absolutely, wickedly awesome. One tip for Unity3D 4 ...
If you get the error: Assets/_Core/Ev$$anonymous$$gr/DynaCompile.cs(5,12): error CS0234: The type or namespace name CSharp' does not exist in the namespace
$$anonymous$$ono'. Are you missing an assembly reference?
You can fix it by...
finding a copy of $$anonymous$$ono.CSharp.dll on your machine and drop it into your Assets folder somewhere. (I put $$anonymous$$e in "~\Assets\DLLs")
I found a nice copy of the dll here: C:\Program Files (x86)\Unity42\Editor\Data\$$anonymous$$onoBleedingEdge\lib\mono\2.0\$$anonymous$$ono.CSharp.dll
And yes, I am busted. I renamed the class to be called "DynaCompile" as I move toward dynamically replacing running instances with freshly compiled ones. Now if only I could get Unity to keep its "compile everything" policy to chill out for the purposes of one file temporarily. Hmmmmmmm.
Edit and continue anyone? This may take some work.
Thanks for the head start, T$$anonymous$$Pxyz.
-$$anonymous$$en =]