Как я и думал, нашлось очень простое решение. Обобщённо оно выглядит так: нужно взять и использовать любой компилятор, который создаёт IL-код. Собственно, это всё. Компилятор транслирует исходный код, получается сборка .net, загрузив которую в тот же application domain, в котором выполняется дочернее приложение юнити (то есть наша игра), получим то, что и требовалось — натуральный, «живой» скриптинг.
Реализовать было чуть сложнее.
Сначала я хотел подружить юнити с немерлем. В плюсе то, что он опенсорсный и совершенно бесплатный, синтаксис похож на с#, ну и позволяет он выделывать всякое, что с# не умеет. А в минусе то, что он очень хреново документирован. Это — отсутствие документации — и решило исход: я от немерля отказался, раз решить задачу с наскока не удалось (это, конечно, не значит, что она в принципе не решаема, просто надо сидеть и курить исходники, а настроения на это не было).
Тогда я пошёл по пути наименьшего сопротивления: решил прикрутить то, с чем вообще не надо возиться. Поприсматривался сначала к s# (он хоть и открытый, и бесплатный, и синтаксис на с# похож, но не поддерживает ООП (правда, может притвориться, что поддерживает), а потом к c# script (это практический честный с#). Вот последний и прикрутил к юнити, причём буквально за полминуты. Серьёзно.
Допустим, есть у нас вот такой скрипт, расширяющий поведенческую реакцию какого-то объекта. Не важно, откуда он взялся: был ли получен по сети, взят с харда или вообще сгенерирован в рантайме — это совершенно по фигу, главное — код есть.
Используется csharp
using UnityEngine;
public class CSSBehaviourScript : MonoBehaviour
{
public void Update()
{
this.transform.Rotate(Vector3.up, 0.01f);
}
}
Тогда, чтобы использовать его в своей игре надо произвести следующие телодвижения. Во-первых, добавить DLL C# Script в свой проект (как я понимаю, в инди не сработает, хотя есть способ, но об этом ниже). Во-вторых, надо скомпилировать исходник. Сделать это можно, например, вот так:
Используется csharp
using UnityEngine;
using System.Reflection;
// Подключим библиотеку для использования C# Script'а
using CSScriptLibrary;
public class CSSBehaviourExtender : MonoBehaviour
{
public void SetBehaviour(string SourceCode)
{
if (SourceCode.Length > 0)
{
// Переданный в качестве параметра в функцию код компилируется
// в отдельную сборку, с которой уже можно работать хоть стандартными
// средствами System.Reflection, хоть средствами библиотеки C# Script'а,
// и она загружается автоматически в текущий application domain
Assembly assembly = CSScript.LoadCode(SourceCode, null);
// Получаем список типов, которые определены в сборке
System.Type[] types = assembly.GetTypes();
if (types.Length > 0)
{
// Допустим, первый попавшийся тип и есть наследник монобеха,
// соответственно ему и лезть на объект
this.gameObject.AddComponent(types[0]);
}
}
}
}
Этот код висит на объекте, поведение которого необходимо изменить полученным скриптом. Для изменения необходимо вызвать единственный метод SetBehaviour(), который я описал, и в качестве параметра передать ему строку, содержащую исходный код скрипта. Для работы в реальных условиях, конечно, не помешало бы добавить дополнительных проверок (так, компиляция может завершиться с ошибкой, в этом случае C# Script бросит исключение) и поменять принцип добавления (скажем, делать это сразу для множества объектов и при загрузке очередного уровня). Но в качестве примера допустимо и так. Главное, что этот код компилируется и работает. Тестовый скрипт тоже компилируется (уже в рантайме), добавляется на объект как компонент и прекрасно работает. Задача решена.
Вот в билде под веб C# Script юнити почему-то зарезала. Но приятная новость, что он распространяется в том числе и в исходниках, то есть потенциально скриптинг доступен и в вебе (а также для инди-версии). Но, думаю, уже с этим будут некоторые сложности: там лицензия изменения в исходном коде чётко оговаривает — нельзя. Взять C# Script можно
здесь. Он, кстати, поддерживает не только c# синтаксис и прекрасно документирован. Разработчик — Олег Шило.
В общем, для себя я решил. Неплохой вариант, пока немерль к юнити не прикручу.