Как мне преобразовать строку в исполняемый код? (в Unity)

#c# #unity3d #scripting #compilation

#c# #unity-игровой движок #написание сценариев #Сборник

Вопрос:

Я создаю небольшую игру в Unity и прямо сейчас пытаюсь создать систему квестов. Эта игра будет симуляцией, поэтому квестам придется взаимодействовать с огромным количеством различных классов данных / систем. Я могу просто создать кучу служебных классов… или даже создать поддельную «базу данных» для обработки вызовов данных… но это неэлегантно.

Наверняка должен быть способ, с помощью которого я мог бы просто обозначать фактический код из строки?

Пример:

 String questText = Hello player.getFullName();, how are you?

questResults<String>[1] = player.inventory.add(GameObjectBuilder.Create(new WhateverObject()));
  

Я использую Unity ScriptableObject для создания заданий, чтобы я мог заполнять текстовые данные через редактор, а не делать это на стороне IDE (тем более, что unity, насколько я знаю, не поддерживает интерполированные и составные строки).

Я знаю, что в Java есть API под названием «Reflection», который, насколько я понимаю, делает что-то подобное, но я никогда не мог полностью обмозговать это.

Итак, как мне преобразовать элементы из строки в исполняемый код?

Если это возможно, не вызовет ли это проблем с предварительной обработкой с неопределенным количеством объектов, которые могут сталкиваться со сценариями, которые необходимо преобразовать?

Существуют ли какие-либо другие альтернативные методы, которые достигают аналогичной цели? (это просто любопытство)

Комментарии:

1. вы пробовали CSharpCodeProvider , его разработка происходит быстрее, чем рефлексия.

2. @LeiYang Я даже не до конца уверен, что Reflection — это та технология, которая мне нужна в этом случае, вероятно, мне просто не следовало упоминать об этом. Позволяет ли мне CSharpCodeProvider превращать C #, обнаруженный в строке, в реальный процесс выполнения? Если да, то функционирует ли это с unity?

3. это работает в C #. пожалуйста, сначала прочтите документ и проведите несколько экспериментов.

4. Хорошо, просто чтобы убедиться, что я понимаю, как работает CSharpCodeProvider… так ли будет проходить процесс: GameEngine [ обнаруживает код] -> GameParsingEngine [ записывает код в исходный файл] -> CSharpCodeProvider [ Компилирует и запускает код в игре]?

5. я думаю, вам даже не нужно записывать строку в исходный файл. он компилируется в памяти во время выполнения, и IL может быть запущен.

Ответ №1:

В качестве альтернативного метода вы можете использовать ключевое слово, которое вы ищете и заменяете, вместо того, чтобы записывать фактический код непосредственно в вашу строку. Я бы предложил использовать этот подход, поскольку он понятнее для чтения и проще в обслуживании. Я использовал этот подход в похожей системе.

Это хорошо работает, если существует лишь небольшое количество возможностей, которые вам нужно будет разрешить (или вы не возражаете против добавления «обработчиков» для всех ключевых слов., вы можете включить в свой текст своего рода ключевое слово, которое вы можете пропустить через метод перед его использованием.

Например..

Hello {PLAYER_NAME}, how are you? — это исходная строка.

 public string ParseQuestText(string input)
{
    if(input.contains("{PLAYER_NAME}")
        input.Replace("{PLAYER_NAME}",player.getFullName());

    /Add other replacers here

    return input;
}
  

Комментарии:

1. Да, я думал о ключевом слове route на начальных этапах. Я разрабатываю будущую реализацию SQL, чтобы это могло работать как многопользовательская вещь… но это привело к осознанию того, что мне нужны команды обработки, а не просто запросы данных. Это привело к тому, что я потратил день на написание собственного языка сценариев, что позволило мне осознать степень детализации классов, которая возникла бы, если бы я попытался пойти этим путем. Игра представляет собой довольно углубленную бизнес-симуляцию на основе данных (в отличие от физики), поэтому в ней будет огромное количество различных классов, которым затем понадобятся служебные методы, подобные вашему.

2.Или string.format ("Hello {0}, how are you?", player.GetFullName()); learn.microsoft.com/en-us/dotnet/api /…

3. Извините, возможно, мне следует уточнить. string questText это поле, которое я задаю в редакторе Unity, а не прогроматически. Я также не хотел еще больше запутывать вопрос, но в квесте он на самом деле читался бы так: Hello, $player.getFullName();, how are you today? $ обозначает начало кода, вставленного в отображаемый текст, ; естественно, заканчивает его. У меня довольно простой дизайн для фактического разбора команд, это возможность динамически генерировать одноразовый класс для бесконечных пользовательских инструкций, которые понадобятся, а не миллион служебных классов.

4. Реально, сколько уникальных методов вам понадобится? Делаю это с помощью строки. Заменить было бы намного проще, чем то, что, похоже, вы хотите сделать, не говоря уже о том, что намного безопаснее (о чем я был бы обеспокоен, если бы вы когда-нибудь сделали этот контент «модифицируемым»).