Как наладить дружеские отношения между Unity и F#?

F# — это функциональный язык программирования (но, если точнее, на самом деле, это — мультипарадигмальный язык, т.к., кроме функционального программирования, он поддерживает как императивное программирование, так и объектно-ориентированное программирование) под платформу .NET Framework. Своего рода Scala в мире JVM, только для CLRF# предоставляет много интересных возможностей, и во многих сценариях он на две головы выше своего брата C#. Пожалуй, чтобы описать все преимущества F# над C#, потребуется целая статья (кстати, хорошая идея для следующей статьи), поэтому давайте не будем останавливаться на этом вопросе сейчас. Тем более, никто не обязывает нас писать проект полностью на F#. Если в каких-то местах есть необходимость (или более выгодно) писать на C#, нам никто не запретит это сделать. Таким образом, можно использовать сильные стороны обоих языков программирования!

 

Основным языком программирования в движке Unity, как, думаю, многим должно быть известно, является C#. И, несмотря на то, что F# движком Unity официально не поддерживается, нам попадалась информация от одного из сотрудников Unity в твиттере о том, что у них есть тесты некоторой кодовой базы на F#.

Другими словами, не стоит бояться писать на F# под Unity, только из-за того, что что-то может не заработать или не скомпилиться, т.к. F# официально не поддерживается. Все-таки, и C# и F# работают поверх CLR и компилируются в промежуточное представление (IL), которое и выполняется либо Mono, либо компилируется в нативный код посредством IL2CPP. Таким образом, для Unity, теоретически, абсолютно не важно, на каком языке вы будете писать.


Настройку проекта мы будем выполнять в Windows. У нас установлена Unity версии 2019.1.8f1, но, думаю, может подойти и чуть более старая версия. Само собой, это также должно сработать и на более новых версиях Unity. В качестве IDE мы будем использовать IDE от JetBrains — Rider. По идее, нет особой разницы, какую IDE использовать, так что если у вас Visual Studio, то все описанные действия можно адаптировать и под нее.

 

Создаем новый Unity проект (пускай он будет называться FSharpUnityProject).

Далее создаем папку Scripts внутри папки Assets, после чего создаем тестовый скрипт на C# (TestScript) и открываем его в Rider-е.

Далее, в папке основного проекта создаем подпапку для проекта на F# — FSharpLib. Затем из Rider-а создаем новый F# проект типа .Net Core Class Library (.Net Core уже должен быть установлен на вашем компьютере; если это не так, то самое время исправить это досадное недоразумение) в этой папке с аналогичным именем. В качестве языка программирования указываем F#, а в качестве фреймворка —  .NetStandard2.0.

Далее из консоли (терминала), прямо не выходя из Rider-а, запускаем команду для сборки проекта:  dotnet publish . После успешной сборки проекта создаем папку  Assets/Libraries и копируем в нее из папки  FSharpLib\bin\Debug\netstandard2.0\publish файлы  FSharp.Core.dll (основная библиотека языка F#, без нее у нас не скомпилируется проект).

Теперь необходимо подключить Unity зависимости к нашей F# библиотеке. Для этого переходим к структуре проекта, выбираем Dependecies, затем выполняем  RMB -> Add Reference... -> Add From и добавляем C# библиотеку  Library/ScriptAssemblies/Assembly-CSharp.dll в качестве зависимости (не обязательный пункт; он нужен, чтобы мы могли обратиться к C# части проекта из F#). Теперь нужно подключить завимости от движка Unity из папки с установкой. В нашем случае это  C:\Program Files\Unity\Hub\Editor\2019.1.8f1\Editor\Data\Managed .

Выбираем все необходимые зависимости (можно выбрать все библиотеки). В нашем случае достаточно  UnityEngine.dll и UnityEngine\UnityEngine.CoreModule.dll .

 

Теперь давайте создадим наш первый Unity скрипт на F#. Для этого переключаемся обратно в Rider в проект с библиотекой и пишем вместо уже имеющегося примерно следующий код:

Сохраняем и пересобираем проект  Build -> Build Solution . Затем переходим в папку  FSharpLib\bin\Debug\netstandard2.0  и копируем следующие файлы:  FSharpLib.dll (библиотека с кодом выше) и  FSharpLib.pdb (файл с отладочной информацией, чтобы можно было подключиться с дебаггером; необязательный шаг) в папку Libraries . Переходим в Unity, создаем пустой игровой объект на сцене, вешаем скрипт  HelloWorldScript  на него и запускаем проект. В консоли должна показаться заветная фраза. Поздравляю! Нам удалось подружить Unity с F#.

 

Для примера взаимодействия с C# частью проекта давайте изменим тестовый скрипт следующим образом:

Вызовем новый метод на стороне F#:

Сохраняем, пересобираем, снова копируем и запускаем:

 

Копировать файлы после пересборки проекта вручную довольно утомительно и ошибкоопасно. Поэтому стоит этот момент автоматизировать. К сожалению, в отличие от Visual Studio, в Rider-е нет возможности настроить действия после сборки приложения прямо из пользовательского интерфейса. Но не беда, мы можем это сделать вручную. Для этого открываем файл проекта библиотеки  FSharpLib\FSharpLib.fsproj в блокноте и добавляем следующие строки:

Благодаря этому при каждой пересборке проекта автоматически будут скопированы файл библиотеки и отладочный файл.

 

Таким образом, мы не только подружили Unity и F#, наладили взаимодействие между C# и F#, но и автоматизировали часть процесса сборки. В общем, потрудились на славу. Полный исходный код проекта можно скачать здесь. Если есть какие-то вопросы, то милости просим в комментарии к этой статье. Всем спасибо за внимание и до скорых встреч!

Добавить комментарий