Search Unity

[Released] Dynamic C# - Runtime C# Scripting

Discussion in 'Assets and Asset Store' started by scottyboy805, Feb 8, 2017.

  1. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    We have not tested on Android but I don't see any reason why it shouldn't work. We don't have an android device to test on but if you wanted to be a guinea pig and test for us then send us an email to info@trivialinteractive.co.uk and we may be able to work something out.
     
  2. bear56

    bear56

    Joined:
    Jan 23, 2018
    Posts:
    4
    I just purchased this plugin but got 6 errors when installing the compiler package in Unity 2017.3.(64 bits)

    Assets/DynamicCSharp/Scripts/Compiler/McsCompiler.cs(169,35): error CS0433: The imported type `Mono.CSharp.Target' is defined multiple times

    Assets/DynamicCSharp/Scripts/Compiler/McsDriver.cs(162,64): error CS0019: Operator `==' cannot be applied to operands of type `Mono.CSharp.Target' and `Mono.CSharp.Target'
    ...

    Any suggestion ?

    ------------------------------------------ update --------------------------------
    I install it in Unity 2017.2 (64 bits) everything is ok.
     
    Last edited: Jan 23, 2018
  3. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    I have managed to reproduce the error in 2017.3. It looks like Unity added a new type using the same name and namespace as a type in the mcs assembly included in our asset but I have found a workaround that fixes the issue.

    The update has been submitted to the asset store and should be live within the next day or so but if you want it straight away then just send us an email at info(at)trivialinteractive.co.uk including your invoice number.

    Thanks for reporting the issue. Let me know if you have any more problems.
     
  4. bear56

    bear56

    Joined:
    Jan 23, 2018
    Posts:
    4
    Thank you for your help. I'll try the update later.
     
  5. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    We had an email requesting the latest version but the email address given was unreachable so we could not send the update. If that was you then could you try contacting us directly at info(at)trivialinteractive.co.uk
     
  6. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.1.0 is now live and fixes the above issues in Unity 2017.3
     
  7. bear56

    bear56

    Joined:
    Jan 23, 2018
    Posts:
    4
    Hi scottyboy805
    I new a unity 2017.2 project and installed the compiler also switch to .NET 2.0.
    Then I new a script and apply to MainCamera, everytime I click the play button, I got this error :

    [CS246]: The type or namespace name `MonoBehaviour' could not be found. Are you missing an assembly reference? in <Unknown> at [1, 32]
    UnityEngine.Debug:LogError(Object)
    DynamicCSharp.Compiler.ScriptCompiler:printErrors() (at Assets/DynamicCSharp/Scripts/Compiler/ScriptCompiler.cs:131)
    DynamicCSharp.ScriptDomain:CompileAndLoadScriptSource(String) (at Assets/DynamicCSharp/Scripts/ScriptDomain.cs:296)

    my script is as the following :

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using DynamicCSharp;
    public class TestScript : MonoBehaviour
    {
    // Our script domain reference
    private ScriptDomain domain = null;
    public GameObject myGameObject;
    // The C# source code we will load
    private string source =
    "using UnityEngine;" +
    "class Test : MonoBehaviour" +
    "{" +
    " void SayHello()" +
    " {" +
    " Debug.Log(\"Hello World\");" +
    " }" +
    "}";
    void Start()
    {
    // Create the domain - We are using C# code so we need the compiler
    domain = ScriptDomain.CreateDomain("MyTestDomain", true);
    // Compile and load the source code
    ScriptType type = domain.CompileAndLoadScriptSource(source);
    if (type == null)
    Debug.Log("Type is null !");
    }
    }

    It always print out "Type is null !".
    Please help me to solve this error.
     
    Last edited: Feb 9, 2018
  8. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,

    As of 2017.2 Unity have changed the structure of their API by separating types out into separate modules. As a result, most types are no longer found inside the UnityEngine.dll assembly. To fix the problem you will need to add references to the modules you want to use in the Dynamic C# settings. The MonoBehaviour type has been moved into UnityEngine.CoreModule.dll so if you go to 'Tools/Dynamic C#/Settings' and add that to the assembly references then you should be able to access it.

    Another customer had the same issue previously and you can read the report here and the solution here.
     
  9. bear56

    bear56

    Joined:
    Jan 23, 2018
    Posts:
    4
    It works ! Thanks for your reply.
     
  10. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    181
    Hi, I am looking for a way to parse a string to c#. Specifically for math equations. Would this be possible using your asset?
     
  11. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    yes Dynamic C# can compile and run any C# math expressions if that is what you meant. You can also use the recently added ScriptEvaluator which is capable of taking an input string like below and accessing the result via code:

    Code (CSharp):
    1. ScriptEvaluator scriptEval = new ScriptEvaluator();
    2.  
    3. Debug.Log(scriptEval.Eval("return 6 + (2 * 8) / 4;"));
     
  12. tcmeric

    tcmeric

    Joined:
    Dec 21, 2016
    Posts:
    181
    Thanks. Looks like the script evaluator is what I am looking for :D . I will give it a try.
     
    scottyboy805 likes this.
  13. TheGabelle

    TheGabelle

    Joined:
    Aug 23, 2013
    Posts:
    94
    Can I specify which namespaces are available explicitly instead of creating a list of restrictions?
    Would it be safe to create 'class' scaffolding into which I concatenate variables and methods text imported from a file?
    concept:
    Code (CSharp):
    1. string classScaffoldingTop =
    2. "using UnityEngine" +
    3. "using Other.Namespace" +
    4. "public class " + nameOfFile + "{"
    5.  
    6. string textFromFile =
    7. "int baseNumber = 5;" +
    8. "void test(SomeClass obj){" +
    9. "    obj.someProperty += baseNumber;"+
    10. "}"
    11.  
    12. string classScaffoldingBottom = "}";
    13.  
    14. string fullClassCode = classScaffoldingTop + textFromFile + classScaffoldingBottom;
     
  14. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    There is no built in way to specify namespaces which are allowed to be used. You are only able to create restrictions. If you need to modify the restrictions via code though you are able to do that using the following code which will modify the Dynamic CSharp global settings:

    Code (CSharp):
    1. DynamicCSharp.Settings.namespaceRestrictions = new NamespaceRestriction[]
    2. {
    3.     new NamespaceRestriction("System.IO"),
    4. };
    A scaffolding class is perfectly fine to use and will work fine. In fact the 'ScriptEvaluator' uses this same approach to execute method body code without any class or method setup code. it might be worth taking a look at the class and the accompanying template file at 'Assets/DynamicCSharp/Resources/DynamicCSharp_EvalTemplate.txt" to see how it works.
     
  15. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.1.1 has been submitted to the asset store for review. This version includes:
    • Support for async compiling
    • Dropped support for older Unity versions. Current supported versions are 5.3.5 to current.
    • Minor bug fixes
    The async compiling allows you to compile source code on a background thread allowing you to do other tasks on the main thread in the meantime. We have tried to make it as similar to Unity as possible so it is intuitive and familiar to use. here is a basic example:

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using DynamicCSharp;
    4.  
    5. class Example : MonoBehaviour
    6. {
    7.     IEnumerator WaitForCompile()
    8.     {
    9.         // Create a domain as usual
    10.         ScriptDomain domain = ScriptDomain.CreateDomain("example", true);
    11.  
    12.         // Issue an async compile request
    13.         AsyncCompileLoadOperation task = domain.CompileFilesAsync("C:/Source/Program.cs");
    14.  
    15.         // Wait for the compile to finish
    16.         yield return task;
    17.  
    18.         if(task.IsSuccessful == true)
    19.         {
    20.             Debug.Log("Compile successful:" + task.MainType);
    21.         }
    22.         else
    23.         {
    24.             Debug.LogError("There were compiler errors:");
    25.  
    26.             foreach(string error in task.Errors)
    27.                 Debug.LogError(error);
    28.         }
    29.     }
    30. }
    Also if anyone has any features they would like to see added then please do let us know otherwise it will likely be just bug fixes from now on. We have experimented with some things such as webgl support but after much testing we were unsuccessful but we are keen to hear any other requests.
     
  16. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Version 1.1.2 has been submitted to the asset store for review. This is just a small update that fixes an issue with assembly referencing. Unity versions 2017.2 and newer now use assembly modules instead of the single 'UnityEngine.dll' and Dynamic C# will now automatically reference a handful of these modules if you are using a newer Unity version (Modules can also be added or removed via the settings menu).
     
  17. Coredumping

    Coredumping

    Joined:
    Dec 17, 2014
    Posts:
    42
    Great asset! Currently working on integrating it into my game and just wanted to give you heads up on some issues I ran into:
    *Referencing a class that in any way reference other sub-classes of generic types will break the compiler, and the resulting exception is in no way helpful, since the original exception is thrown away by Mono.
    *Because all assembles are named Dynamic_# and I was caching them for faster loading, the names would collide and end up loading the same assembly twice.
    *Since the security check isn't set to throw an exception when you load assembly data, it will load the assembly regardless of any security issues raised.

    And personally I would've liked if errors were returned by the API, instead of just being output directly to the Unity console.
     
  18. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Thanks very much for your feedback.
    • We are not aware of this issue but we will look into it. It sounds like a compiler bug though so it may be out of our hands.
    • I'm not sure I understand this. Each compiled assembly should have a unique name usually with a number on the end to ensure that it is unique. Are you saying that each assembly that is compiled ends up with the same name?
    • This is expected behavior of the byte array load method however I understand the problem is that compiled scripts are loaded using this method which results in avoiding the security measures. We will make the necessary changes for the compiler to write the compiled assembly to file where it can be loaded by one of the security protected load methods.
    You can access the error and warning messages generated by the compiler via a script domain reference as shown below. The console messages will always be printed though but we can look into adding an option to disable console messages if they are not desirable.

    Code (CSharp):
    1. ScriptDomain domain = ScriptDomain.CreateDomain("ExampleDomain", true);
    2.  
    3. foreach(string error in domain.CompilerService.Errors)
    4.     Debug.LogError(error);
    5.  
    6. foreach(string warning in domain.CompilerService.Warnings)
    7.     Debug.LogWarning(warning)
     
    Marcos-Elias likes this.
  19. Coredumping

    Coredumping

    Joined:
    Dec 17, 2014
    Posts:
    42
    Yes, it is definitely a compiler issue. Just thought I'd give you a heads up, if anyone else asks why they are thrown an error when loading a type reference. It was an easy fix on my end.

    The name counter resets when the application is restarted, so if you compile a binary and then compile a new one on a second run, and then load both on a third, they will both be dynamic_1, and thus the second load will be ignored. I just added an output assembly name parameter to the compiler class to fix it.

    The third issue was an easy fix as well. When you load an assembly, you just need to set the throwOnError parameter to true, instead of leaving it on false, so the method exits before loading the assembly. Otherwise the assembly might start executing unsafe code on load.

    I also made the changes necessary to handle the errors myself, just thought you might want to add that as an option.
     
  20. Player7

    Player7

    Joined:
    Oct 21, 2015
    Posts:
    1,390
  21. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    It depends what you mean by compatible. At the moment our asset can run under .Net 4 just fine but any scripts you intend to compile and load will need to use the .net 3.5 framework or lower. Note that the documentation mentions that .net 2.0 is required but the actual requirement is that a .Net subset is not used.
     
  22. Player7

    Player7

    Joined:
    Oct 21, 2015
    Posts:
    1,390
    hmm I guess the current package is just not really setup for those who switched to Net 4 ... either way messing about with the .net version and going backforth with it, I've managed to get it so it is actually working without compiler errors being thrown.. so .Net4.x Equiv with api compatibility Net4.x .. is possible, I'm fine with only using 3.5 framework supported features in the runtime compiled scripts.

    Should fix the installer so that it can work with the newer net stuff, not sure 3.5 will be default .net version selected in Unity 2018.3 going forwards anyway.
     
  23. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Were you getting compiler errors setting this up then because we would be interested to know if you were so that we could fix them. We have tested under .net 4 on a couple of Unity versions including the 2018.3 beta and did not see any errors. The installer also worked correctly in our testing despite only mentioning .net 2.0 however we will update it to take .net 4 into account so there is less confusion in the future.
     
  24. Player7

    Player7

    Joined:
    Oct 21, 2015
    Posts:
    1,390
    I was getting errors.. don't recall them now as it's been fixed and I never copied them down, but it wasn't a simple setup that just worked for 2018.2f17 which what I was using when importing, while api was at 4.0x

    Also yeah is few depreciated warnings coming through on this asset with newer unity releases.. like

    Assets/DynamicCSharp/Scripts/Editor/AutomaticInstaller.cs(133,36): warning CS0618: `UnityEditor.PlayerSettings.apiCompatibilityLevel' is obsolete: `apiCompatibilityLevel is deprecated. Use PlayerSettings.GetApiCompatibilityLevel()/PlayerSettings.SetApiCompatibilityLevel() instead.'

    etc would be good to see them fixed on the asset
     
  25. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    OK thanks for letting me know. I will have to do some testing on that version to see if I can get any errors to show up. Did you let the Unity API updater run once the asset was imported? We have updated the auto installer to work with 4.6 now and will be submitting the update to the asset store soon so that should address the obsolete warnings.
     
  26. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Dynamic C# 1.1.3 is now available on the asset store. As above this version includes changes to the auto-installer to support .Net 4.6. Note that scripts you compile at runtime will still be limited to .Net 3.5 but this update means that you are able to use Dynamic C# in games that use 4.x
     
  27. Farox

    Farox

    Joined:
    Oct 12, 2014
    Posts:
    16
    Having problems with includes.

    I have unity 2018.3, blank project and whatever example I use it can't access the unity types (GameObject, Primitives, Debug etc.) So even the samples fail for me. Scripting Runtime is 4.x equiv, Api Compat Level is 4.x.

    Any ideas?

    As an example your LoadScriptExample outputs

    [CS103]: The name `Debug' does not exist in the current context in <Unknown> at [1, 68]
    UnityEngine.Debug:LogError(Object)
    DynamicCSharp.Compiler.ScriptCompiler:printErrors() (at Assets/DynamicCSharp/Scripts/Compiler/ScriptCompiler.cs:141)
    DynamicCSharp.ScriptDomain:CompileAndLoadScriptSource(String) (at Assets/DynamicCSharp/Scripts/ScriptDomain.cs:296)
    DynamicCSharp.Demo.LoadScriptExample:Start() (at Assets/DynamicCSharp/Demo/ExampleScripts/LoadScriptExample.cs:35)

    etc.
     
  28. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    It looks like you do not have the necessary assembly references added to the settings. You will need to go to the menu 'Tools -> Dynamic C# -> Settings' and locate the section called 'Assembly References'. You will need to add the reference 'UnityEngine.CoreModule.dll' to this list box using the '+' button in order to access the Debug class. There are also a number of other engine modules that you may need to add references for in order to access other parts of the engine such as physics. I am not aware of any official documentation that lists all of these modules but if you look in the folder at '<unity_install_path>\Editor\Data\Managed\UnityEngine\' you should see most of these module assemblies.

    I hope this helps you. Let me know if you have any further issues.
     
  29. Farox

    Farox

    Joined:
    Oct 12, 2014
    Posts:
    16
    I'll try, thanks! Also for the quick reply

    Edit: That did it. Thanks!
     
    Last edited: Dec 23, 2018
  30. shaneharris

    shaneharris

    Joined:
    Dec 17, 2016
    Posts:
    1
    Hi,

    So I'm trying the asset on Android, I saw further up the thread you were encouraging someone to give it a try. I also notice the documentation says you only support windows/mac/linux so i'm hoping you have some quick and simple insight on what seems to me to be a permissions error:

    Code (CSharp):
    1. 2019-03-02 19:12:48.047 24000-24015/? E/Unity: [CS16]: Could not write to file `DynamicAssembly_0', cause: Access to the path "/DynamicAssembly_0.dll" is denied.
    2.  
    3.    (Filename: ./Runtime/Export/Debug.bindings.h Line: 43)
    4. 2019-03-02 19:12:48.048 24000-24015/? E/Unity: [CS]: Mono.CSharp.FatalException: Could not write to file `DynamicAssembly_0', cause: Access to the path "/DynamicAssembly_0.dll" is denied.
    5.       at Mono.CSharp.Report.Error (System.Int32 code, Mono.CSharp.Location loc, System.String error) [0x0007b] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    6.       at Mono.CSharp.Report.Error (System.Int32 code, System.String error) [0x00000] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    7.       at Mono.CSharp.AssemblyDefinition.Save () [0x000d7] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    8.       at DynamicCSharp.Compiler.McsDriver.Compile (System.Reflection.Emit.AssemblyBuilder& assembly, System.AppDomain domain, System.Boolean generateInMemory) [0x002c2] in <cc81496e64a442f1895dd2d54c15c588>:0
    9.       at DynamicCSharp.Compiler.McsCompiler.CompileFromSettings (Mono.CSharp.CompilerSettings settings, System.Boolean generateInMemory) [0x0002c] in <cc81496e64a442f1895dd2d54c15c588>:0  in  at [0, 0]
    10.  
    11.     (Filename: ./Runtime/Export/Debug.bindings.h Line: 43)
    12. 2019-03-02 19:12:48.088 24000-24015/? E/Unity: NullReferenceException: Object reference not set to an instance of an object
    13.       at DynamicCSharp.Demo.LoadScriptExample.Start () [0x00025] in <cc81496e64a442f1895dd2d54c15c588>:0
    14.  
    15.     (Filename: <cc81496e64a442f1895dd2d54c15c588> Line: 0)
    Is there a way to specify a path maybe? Using Application.persistentDataPath instead?

    I notice the DynamicCSharp.Compiler.McsDriver.Compile method has a generateInMemory flag, could that be utilised?

    Edit: Unity 2018.2.20
    Android: Oculus Go

    Edit2: i just noticed you said i should reach out to you at info@trivialinteractive.co.uk, let me know if you want me to do that.

    Edit3: I was able to resolve this issue by adding the following to McsCompiler.cs on line 26
    Code (CSharp):
    1. public static string OutputFilePath = "";
    and changed the following in McsMarshal.cs on line 87
    Code (CSharp):
    1. assemblyData = File.ReadAllBytes(name);
    2. // To this
    3. assemblyData = File.ReadAllBytes(McsCompiler.OutputFilePath+name);
    Then in the LoadScriptExample just before the CompileAndLoadScriptSource call i was able to add
    Code (CSharp):
    1.  McsCompiler.OutputFilePath = Application.persistentDataPath+"/";
    There is probably a more elegant way to achieve this but ill leave that up to you!
    Once those changes were in place I was then able to compile runtime scripts on android.
     
    Last edited: Mar 3, 2019
    JBR-games and scottyboy805 like this.
  31. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Sorry for the delay.
    I was going to suggest that you modify the source code to change the path but you beat me to it. We do intend to make this path modifiable at some point but we have a lot of work to do for some of our other assets at the moment so I cannot say when it will be added.
     
    shaneharris likes this.
  32. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Dynamic C# version 1.1.4 has been submitted to the asset store for review and should be available for download within a couple of days. This version includes:

    • C# code compiled from file will now include the filename and line numbers in any compiler errors that are generated. This should make it much easier to find any syntax errors in the code.
    • Added a new hidden parameter to the settings window called 'compilerWorkingDirectory'. You can assign a directory path to this parameter and the compiler will then use the directory for IO operations. You should make sure that the directory has IO access to avoid compiler issues. This parameter can only be accessed from code via 'DynamicCSharp.Settings.compilerWorkingDirectory'.
    • Added a new parameter to the settings window called 'debugMode'. When enabled the compiler will generate an assembly with debug information including .mdb symbols and disable code optimizations. At the moment the generated .mdb symbols will be loaded automatically by Dynamic C# if they exist however they do not yet provide any useful debug information in runtime exceptions caused by compiled code. We are looking into this further to hopefully get it working in the near future.
     
  33. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Dynamic C# version 1.1.5 has been submitted to the asset store for review. This version includes minor bug fixes and addresses some import problems in Unity 2018.3 and later.
     
    Whitebrim and TheGabelle like this.
  34. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    FeatureTrimmed.png

    We have now released a new asset which may be of interest if you have purchased Dynamic C#. InGame Code Editor is and advanced text input field with line numbering and full syntax highlighting for C# and many other languages as well as many more features. Check out the asset store or forum page.
     
    JBR-games likes this.
  35. JBR-games

    JBR-games

    Joined:
    Sep 26, 2012
    Posts:
    560
    Is this an add-on for dynamic c# ?
    Its a run time (in game code editor)?
     
  36. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    No it’s not an add-on specifically it is just a separate asset that we created and thought that Dynamic C# users may find it useful. Yes it’s a runtime code editor for use in game.
     
    JBR-games likes this.
  37. unormal

    unormal

    Joined:
    Jan 10, 2012
    Posts:
    29
    God a weird one; I was using aeroson's compiler directly when I ran into this, and moved to Dynamic C# to see if it was something dumb I was doing, but I seem to run into the same issue.

    On at least Unity 2018.3 and 2019.1 (this seems to work on 2019.3, and I haven't yet tested 2019.2), the code snipped below fails to build with an internal compiler error. It seems to choke when compiling any use of a Dictionary iterator, but this is the simplest code reproduction of the failure.

    Any thoughts?

    Code (CSharp):
    1. using UnityEngine;
    2. using DynamicCSharp;
    3. public class CompileTest : MonoBehaviour
    4. {
    5.     const string testSource = @"using System;
    6. using System.Collections.Generic;
    7. namespace Test
    8. {
    9.    public class ThisDoesntCompile
    10.    {
    11.        public static void getenumeratortest()
    12.        {
    13.            var t = new Dictionary<string,string>();
    14.            var test = t.Keys.GetEnumerator();
    15.        }
    16.    }
    17. }";
    18.     // Start is called before the first frame update
    19.     void Start()
    20.     {
    21.      
    22.     }
    23.     // Update is called once per frame
    24.     void Update()
    25.     {
    26.         Debug.Log("testing compilation...");
    27.         var modDomain = ScriptDomain.CreateDomain("ModMain", true);
    28.         var result = modDomain.CompileAndLoadScriptSource(testSource);
    29.         Debug.Log("Compiled...");
    30.     }
    31. }
    e: bonus bug, the same code in 2019.2.b2 produces the following error:

    Code (CSharp):
    1. testing compilation...
    2. UnityEngine.Debug:Log(Object)
    3. CompileTest:Update() (at Assets/CompileTest.cs:26)
    4.  
    5. [CS6]: Metadata file `UnityEngine.UI.dll' could not be found
    6. UnityEngine.Debug:LogError(Object)
    7. DynamicCSharp.Compiler.ScriptCompiler:PrintErrors() (at Assets/DynamicCSharp/Scripts/Compiler/ScriptCompiler.cs:166)
    8. DynamicCSharp.ScriptDomain:CompileAndLoadScriptSource(String) (at Assets/DynamicCSharp/Scripts/ScriptDomain.cs:331)
    9. CompileTest:Update() (at Assets/CompileTest.cs:28)
    10.  
    11.  
    12. [CS]: Mono.CSharp.FatalException: Metadata file `UnityEngine.UI.dll' could not be found
    13.   at Mono.CSharp.Report.Error (System.Int32 code, Mono.CSharp.Location loc, System.String error) [0x0007b] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    14.   at Mono.CSharp.Report.Error (System.Int32 code, Mono.CSharp.Location loc, System.String format, System.String arg) [0x0000b] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    15.   at Mono.CSharp.Report.Error (System.Int32 code, System.String format, System.String arg) [0x00000] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    16.   at Mono.CSharp.AssemblyReferencesLoader`1[T].Error_FileNotFound (System.String fileName) [0x0000b] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    17.   at Mono.CSharp.DynamicLoader.LoadAssemblyFile (System.String assembly, System.Boolean isImplicitReference) [0x000d6] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    18.   at Mono.CSharp.AssemblyReferencesLoader`1[T].LoadReferencesCore (Mono.CSharp.ModuleContainer module, T& corlib_assembly, System.Collections.Generic.List`1[Mono.CSharp.Tuple`2[Mono.CSharp.RootNamespace,T]]& loaded) [0x00065] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    19.   at Mono.CSharp.DynamicLoader.LoadReferences (Mono.CSharp.ModuleContainer module) [0x00000] in <a1c1f79be49c4b2f906d07ecc2ddc791>:0
    20.   at DynamicCSharp.Compiler.McsDriver.Compile (System.Reflection.Emit.AssemblyBuilder& assembly, System.AppDomain domain, System.Boolean generateInMemory) [0x001a2] in G:\Workspace\DynCSharp2019.2\Assets\DynamicCSharp\Scripts\Compiler\McsDriver.cs:216
    21.   at DynamicCSharp.Compiler.McsCompiler.CompileFromSettings (Mono.CSharp.CompilerSettings settings, System.Boolean generateInMemory) [0x00026] in G:\Workspace\DynCSharp2019.2\Assets\DynamicCSharp\Scripts\Compiler\McsCompiler.cs:164  in  at [0, 0]
    22. UnityEngine.Debug:LogError(Object)
    23. DynamicCSharp.Compiler.ScriptCompiler:PrintErrors() (at Assets/DynamicCSharp/Scripts/Compiler/ScriptCompiler.cs:166)
    24. DynamicCSharp.ScriptDomain:CompileAndLoadScriptSource(String) (at Assets/DynamicCSharp/Scripts/ScriptDomain.cs:331)
    25. CompileTest:Update() (at Assets/CompileTest.cs:28)
    26.  
    27. Compiled...
    28. UnityEngine.Debug:Log(Object)
    29. CompileTest:Update() (at Assets/CompileTest.cs:29)
     
    Last edited: May 21, 2019
  38. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    I have had a quick look at this. I was able to replicate the error using the code you provided and it appears to be a compiler bug. It looks like the compiler cannot infer the return type of 'GetEnumerator' for some reason because explicitly declaring the return variable causes the error to go away:

    Code (CSharp):
    1. IEnumerator<string> test = t.Keys.GetEnumerator()
    I will look into this a bit more when I have chance but if it is a compiler issue then I don't know if we will be able to do anything about it.

    As for the second error you mention: You may need to go to 'Tools -> Dynamic C# -> Settings' and remove the 'UnityEngine.UI.dll' reference and replace it with 'UnityEngine.UIModule.dll' as Unity have shuffled around their assemblies a bit.
     
  39. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    scottyboy805
    Hello, this asset is great! Thanks you very much for it.

    I have a question:
    I may specify a "black list" of restricted name spaces or types.
    But can I specify a "white list" of allowed types and methods?

    I will clarify. I am developing a game with "in-game programming" feature. Users should be able to write a code which will control various devices. But possibilities of users should be very restricted. User should be able only edit some inputs and read some outputs (like in games Garry's Mod, Space Engineers, From the Depths etc)

    User should not be able to access code of the game core. Of course I may just search a specific text in the text of the code, but "black list" will be huge and not always possible.

    For example I have the next code for rocket engine:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Engine : MonoBehaviour {
    4.  
    5.  
    6.     public float ThrustLevel;
    7.     // User should NOT be able to change this
    8.     public float MaxForce;
    9.     Rigidbody rigidbody;
    10.  
    11.  
    12.     void FixedUpdate () {
    13.         rigidbody.AddRelativeForce (Vector3.forward * MaxForce * ThrustLevel);
    14.     }
    15.  
    16.  
    17.     // User should be able to call this
    18.     public void SetThrustLevel (float NewValue) {
    19.         ThrustLevel = NewValue;
    20.     }
    21.  
    22.  
    23.     // User should NOT be able to call this
    24.     public void SomeAnotherFunction () {
    25.         // Some actions
    26.     }
    27. }
    28.  
    User should be able to call SetThrustLevel () and nothing else.
    Such code is not allowed:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Example : MonoBehaviour {
    4.  
    5.  
    6.     public Engine Engine1;
    7.  
    8.  
    9.     void Start () {
    10.         // I am a cheater now!
    11.         Engine1.MaxForce = 999999f;
    12.         Engine1.SomeAnotherFunction ();
    13.     }
    14. }

    "White list" should solve it.
    Is there a way to solve it somehow? Or maybe you may suggest a better way to solve it?
    Maybe I need to edit a source code somehow? For example your compiler may check a code and detect "I see you are trying to invoke SomeAnotherFunction of Engine, but only SetThrustLevel allowed, so throw error"?
     
    Last edited: Jun 8, 2019
  40. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    Seems like I found a solution.
    Interfaces.
    I noticed that in Space Engineers every component type have "I" symbol at the start, like interfaces.

    And this have a sense. I just created:
    Code (CSharp):
    1. public interface IEngine {
    2.  
    3.  
    4.     float thrustLevel {
    5.         get;
    6.     }
    7.  
    8.  
    9.     void SetThrustLevel (float NewValue);
    10. }
    And user now should access only "IEngine", while "Engine" should be restricted type.
    Now I need just a white list of allowed types.

    Seems like I found a solution for that too.
    I found a code:
    Code (CSharp):
    1. public override bool Verify(ModuleDefinition module)
    In NamespaceRestriction.cs
    where I may check each type via
    Code (CSharp):
    1. foreach(TypeReference reference in references)
    and stop the code if type not in the my white list

    But I am not sure that it is a proper solution, so please correct me if you have some better idea.
     
  41. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    Yes interfaces would be the best way to do this.
    Unfortunately Dynamic C# does not support whitelists but if you are able to modify the code to suit your needs then there i no harm in doing that. Our new asset Roslyn C# does support whitelists as it has a completely rewritten code security system which can provide better error messages so that may be worth taking a look at.
     
    Artaani likes this.
  42. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    Amazing, thank you! : )
     
  43. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    Another question.
    How can I get all fields of compiled script?
    I need it to create some kind of "in-game Unity inspector" for scripts which compiled by player.

    I tried to use Reflection but it does not works.

    Here is an example:

    Code (CSharp):
    1.  
    2.         scriptDomain = ScriptDomain.CreateDomain ("MyDomain", true);
    3.         ScriptType  scriptType  = scriptDomain.CompileAndLoadScriptSource (CodeToCompile);
    4.         ScriptProxy scriptProxy = scriptType.CreateInstance (gameObject);
    5.  
    6.         FieldInfo[] fields = scriptType.RawType.GetFields ();
    7.         Debug.Log ("Fields: " + fields.Length);
    8.  
    I always have "Fields: 0" in the console, even if I have a few float variables in the "CodeToCompile"

    For others scripts which are created in the Unity editor the same method works, so I suppose it just does not works for scripts which compiled at runtime.

    Any ideas?
     
  44. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi,
    Reflection works just fine with compiled code. You may need to specify some binding flags when calling 'GetFields' if the fields are not declared as public. Here's a quick example:

    Code (CSharp):
    1. type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    Hopefully that should fix the problem.
     
    Artaani likes this.
  45. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    The field is public. Weird, it still does not works even with these binding flags.

    Can you please check that on your computer?
    I created an example for quick test.
    Move this code to your project and attach it to empty object.

    Code (CSharp):
    1. using UnityEngine;
    2. using DynamicCSharp;
    3. using System.Reflection;
    4.  
    5. public class DynamicCSharpReflectionTester : MonoBehaviour {
    6.  
    7.  
    8.     ScriptDomain scriptDomain;
    9.  
    10.     [TextArea (2, 30)]
    11.     public string CodeToCompile;
    12.  
    13.  
    14.     void Start () {
    15.  
    16.         scriptDomain = ScriptDomain.CreateDomain ("MyDomain", true);
    17.  
    18.         ScriptType  scriptType  = scriptDomain.CompileAndLoadScriptSource (CodeToCompile);
    19.         ScriptProxy scriptProxy = scriptType.CreateInstance (gameObject);
    20.  
    21.  
    22.         // Debug fields
    23.         FieldInfo[] fields = scriptType.GetType ().GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    24.         Debug.Log ("Amount of fields: " + fields.Length);
    25.  
    26.         foreach (FieldInfo each in fields) {
    27.             Debug.Log (each.Name + " " + each.FieldType);
    28.         }
    29.     }
    30. }
    31.  
    After that, in inspector set in "CodeToCompile" the next code:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class UserCodeExample1 : MonoBehaviour {
    4.  
    5.  
    6.     public int TestIntVariable;
    7.     public float TestFloatVaraible;
    8.    
    9.  
    10.     void Update () {
    11.  
    12.     }
    13. }
    After the start, a console should show:
    TestIntVariable int
    TestFloatVaraible float

    But it shows only 5 some weird elements, not these two fields.
    Do you have the same issue on your computer?
     
  46. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Hi again,
    I notice that you are calling 'GetType' on a 'ScriptType' object but this will return the incorrect type. Instead you will need to use the property 'ScriptType.RawType' which will provide access to the compiled type. After changing the following line from:

    Code (CSharp):
    1. FieldInfo[] fields = scriptType.GetType ().GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    To:

    Code (CSharp):
    1. FieldInfo[] fields = scriptType.RawType.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    Your example code will then work as expected and display 2 fields in the console
     
    Artaani likes this.
  47. Artaani

    Artaani

    Joined:
    Aug 5, 2012
    Posts:
    405
    Oops, didn't noticed that.
    Now everything is works! Amazing! C# in-game programming feature almost done! Thanks you very much for this asset and your help! : )
     
  48. scottyboy805

    scottyboy805

    Joined:
    Apr 10, 2013
    Posts:
    503
    Glad to hear its all working now. Let me know if you need anything else.
     
    Artaani likes this.