Search Unity

C# 6.0

Discussion in 'Scripting' started by Deleted User, Mar 27, 2015.

  1. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Hah, couldn't find it. Good to know! Thanks then for it!
     
  2. Ludiq

    Ludiq

    Joined:
    Mar 6, 2015
    Posts:
    577
    Any chance of a collaboration / integration with Unity3D.IncrementalCompiler? Especially since it's inspired from your implementation.
     
    mgear likes this.
  3. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    No special integration is needed. You can copy/paste AsyncTools folder from my project to a project that uses the incremental compiler and async/await and caller info features will work as usual. My demo scenes/scripts work fine.

    I expect them to continue to work fine even when Unity finally updates the ancient compiler to a normal one during 5.5.x cycle.
     
    Last edited: Jul 15, 2016
  4. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    864
    I have some questions:

    - can this potentially be considered production ready?
    - is the code generated faster than the unity one?
    - is it the compilation faster than the unity one?
     
  5. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    My opinions:
    - About as much as most Unity things are production ready
    - Slightly
    - Definitely
     
    alexzzzz likes this.
  6. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    I was about to say something like "use it at your own risk", but I like your answer.
     
    makeshiftwings likes this.
  7. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    864
    hehe thanks, I have another question if you don't mind. Can I use compiler settings per project? A Unity solution is made up 4 projects, can I use different settings for each? I want to disable warnings for the plugin dll.
     
  8. janus007

    janus007

    Joined:
    Apr 12, 2016
    Posts:
    5
    Amazing work.
    Can anyone tell me why this isn't more popular? I've been developing in C# since it was born, and as a newcomer to Unity3D one of the first things I noticed was the weird Coroutine functionality and the mono dependency.
     
    Agent766 likes this.
  9. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    The weird (?) coroutines and mono dependency are still there. This just lets you compile C# 6 into a .NET 3.5 assembly that the Mono runtime can handle.
     
  10. anton90001

    anton90001

    Joined:
    Aug 13, 2015
    Posts:
    2
    Hi Alex,

    First of all, thank you very much for untangling this bit and doing great job!

    I noticed a very strange behavior, though: on Unity 5.4.0b19 on Mac OS installing the plugin and reimporting everything leads to a bunch of errors printed out to console:

    Code (CSharp):
    1.  
    2. Assets/CSharp 6.0 Support/AsyncTools/UnityTaskScheduler.cs(7,35): error CS0433: The imported type `System.Threading.Tasks.TaskScheduler' is defined multiple times
    3. Assets/CSharp 6.0 Support/AsyncTools/AsyncTools.cs(67,66): error CS0433: The imported type `System.Threading.CancellationToken' is defined multiple times
    4. Assets/CSharp 6.0 Support/AsyncTools/AsyncTools.cs(84,16): error CS0433: The imported type `System.Threading.Tasks.Task<TResult>' is defined multiple times
    5.  
    Looks like Unity loads other assemblies (rather than provided with the plugin) and fails to compile. The scene doesn't run either. However, Mono Develop feels pretty much comfortable with the code and builds everything fine (I appreciate they go for different compilers).

    Has anyone run into a similar issue?
     
  11. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Happened on Mac OS X if Mono 4.4 was installed. Check the updated CSharp60Support 1.8.1.zip

    No, it works for the whole solution.
     
  12. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    864
    I understand, but can something be done about it?
     
  13. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Unity doesn't make any distinction between projects and uses the same compiler options for all the projects. Theoretically it's possible to modify CSharpCompilerWrapper.exe so that it would use different compiler options depending on the output library's name.
     
  14. anton90001

    anton90001

    Joined:
    Aug 13, 2015
    Posts:
    2
    This indeed helps, thank you very much!
     
  15. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Btw, what is the intended way of waiting for UnityEngine.AsyncOperation (returned by UnityWebRequest.Send()) in my async/await code?

    My current approach doesn't look like a way to go:
    Code (csharp):
    1. while (!asyncOp.isDone) {
    2.    await TaskEx.Delay(100);
    3. }
     
  16. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    I tried to write a custom awaiter for AsyncOperation, but since it doesn't let one to subscribe for its completion, whatever I came up with was much more complex than
    Code (CSharp):
    1. while (asyncOp.isDone == false)
    2. {
    3.     await 0; // equivalent for yield return null
    4. }
     
  17. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    ... and did basically the same behind the curtain.

    Having this code somewhere in a project will let you to await AsyncOperations, for example:
    Code (CSharp):
    1.     async void Start()
    2.     {
    3.         var request = UnityWebRequest.Get("google.com");
    4.         await request.Send();
    5.         Debug.Log("downloaded " + request.downloadedBytes + " bytes");
    6.     }
    PS
    Integrated it into CSharp60Support 1.11.0
     
    Last edited: Aug 14, 2016
    mdrotar likes this.
  18. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Hi, thanks for such a fast response. One more problem. It turned out that I've missed documentation a bit and forgot to add UnityScheduler prefab to my scene so async/await continuations are performed on main thread. After I've added it Unity crashes when I stop simulation in Editor (unpress play button). Here is crash report: http://pastebin.com/JrYwJUav
    Interesting thing is that crash is only happening if I press my ui button with all async handler. Tried to reproduce same crash in your AsyncOperationAwaiter demo but no luck for now
     
  19. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Reproduced. Seems to be somehow related to C# generics. Here is modified AsyncOperationAwaiterTest.cs that crashes upon stop.

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3. using UnityEngine.Networking;
    4. using System.Threading.Tasks;
    5.  
    6. public class ResponseClass
    7. {
    8. }
    9.  
    10. public class NetworkClass
    11. {
    12.     public static async Task<T> Send<T>(string path) where T : new() {
    13.         var request = UnityWebRequest.Get(path);
    14.         await request.Send();
    15.         return new T();
    16.     }
    17. }
    18.  
    19. public class AsyncOperationAwaiterTest : MonoBehaviour, IPointerClickHandler
    20. {
    21.     private Texture originalTexture;
    22.     private Texture2D texture;
    23.     private Material material;
    24.  
    25.     public async void OnPointerClick(PointerEventData eventData)
    26.     {
    27.         var response = await NetworkClass.Send<ResponseClass>("http://google.com");
    28.         Debug.Log("log");
    29.     }
    30.  
    31.     private void Start()
    32.     {
    33.         material = GetComponent<Renderer>().sharedMaterial;
    34.         originalTexture = material.mainTexture;
    35.         texture = new Texture2D(512, 512);
    36.  
    37.         Debug.Log("\n--> Click on the box to change its texture <--\n");
    38.     }
    39.  
    40.     private void OnDestroy()
    41.     {
    42.         Destroy(texture);
    43.         material.mainTexture = originalTexture;
    44.     }
    45.  
    46.     private void Update()
    47.     {
    48.         transform.Rotate(0, 90 * Time.deltaTime, 0);
    49.     }
    50. }
     
  20. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Look's like a Mono compiler bug/feature. The same code compiled with Roslyn works fine. If Mono compiler is used, the editor crashes on stop playing the scene.

    Unfortunately I can't make Roslyn run on Mac OS.
     
  21. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Thats completely fine ;)
    Maybe you have any insights or ideas what's wrong with Mono? So it can be workarounded or atleast we can submit Mono bug?
     
  22. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Btw I've checked Roslyn github and there is MacOS build badge. But I guess it's not that simple :) Could you please explain what's wrong with Roslyn on MacOS?

    Update: and according to release notes Xamarin Studio 6.0 uses roslyn internally.
     
    Last edited: Aug 16, 2016
  23. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Some previous versions of Unity couldn't load assemblies generated with Roslyn without debug information files (.mdb). Roslyn can't generate .mdb, so I use pdb2mdb utility to convert Microsoft's .pdb-files to Mono's .mdb that Unity can consume. It works fine on Windows, but on MacOS Roslyn can't generate .pdb-files either:
    The latest versions of Roslyn (I took the one from VS 15 Preview 3) can generate some "portable" version of .pdb but it makes pdb2mdb utility crash.

    However, today I realized that Unity 5.4 actually can load Roslyn's assemblies with no debug information at all. Debugging in an IDE won't work but at least everything else seems to work.

    Check CSharp60Support 1.11.11 with experimental Roslyn support on MacOS. Not sure if it will work in Unity 4, probably not.
     
    Last edited: Aug 17, 2016
  24. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Works fine for me :) But probably roslyn on MacOS should be optional. And Mono bug also could be probably fixed in future releases. So maybe after adding some checkbox in UI you can make non-experimental release.

    I'll take a look at portable pdb in the meanwhile.
     
  25. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Btw I also had a thought that more fresh versions of mcs.exe like 4.4.2.11 or even 4.6 master could be working. Where you got that mcs.exe? Cause on mac I have only osx-binary versions like /usr/local/bin/mcs
     
  26. janus007

    janus007

    Joined:
    Apr 12, 2016
    Posts:
    5
    Yes "weird", why should we run anything on main thread that isn't UI specific? Weird, as in "yes let us make a loop and let us interrupt the user experience"

    Yes, the mono dependency would still be there, that is obvious, but still way better than coroutines
     
  27. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    Unity is not thread-safe, so you can't access most of its classes from a secondary thread anyway. It will throw an exception when you try it. You can already create separate threads with .NET 3.5 by using ThreadPool or similar methods, C# 6 just adds await/async, but using those you still can't access Unity components on secondary threads. There is a way to use async to leave and then come back to the main thread using alexzzzz's AsyncTools that are included, but if you think coroutines are weird, you'll probably think the AsyncTools are even weirder. ;)
     
  28. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Just had a thought that for Unity 5.5 plugin can be simplified to using default Mono 4.4 compiler but without forcing it to .NET 2.0 mode
     
  29. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Are you talking about API Compatibility Level: Net 2.0 / Net 2.0 Subset ?
     
  30. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    My point is that Unity 5.5 now has Mono 4.4 built-in. But by default it uses Mono 4.4 compiler in .net 2.0 mode. All we need to do is to use that compiler but without forcing .net 2.0 mode. This means we can drop roslyn and mcs.exe from plugin.
     
  31. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    That would mean that I would have to support one more version of the plugin:
    - Unity 4.x
    - Unity 5.0-5.4
    - Unity 5.5+

    Btw, does anyone still use Unity 4?
     
    Last edited: Sep 5, 2016
  32. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Yeah, from a maintenance side that's probably is not the best idea ever :)
    Regarding Unity 4 I think it's ok to drop it.
     
  33. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Yeah, on the second thought it's really bad idea because there will be C# 7.0 soon which is not supported by Mono 4.4
     
  34. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    tuples.png

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class TuplesTest : MonoBehaviour
    4. {
    5.     void Start()
    6.     {
    7.         Debug.Log("Tuples:");
    8.  
    9.         var i = 10;
    10.         var tuple = GetTuple(i);
    11.  
    12.         Debug.Log($"{i} doubled = {tuple.doubled}, {i} squared = {tuple.squared}, text = {tuple.text}");
    13.  
    14.         // Deconstruction
    15.         // #1
    16.         (int first, int second, string third) = tuple;
    17.         Debug.Log($"first = {first}, second = {second}, third = {third}");
    18.  
    19.         // #2
    20.         var (primero, segundo, tercero) = tuple;
    21.         Debug.Log($"primero = {primero}, segundo = {segundo}, tercero = {tercero}");
    22.  
    23.         // #3
    24.         int a, b = 42;
    25.         string text = "some text";
    26.         (a, b, text) = tuple;
    27.         Debug.Log($"a = {a}, b = {b}, text = {text}");
    28.  
    29.         // #4
    30.         var vector = new Vector3(1, 2.5f, 3);
    31.         var (x, y, z) = vector;
    32.         Debug.Log($"Vector {vector} => x = {x}, y = {y}, z = {z}");
    33.  
    34.         Debug.Log("");
    35.     }
    36.  
    37.     (int doubled, int squared, string text) GetTuple(int x) => (x * 2, x * x, x.ToString() + "!");
    38. }
    39.  
    40. static class Vector3Extensions
    41. {
    42.     public static void Deconstruct(this Vector3 vector, out float x, out float y, out float z)
    43.     {
    44.         x = vector.x;
    45.         y = vector.y;
    46.         z = vector.z;
    47.     }
    48. }

    The biggest downside of C# 7.0 is that Resharper supports only 6.0.

    PS
    Just updated the repository and the downloads page.
     
    Last edited: Sep 5, 2016
  35. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    macos7.PNG
    vscode7.PNG
     
    Qbit86 likes this.
  36. malyzeli

    malyzeli

    Joined:
    May 1, 2014
    Posts:
    11
    I believe soon there will be no more reason to use Visual Studio & ReSharper, considering Rider is coming..
    Seriously, Visual Studio is such a stupid IDE compared to IntelliJ IDEA and its derived tools - try it and you are never going back..
     
  37. IvanShakhov

    IvanShakhov

    Joined:
    May 19, 2016
    Posts:
    23
    Is ther a way to detect that "unity-c-5.0-and-6.0-integration" from other Unity plugin?
    Currently I added check for presence of the folder CSharp60Support.
    (https://github.com/JetBrains/Unity3dRider)
    to avoid setting LangVersion to 5.0

    @alexzzzz
     
    Last edited: Oct 10, 2016
  38. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    The easiest way, I think, is to check if the current synchronization context is not null, and if it's not then check its type name. Unity will provide a synchronization context in its official C# 5 support.

    Code (CSharp):
    1.     bool IsCSharp5Available()
    2.     {
    3.         return SynchronizationContext.Current != null;
    4.     }
    5.  
    6.     bool IsCSharp5SupportUnofficial()
    7.     {
    8.         return SynchronizationContext.Current.GetType().Name == "UnitySynchronizationContext";
    9.     }
    PS
    Oops! the previous solution won't work in the editor. This one should work:
    Code (CSharp):
    1. bool found = AppDomain.CurrentDomain.GetAssemblies()
    2.                       .SelectMany(assembly => assembly.GetExportedTypes())
    3.                       .Any(type => type.Name == "UnitySynchronizationContext");
     
    Last edited: Oct 10, 2016
    IvanShakhov likes this.
  39. Ludiq

    Ludiq

    Joined:
    Mar 6, 2015
    Posts:
    577
    Hey!

    So the Unity 5.5 Beta includes a Mono compiler upgrade to 4.4, which should theoretically be feature complete for C# 6.

    However, when I try to use C# 6 features, I get "Feature (XXX, ex.: 'nameof operator') is not available in C# 4. Please use language version 6 or greater". I feel like this is an artificial limitation imposed by Unity's generated project files, do you know of any way to disable it?
     
  40. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    You should post about that in the beta forum here: https://forum.unity3d.com/forums/experimental-scripting-previews.107/
    Short answer: you need the VSTU update in the sticky thread at the top of that forum.
     
  41. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    @ludiq In your Assets folder create a text file named "mcs.rsp" and put this line in it:
     
  42. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Just updated my plugin to 2.0.0.

    1. Dropped Unity 4 support.

    2. 'UnityScheduler' prefab is no longer needed on a scene. Delete it, please. The synchronization contexts are initialized automatically.

    3. Added a synchronization context for the editor update. Async/await now can be used in editor scripts.

    4. Two separate downloads: CSharp60Support 2.0.0.zip and CSharp70Support 2.0.0.zip. The names speak for themselves. The difference is:
    - CSharp60Support includes Mono 4.4 C# 6.0 and Roslyn C# 6.0 compilers.
    - CSharp70Support includes only Roslyn C# 7.0 preview compiler taken from Visual Studio 15 Preview 5. The .unitypackage provides additional types required for C# 7.0 tuples support.

    5. Roslyn by default is enabled for MacOS. Notes:
    - The C# 7.0 version will require Mono 4.6+ to run properly.
    - Roslyn cannot write .pdb files on MacOS, so debugging won't work. If you need it, just delete Roslyn folder to use the Mono compiler instead.

    6. LangVersion entries in .csproj files are no longer automatically removed. On the contrary, they are automatically created and should always contain a correct value (either 6 or 7).
     
  43. stopiccot

    stopiccot

    Joined:
    May 2, 2013
    Posts:
    26
    Btw, it would be great to make plugin compatible with Unity's code hot-reload. On first sight moving intialization code to OnEnable() does the job. But probably this should be investigated more carefully)
     
  44. forumr

    forumr

    Joined:
    Nov 22, 2016
    Posts:
    2
    thanks!

    Is it possible to get the smcs.rsp file to work so that I can enforce warnings as errors?
    http://answers.unity3d.com/questions/216838/how-to-force-warnings-as-errors.html



     
  45. forumr

    forumr

    Joined:
    Nov 22, 2016
    Posts:
    2
  46. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Yes, the rsp name should match the compiler name. For Unit 5.5 with updated Mono compiler it will be mcs.rsp
     
  47. Agent766

    Agent766

    Joined:
    Nov 10, 2016
    Posts:
    3
    I'm trying to update my project to use the new version of CSharp 6.0 Support. I'm trying to run a function on the next frame by starting a task and await ToUpdate().
    Code (Csharp):
    1. Task.Factory.StartNew(async () =>
    2.         {
    3.             AsyncTools.WhereAmI("SceneLoaded");
    4.             await AsyncTools.ToUpdate();
    5.             AsyncTools.WhereAmI("SceneLoaded 2");
    6.             RemoveComponents();
    7.         });
    What's getting printed is this:
    Code (csharp):
    1. SceneLoaded: background thread, id: 2
    2. SceneLoaded 2: background thread, id: 2
    I set a breakpoint and the UnityScheduler's Initialize method is being called before my function and the thread id there is 1 like it should be. Any ideas why this could be happening?
     
  48. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    @Agent766

    I've managed to simulate the same behaviour by replacing
    Code (CSharp):
    1. public static class AsyncTools
    2. {
    3.     private static readonly Awaiter updateAwaiter = new SynchronizationContextAwaiter(UnityScheduler.UpdateScheduler?.Context);
    with
    Code (CSharp):
    1. public static class AsyncTools
    2. {
    3.     private static readonly Awaiter updateAwaiter = new SynchronizationContextAwaiter(null);
    It must be a racing condition where AsyncTools' static fields happen to be initialized before UnityScheduler.Initialize() executes. This is certainly a bug that has to be fixed. And this bug is hidden by using Elvis-operator instead of the normal member access operator.

    Is there, by chance, any code in your project that touches AsyncTools class (triggering its initialization) that potentially can run before UpdateScheduler property gets correctly initialized inside UnityScheduler.Initialize()?
     
    Last edited: Dec 1, 2016
  49. potterdai

    potterdai

    Joined:
    Apr 23, 2014
    Posts:
    9
    @alexzzzz
    Really appreciate your library!
    Just got a question, does this mean that I can use external net4.* plugins like JIL etc.?
    Thank you very much! = )
     
  50. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    @potterdai
    Despite the code can be C# 6 or 7, the CLR version it targets is still 2.0. So, you can't reference CLR 4.0 assemblies yet inside Unity. You can do it only in mono-upgrade preview build of Unity.