Search Unity

Unity errors when compiling valid code - what version of C# language is supported?

Discussion in 'Scripting' started by malyzeli, Jan 26, 2016.

  1. malyzeli

    malyzeli

    Joined:
    May 1, 2014
    Posts:
    11
    Hello everybody!

    I started working with Unity recently, but I have many years of experience in multiple programming languages, and I'm always trying to utilize maximum of advanced features of the language. I discovered there are some expressions which are valid C# code, but Unity has trouble compiling it, so I'm assuming those are newer language features which Unity can't comprehend. When it happened first time, I just ignored it, but since I found multiple occurrences of this thing, I decided to ask here.

    So, what version of C# language is supported in Unity?

    I'm using amazing VS plugin Jetbrains ReSharper, which watches over your code and (apart from unbeatable refactoring features) it suggests you many improvements of your code like correct naming conventions and newer syntax of stuff you could write better in today C#.

    I'm quite new in C# development and Visual Studio is not my native IDE, so I would really appreciate if somebody could tell me how can I set corresponding language version for the project, so the plugin would stop recommending me to use syntax which is not supported by older compilers.

    If there is any way how to make this code to compile in Unity so I can keep using latest language features, it would be even better!

    There are some problematic snippets I found:

    New string interpolation expression - not working
    Code (CSharp):
    1. Debug.Log($"Repeated Initialization Blocked on {gameObject.name} ({gameObject.GetInstanceID()})");
    Old string format method - working
    Code (CSharp):
    1. Debug.Log(String.Format("Repeated Initialization Blocked on {0} ({1})", gameObject.name, gameObject.GetInstanceID()));

    Error message

    Code (CSharp):
    1. Script.cs(18,27): error CS1525: Unexpected symbol `<internal>'
    New lambda property accessor - not working
    Code (CSharp):
    1. public BottomPanel BottomPanel => new BottomPanel(...);
    Property accessor - working
    Code (CSharp):
    1. public BottomPanel BottomPanel { get { return new BottomPanel(...); } }
    Error message
    Code (CSharp):
    1. Script.cs(86,41): error CS1519: Unexpected symbol `=>' in class, struct, or interface member declaration
    Conditional access - not working
    Code (CSharp):
    1. controller.GetType().GetField("testField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(controller, true);

    Error message

    Code (CSharp):
    1. Script.cs(33,108): error CS1525: Unexpected symbol `.'
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,510
    Unity uses an older version of Mono.

    It fully meets the requirements of .Net 2.0 (or subset, depending your configuration).

    It can support most features up to .Net 3.5, but not all (random things here and there, I believe unity has a pretty comprehensive list in their documentation).
    http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html

    As for C# version, it allows up to C# 3.0. Though I've seen threads on the forums here to hack unity into accepting the syntax sugar of newer version of C# (while of course not supporting the framework related stuff).
     
    malyzeli and aer0ace like this.
  3. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    You can create a Windows native plugin and use that code there, but not directly in Unity. I've used a lot of threaded await/async code this way.

    Unity is based off an old version of Ximarin's Mono .NET. Unity got a perpetual license back when Novell still owned it, and have been patching it ever since.

    Effectively, this means Unity's .NET is somewhere between 2.0 and 3.5. (Closer to 3.5) It also explains their drive to make IL2CPP as they want to get away from their patched version of Mono.

    This may also be useful:
    http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html
     
    malyzeli and lordofduct like this.
  4. malyzeli

    malyzeli

    Joined:
    May 1, 2014
    Posts:
    11
    Thank you for your responses and for the link to compatibility sheet. It would be nice to have some Technical Details page directly on main Unity website. I tried to google some queries like "unity C# supported version" but didn't get any convincing results, so I decided to ask here. Coming from Java background I'm still a bit confused about this .NET/Mono/C# terminology. :)

    When you say "create a Windows native plugin" I believe you mean creating standalone project as a Class Library and then using compiled DLL like explained in this manual. Please correct me if I'm wrong.
    http://docs.unity3d.com/Manual/UsingDLL.html

    Also I found this project promising newer language features integration, which seems to be really useful, definitely going to give it a try!
    https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    3,941
    Explanation of .NET/Mono/C#:

    C# is the language. There are two available platforms for the language:

    .NET - Microsoft's (mostly) closed source implementation for the Windows platform.
    Mono - Open-source implementation for a bunch of different platforms.

    Unity uses a ported version of Mono, and has an enormous technical debt in that area. They're trying to fix that, and will be attempting to jump up to C# 6 (Which is equivalent to .NET 4.5, and Mono 4.0, if you didn't feel confused yet), but that's under " IN-PROGRESS, TIMELINES LONG OR UNCERTAIN" on the Roadmap.

    I haven't found a way to make Resharper aware of what C# version you're using, but I haven't looked very hard.

    EDIT: If you're from Java, there's the same thing with Oracle JDK and Open JDK, and this mess. If you'd worked with C/C++, there's clang vs. gcc. Any large enough language is doomed to get a bunch of different implementations.
     
    Last edited: Jan 27, 2016
    malyzeli likes this.
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,510
    You see, C# unlike Java isn't a framework and runtime tied to a language.

    Rather it's broken up into parts so that it can support multiple languages.

    The infrastructure

    .NET - the over encompassing name for an entire ecosystem

    .NET Framework - a framework of available libraries to quickly start writing software against, it's like the standard libraries you start off with in Java.

    .NET CLR (Common Language Runtime)- the runtime on which .NET applications run, this is just like the JRE.

    The Framework and CLR are tied together by version. As new versions of the framework are released, a new version of the CLR must be released as well to run those new additions to the framework.

    The Languages

    CIL - Common Intermediate Language, this is what is generated when you build a .Net application. It's like Java's 'bytecode'. When distributed to an end user, the CIL is then compiled to their specific machine in a JIT compiler, just like Java.

    CLI - Common Language Infrastructure, yeah, that name is confusing as all hell... CIL and CLI? This is an open specification submitted by MS to the ISO and ECMA standards. Allowing the open development of CLI languages that can be built into CIL.

    All .Net language definitions just need to be CLI compatible. May the language be defined from the getgo to compile to CIL, or an existing language has a CIL compiler built for it.

    Note, these languages may then evolve over time, meaning they get versions to them... their growth is independent of the .Net framework, so therefore does not coincide with the version of the .Net framework. Though new additions to the framework may require a new version of the language so as to adequately tap the capabilities of that new addition (if so required).

    Microsoft included a few languages from the get go.

    C# - a language designed from the ground up for .Net. It is C-like and based heavily on Java. It started at version 1 and is currently sitting at version 6.

    VB.Net - A major upgrade of the pre-existing language VB for .Net. Going from VB6 to VB.Net v7, and growing from there up to the current v14.

    C++/CLI - it's C++... but for .Net (this one gets into weird territories though)

    There were other languages that died out, or just aren't popular.

    F# - a language more focused on the functional paradigm

    J# - pretty much dead, but was a MS created language to make Java CLI compliant.


    As I said, the CLI standard is open. So others could start making CLI compliant versions of languages. There's a long list of them, here's some of them:
    https://en.wikipedia.org/wiki/Category:.NET_programming_languages

    Another CLI compliant language is Unity's own UnityScript (which is heavily based on Javascript).

    Cross-platform, but not exactly

    Microsoft built the .Net CLR to be cross-platform... but they really only ever build it for all windows based operating systems. You might think to yourself "well that's not cross-platform, it's only on MS platform". True... but not true.

    First off, Microsoft has many platforms. Especially at the time of the invention of the .Net ecosystem back in the late 90's. NT, CE, MS/DOS and the DOS Windows (95,98,Me), and what not, all capable of targeting different hardware.

    Second off, the time of the release of .Net the future of where the OS's were to be going was a little fuzzy. A big thing was on its way... consumer 64-bit CPUs. Here's the thing, the 2 big CPU builders were designing their own 64-bit implementations.

    Intel was working on a completely new CPU design for the move to 64-bit, which meant a brand new instruction set, which meant having to compile brand new 64-bit versions of software to run on it. No backwards compatibility.

    AMD on the other hand was working to expand the x86 instruction set to include 64-bit support. This was x86-64. It meant for a more bloated design, BUT had the added benefit of being backwards compatible.

    It wasn't quite certain where things were going quite yet. And honestly the idea was that it'd be a completely new CPU structure. The CPU upgrades of the years before usually required it. So yeah.

    .Net was designed to allow the easy porting across those sorts of hurdles. So that way, no matter where hardware were to go... Microsoft could just make a version of Windows for that hardware, compile a version of .Net CLR for that hardware, and then your software that you wrote just magically started to work on that new hardware... no need to rework anything on your end (in most cases, as long as you weren't tapping into some weird hardware specific thing... hence why most .Net languages shield you from hardware).

    THING IS, It was still Windows only...

    Mono

    So a company named Ximian created the 'Mono-project'. They went through many changes, being bought by Novell, then when Novell was acquired by Attachmate, engineers from the original Ximian team that had left, formed a new company Xamarin. Attachmate showed no interest in maintaining Mono, and Xamarin picked it back up.

    Note the puns they like. Mono isn't a reference to 'single', it's a monkey reference (mono being spanish for monkey). Hence 'Ximian' a pun for 'Simian', or Xamarin, a pun for Tamarin. They really like monkeys for some reason.

    The 'mono-project' was an attempt to port the .Net framework and CLR to linux and other unix-like OS's (and beyond as well). Because CLI was an open standard, compiling to CIL wasn't a problem... it was the framework and CLR that was closed source on the MS side. After getting to work, Microsoft allowed their open-source effort for porting it to other operating systems. (of course it wasn't an official license, and MS sort of held onto the ability to not support and change at any time with out warning).

    The mono-project has many parts as well:

    mono-framework - this is just like the .Net framework, it's a complete rewrite of the standard libraries delivered with .Net

    mono-runtime - this is just like the .Net CLR, it runs CIL truly cross-platform.

    MonoDevelop - the Visual Studio of mono.

    And then... there's Xamarin.

    Xamarin

    This gets into some weird history, read if you want... but isn't as relevant to your question as the rest of that was.

    So, you know how Xamarin took back the responsibility of maintaining the open-source Mono-project after leaving Novell.

    Well, yeah, they do maintain the open-source Mono project.

    BUT, they also have something else.

    The Xamarin platform allows writing software that targets mono, and then compiling them to natively run on different hardware. This is primarily useful for mobile development for Android, iOS and Windows phone... but technically can be used to compile to native code for other platforms.

    It's sort of ironic... an entire ecosystem that was designed to run virtually in VME's for a cross-platform deployment. Now comes with a whole set of tools that allows it to return to the pre-VME time of compiling to specific platforms!

    This is often referred to as AOT compilation (Ahead-of-time). Unlike JIT compiler (just-in-time) that ran on the target platform and compiled CIL to machine code on the fly. Instead an AOT compiler compiles all of the CIL to machine code before hand with a target platform in mind.

    The problem here is... Xamarin didn't make this quite so open-source as they made Mono.

    This is why when you have a the pro versions of Unity you need to pay EXTRA licensing fees to compile to other platforms like iOS and what not (of course this gets fuzzy in unity 5 w/ il2cpp).

    Licensing

    Combine this with the fact that Mono sits under a LGPL/GPL/X11 license which if a closed source developer wants to tap into while not having to follow the GPL/X11 requirements would need to get a commercial license:
    http://www.mono-project.com/docs/faq/licensing/

    These complicated licensing issues is why Unity is stuck in limbo with their Mono implementation.

    See Unity needed to modify the mono runtime to fit it into their unity engine. But the unity engine is all closed source (and they want to keep it that way I bet)... because the open-source licensing would have required conflicted with Unity's licensing of the unity game engine... they had to opt for the commercial license.

    Thing is, the commercial license didn't cover new versions of Mono. And they got this way the hell back when Novell were maintaining mono-project. And they were also a much smaller entity back then at the beginning. Just getting off the ground as a game engine developer.

    Now a days Unity is a much larger name in the games industry. And the negotiations with Xamarin on the updated commercial license aren't exactly going the way Unity would like them. With Xamarin wanting a bit more money then Unity is willing to shell out.

    Thing is... looking at that licensing on there, it's super freaking complicated! Every part of it from the compiler to the tools to the what not all have different sorts of licenses on them depending on what they are. This all has to do with the whole fact that they're emulating Microsoft, while also being born in the linux eco-system of open-sourceness and the GPL license ideology (which well, to be brutally honest... isn't exactly the most lucrative license for the developers... notice how Xamarin platform outside of mono isn't under it!)

    But certain key components of the entire structure are under much more accessible licenses. Take for instance the compiler and the library both being under the MIT/X11 license (with the compiler being joined to the GPL, but not LGPL). This is like I said because of Microsoft. That's technically the parts of the whole get up that Microsoft truly owns the rights too... Microsoft gave their nod to allow its existence... but that's because it was intended to be TRULY open, MS was cool with everyone using it since they weren't directly profiting from it as if the design was their own.

    Not like the GPL/LGPL, which isn't quite exactly truly open (IMO). See, unlike the MIT license which just basically says "yeah, you're free to use my software, as well as hack apart my software... just don't expect me to support you if it breaks". The LGPL and GPL licenses say a quite different thing... they say "sure, you can use my stuff.... but IF you want to hack it to bits, well.... you need to make the new resulting software free and open-source and meet most of the requirements of the LGPL and/or GPL license".

    I mean I get why the GPL/LGPL licenses say this sort of thing. They don't want you to take the fruits of their labour and then zip it all back up into a closed source product and profit from it.

    But this is why I don't consider it truly open. I like to refer to it as a 'virus license'. It's a license that basically infects your software with the GNU ecosystem's ideological software stance. Great if you're already down with that model of software development... but crap if you aren't. GNU is free and open-source, as long as you are GNU as well!

    This isn't to rag on the GNU open-source community.

    But it ain't perfect, and it makes making money off your software a bit more difficult! Again, notice how Xamarin did NOT use this license structure for its Xamarin platform tools!

    So with the MIT/X11 license on the key components of mono... unity decided to go their own way. Instead of using Xamarin's tools to AOT compile, and instead of using the Mono commercial license to support mono runtime. They instead take the open parts of it (the library primarily) and make their own set of AOT compilers.

    il2cpp

    I know you didn't exactly bring this up, but it's another name you'll be seeing thrown around.

    So since Unity runs on an out-dated version of Mono, and licensing conflicts don't allow them to easily upgrade to the latest version.

    They instead created a tool that converts CIL into C++-compilable code.

    This completely side-steps all the parts of the mono-commercial license, as well as Xamarin tools, for running what is essentially .Net code on those platforms.






    Back to your other questions

    Yeah, that was long... sorry.

    That link you supply aren't Windows native plugins.

    There's really 2 types of plugins.

    Managed Plugins - these are mono/.net dll's that are intended to run in the .net/mono frameworks.
    Native Plugins - these are platform dependent dll's that are usually compiled from C/C++ or other language

    So before when I said:

    This was the thing I was referring to.

    Do note, it's not exactly supported by the Unity team. Unity plans to add C#6 support at a later time since it's based on using the C# compiler unity has internally in their editor.

    Thing is, because it's not exactly fully complete. And because Unity still uses the outdated mono-runtime, this will only give you access to SOME of the C# 6.0 features, not all.

    This lack of support, and only partial working, personally makes me consider it unstable and unusable for production code. Great for toying around... but awful for a final project.

    I'll give you an example... C# 6 has a feature that uses 'await'.
    https://msdn.microsoft.com/en-us/library/hh156528.aspx

    This is a mix of syntax sugar as well as framework specific stuff. Though the compiler will recognize the keywords/commands, the System.Threading.Tasks stuff that await uses doesn't exist in the unity version of the mono-framework.

    And there's many other features in C#6 that are like this.

    You're going to have to become intimate with the language version and decipher what is what... especially since Microsoft, nor Xamarin or Unity, make it quite obvious what parts are what. Don't be afraid if some code just doesn't compile even though you think it should... or that other code will compile, but then crash your game.
     
    Last edited: Jan 27, 2016
  7. malyzeli

    malyzeli

    Joined:
    May 1, 2014
    Posts:
    11
    Wow, thanks for your comprehensive response! Really interesting stuff for this "I want to know everything" kind of people like me. I felt like reading some thriller book! :D

    Can you point me to some good quality articles/tutorials about those native plugins you are referring to (I wouldn't mind reading about some advanced use cases)? What are the advantages of native plugins? Performance, I guess, is there something else?

    I used to work on large scale multi-agent simulation built in Java and now I decided to start developing my dream RTS game, and I'm thinking about using similar architecture for my project. One important concept is advanced tactically-thinking AI (my favourite branch of computer sciences), and since I'm not fully convinced about quality of Unity's internal structure, I would like to split the project into several standalone modules. Unity will be definitely used for battleground simulation, so I don't have to mess with rendering, physics, etc., but I believe AI solver should be separately running service, so it's completely separated from possible Unity's flaws.

    My goal is to make it reusable across multiple projects and also allow (almost) unlimited scalability - Need more smart units on the battleground? Just plug-in another instance of server running AI service and you are set.

    What do you think about this idea? Does it sounds applicable in Unity's ecosystem? You know, I'm always a bit skeptic about using frameworks where you can't look into (and possibly fix) the source when you need to. o_O
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,510
    Well managed plugins, which are just .Net/mono dll's, there's not a whole lot to it. You're really just pre-compiling them and including them in your project. Some 3rd party tools for unity might be distributed to you in this manner instead of the entire source code. Or you might do it just to control versioning of your libraries/frameworks.

    Example this is the open-source section of my framework that I use in Unity:
    https://github.com/lordofduct/spacepuppy-unity-framework

    I compile this, as well as the closed-source section of the code, and include them as dll's in my projects. Making them easily portable... just copy the latest version of my framework into a folder in my Assets for my project. And they're ready to go.



    Native plugins on the other hand exist for various reasons.

    One example is you might want to use some existing software out there that was written in C++. For example there is OpenCV:
    http://opencv.org/

    There's versions for several platforms. But each are platform specific. You can include this in unity. You'll end up having to write wrappers for them as well. (note, there is an active port of Java OpenCV to C# for use in unity on the unity store, this is not native).

    Writing your own is viable as well. If you want to maybe get that extra bit of processing power out of it by writing optimized C++.

    At the same time you could write such a thing in C#. You can write stuff to run on their own thread/s independent of the Unity thread.

    The headache that will come in is syncing to the unity thread. You can NOT access the Unity API from outside its thread. So you'll have to make work arounds for this. One design I really like is that used by ThreadNinja:
    https://www.assetstore.unity3d.com/en/#!/content/15717

    I actually have a similar structure in my RadicalCoroutine in my framework... though my framework is much more heavy-weight compared to ThreadNinja... hence why I direct people to that more often.




    If you want articles on it... google is your friend. I don't really know of many of the top of my head... I don't really spend a lot of time reading those sorts of articles.
     
  9. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,400
    Can't argue about that.

    Good news

    My C# 6.0 integration provides the stuff you need to use async/await in Unity:

    1. AsyncBridge.Net35.dll
    This library provides helper types that C# 5+ compiler needs to compile asynchronous code. As a bonus, it also contains a couple of types that enable Caller Info attributes support.

    2. System.Threading.dll
    It's an old version of Task Parallel Library before it became a part of .Net Framework 4.5. Because of its age, it's compiled for CLR 2.0 so we can use it in Unity.

    3. Custom implementations of SynchronizationContext, TaskScheduler and some basic Awaiters that I wrote specifically for Unity. These implementations are not carved in stone and not actually necessary, but make the use of async/await pattern in Unity much easier and more intuitive, just like in WinForms and WPF.

    For example,
    Code (CSharp):
    1. class Foo: MonoBehaviour
    2. {
    3.     async void Start()
    4.     {
    5.         await TaskEx.Delay(1000);
    6.         ...
    7.     }
    8. }
    Here you can be sure that the code that follows will continue to run in the main thread. Without a proper synchronization context it would run in some random thread from the thread pool.

    Bad news

    1. For targeting Windows phones and Windows Store Unity uses .Net instead of the old Mono. AsyncBridge and the old Task Parallel Library can't be used there since they duplicate the existing functionality of .Net Framework.

    It wouldn't be a big deal to just turn these dlls off for those platforms if you wanted to target them, but the API these libraries provide is slightly different from the one that .Net Framework provides. This difference makes your project incompatible with Microsoft platforms (other that desktop Windows) on the source level, which is a great inconvenience.

    2. When Unity upgrades to the newer CLR and introduces the native support for async/await providing its own implementations of SynchronizationContext and others, these new implementations may behave differently than mine do.

    I think the only feature left completely unsupported is the late binding - the dynamic keyword.
     
    Last edited: Feb 22, 2016
    lordofduct likes this.
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,510
    Nice job man.
     
  11. tswalk

    tswalk

    Joined:
    Jul 27, 2013
    Posts:
    1,106

    Is this still the case as IL2CPP can be used which takes it all back to native for the app?... I haven't tried but was curious.