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