Захотел я идти в ногу со временем, посмотрел новые фишки и плюшки C#6/7, воодушевился. Там так всё вкусно и круто, что грех не пользоваться. Открыл Unity, Visual Studio, написал пару строк и...впал в уныние. На любые попытки использования новых фич мне говорят одно:
Feature bla bla bla is not available in C#4. Please use language version 6 or greater
или
Feature bla bla bla cannot be used because it is not part of the C# 4.0 language specification
Посмотрел версию Mono, которую использует Unity 5.6 (!!! самая последняя версия) и это было: 2.0 (Visual Studio built mono). В итоге в ней есть всё, что есть в C#3, плюс часть из C#4.
Это меня не очень радует и устраивает.
Есть ли какая возможность, всё-таки, использовать новые версии языка, а не застыть в далёком 2010-ом? Что можно сделать и как?
Ответ
Да, можно использовать новые версии, но с оговорочкой...об этом ниже.
Хоть Unity и застряла на долгое время на CLR 2.0, тем не менее новые фичи C# не требуют самой последней версии CLR. Компиляторы Microsoft и Mono могут скомпилировать C# 5/6/7 для CLR 2.0 если их явно об этом попросить.
Замечание: однако некоторые фичи все же недоступны, например такие как dynamic
Итак, эту возможность (и, на данный момент, может быть единственную) можно найти в репозитории битбакета Unity C# 5.0 and 6.0 Integration
Что надо сделать?
Для C# 6.0
Скопировать папку CSharp60Support из репозитория (или со страницы закачки) к себе в Unity проект. Папку необходимо поместить в корень проекта, рядом с папкой Assets. НЕ во внутрь!
Импортировать CSharp60Support.unitypackage (находится в папке CSharp60Support) в свой проект.
Перезагрузить Unity
[По желанию - не обязательно]: На Windows - запустить /CSharp60Support/ngen install.cmd с правами администратора. Команда скомпилирует csc.exe, pdb2mdb.exe и mcs.exe используя Ngen, что позволит производить компилирование в Unity чуточку быстрее.
Для C# 7.0
Для MacOS скачать и установить Mono 4.6+. Для Windows скачать и установить .Net Framework 4.6.2+
Скопировать папку CSharp70Support из репозитория (или со страницы закачки) к себе в Unity проект. Папку необходимо поместить в корень проекта, рядом с папкой Assets. НЕ во внутрь!
Импортировать CSharp70Support.unitypackage(находится в папке CSharp70Support) в свой проект.
Перезагрузить Unity
[По желанию - не обязательно] На Windows - запустить /CSharp70Support/ngen install.cmd с правами администратора. Команда скомпилирует csc.exe, pdb2mdb.exe и mcs.exe используя Ngen, что позволит производить компилирование в Unity чуточку быстрее.
Таким образом изменению подвергается только папка с текущим проектом. Остальные проекты будут работать как обычно с текущей версией языка, Mono и прочей жестью :)
Как это работает?
/Assets/CSharp vNext Support/Editor/CSharpVNextSupport.dll - расширение для редактора, которое через рефлексию изменяет внутренние данные редактора, говоря ему, чтобы тот использовал альтернативный компилятор C# (/CSharpXXSupport/CSharpCompilerWrapper.exe). Если он не существует, то используется дефолтный.
CSharpCompilerWrapper.exe получает и перенаправляет запросы на компиляцию от Unity к одному из актуальных C# компиляторов, которые используют следующие правила:
Если существует папка CSharp70Support и она содержит папку Roslyn, то используется компилятор C# 7.0;
Если существует папка CSharp60Support и она содержит папку Roslyn, то используется компилятор C# 6.0;
Иначе если существует папка CSharp60Support и она содержит mcs.exe, то использует компилятор Mono C# 6.0
В ином случае используется компилятор по дефолту (/Unity/Editor/Data/Mono/lib/mono/2.0/gmcs.exe).
Убедитесь, что компилятор CSharpCompilerWrapper.exe действительно работает! Для этого посмотрите в логи компиляции: UnityProject/CSharpXXSupport/compilation.log
Какие платформы поддерживаются?
Работает это на всех основных платформах:
Windows (editor and standalone)
MacOS (editor and standalone)
Android
iOS
Чуть больше информации и небольших ограничениях вы можете почитать на главной странице репозитория, а также (т.к. основная информация дана выше) в виде цитаты с источника на английском языке:
Response (.rsp) files
If you want to use a response file to pass extra options to the compiler (e.g. -unsafe), the file must be named CSharpCompilerWrapper.rsp
platforms are "supported"
On MacOS the Roslyn compiler cannot create debug information files (.pdb) that Unity can consume. If you compile your code with Roslyn on MacOS you won't be able to debug it.
Since WebGL doesn't offer any multithreading support, AsyncBridge and
Task Parallel Library are not available for this platform. Caller Info
attributes are also not available, because their support comes with
AsyncBridge library.
AsyncBridge/TPL stuff is also not compatible with Windows Store
Application platform (and probably all the platforms that use .Net
runtime instead of Mono runtime) due to API differences between the
recent versions of .Net Framework and the ancient version of TPL
(System.Threading.dll) that comes with AsyncBridge. Namely, you can't
use async/await, Caller Info attributes and everything from
System.Threading.dll (concurrent collections for example).
Other known issues
C# 5.0/6.0 is not compatible with Unity Cloud Build service for obvious reason.
Using Mono C# 6.0 compiler may cause occasional Unity crashes while debugging in Visual Studio -
http://forum.unity3d.com/threads/c-6-0.314297/page-2#post-2225696
IL2CPP doesn't support exception filters added in C# 6.0 (ExceptionFiltersTest.cs).
If a MonoBehaviour is declared inside a namespace, the source file should not contain any C# 6.0-specific language constructions before
the MonoBehaviour declaration. Otherwise, the editor won't recognize
the script as a MonoBehaviour component.
Bad example:
using UnityEngine;
using static System.Math; // C# 6.0 syntax!
namespace Foo
{
class Baz
{
object Qux1 => null; // C# 6.0 syntax!
object Qux2 { get; } = null; // C# 6.0 syntax!
}
class Bar : MonoBehaviour { } // "No MonoBehaviour scripts in the file, or their names do not match the file name."
}
Good example:
using UnityEngine;
namespace Foo
{
class Bar : MonoBehaviour { } // ok
class Baz
{
object Qux1 => null;
object Qux2 { get; } = null;
}
}
There's a bug in Mono C# 6.0 compiler, related to null-conditional operator support (NullConditionalTest.cs):
var foo = new[] { 1, 2, 3 };
var bar = foo?[0];
Debug.Log((foo?[0]).HasValue); // error CS1061: Type `int' does not
// contain a definition for `HasValue' and no extension method
// `HasValue' of type `int' could be found. Are you missing an
// assembly reference?
Mono compiler thinks that foo?[0] is int while it's actually Nullable
P.S. Попробую отслеживать тему и держать ссылку на свежую версию актуальной.
Комментариев нет:
Отправить комментарий