Как в Годот сделать Level Script без написания сложного кода?
Например подходим к NPC и включается скрипт:Talk («Привет!»);
Talk («Вот тебе в подарок 1000$, просто так!»);
Money (+1000);
Как сделать так, чтобы в этом скрипте ставилось на паузу пока не закончится следующий диалог?
В юнити я использовал сложный код с text.Split (««), разбивал код на слова, может в годоте можно проще сделать?
- 13 октября 2019, 12:40
- 00
Короче в юнити я делал "парсер" на 2000 строк кода, мне кажется для Годота дожны быть более простые способы, но может я ошибаюсь и придётся тоже делать сложный скрипт.
Там скрипт дальше не читался, пока диалог, сцена или игра стоит на паузе, это то что мне и нужно от подобного кода.
Но так не хочется возиться с такими вещами, хотя бы в годоте.
Чет прям сложно. Если нужна просто задержка между двумя строчками кода, в юнити это без проблем делается корутиной.
По идее, похожим методом можно ждать нажатия кнопки (я не пробовал, но должно работать)
Спасибо) интересная идея, надо бы потестить с кнопками, а временной код не подходит)
тут какие то странные настройки функции, я особо в этом не понимаю
IEnumerator
,можно ли вставить это в обычный код типа Awake или Update?
например:
И ещё один вопрос, можно ли вставить вместо строки:
такую строку с переменной, ибо в диалоге может быть много параметров, которые не позволят сразу промотать текст:
На первый вопрос - нет, Awake\Update не могут ничего ждать (они должны выполниться за время одного кадра), но в Awake\Update можно выполнить
а в Dialog объявленной выше уже ждать.
На второй вопрос - да, можно ждать переменных.
Вот краткое описание: https://habr.com/ru/post/216185/
Спасибо! Я до этого корутины боялся использовать, ибо казалось, что с ними можно забыть про запущенную корутину, забыв её просто остановить например, или другие путаницы с такой необычной работой кода.
Где не совсем линейно идёт чтение кода и я начинаю слегка теряться в понимании кода.
Попробую разобраться с этим.
Сам побаиваюсь их использовать, там есть несколько тонких моментов и легко ошибиться и получить странные баги (например если разбить ее на функции то вызывать их надо будет через yield return, но при этом yield break во вложенных функциях работать не будет), но все-таки они красивее чем конечный автомат и если не слишком усложнять логику идеальны.
Гугл предлагает использовать моды и плагины чужие, но это значить, что если их поддержка прекратиться,
то придётся остаться на старых версиях годота, даже если там критические ошибки, так что лучше не стоит использовать чужое.
В Юнити есть какие-то Yield-инструкции для ожидания какого-то события. Всего 1 раз этим пользовался.
Может в Годоте есть что-то похожее.
А так вообще не понятно что именно ты хочешь сделать.
Просто поставь блокировку "если диалог еще не закончился - выходим из функции и не выполняем дальнейший код, через 1/10 секунды проверяем еще раз".
я Yield функции не до конца понимаю, мне кажется если удалить объект, то появятся ошибки,
или второй вариант например захочется досрочно остановить скрипт или удалить, как остановить этот Yield,
я видел много игр, где из-за Yield появляются какие-то баги, и если я перегружаю действиями игру, то эти все Yield-ы путаются, окна зависают в воздухе и прочая странная штука творится, и я хз, как правильно управлять таким сложным нелинейным процессом
Правильно кажется.
Прикол в том, что запущенная корутина никак не блокирует возможность внешнему коду удалить объект; для этого нужно в тех местах корутины, где происходит обращение к возможно-почившему-в-бозе объекту обернуть всё в проверки вида "а жив ли мальчик?". Ну и как правило, если мальчик уже скорее мёртв, чем жив, то корутина просто "
yield break
"-аектся.А как блокировку поставить?
Например как вспомнить на какой строке кода я остановился, чтоб туда вернуться?
Что именно тебе надо останавливать пока идет диалог?
Ставь лучше на паузу всю игру, кроме кода, управляющего диалогом. В начале Update проверяй - если диалог еще идет, то обновляем диалог и выходим. Тогда никакой код вообще кроме диалогового работать не будет.
А когда пауза снимется, как потом прочитать вторую строку кода?
Ведь на первой строке кода стоит то что уже было, значить надо как-то
перейти на вторую строку и начать с неё читать код, второй раз.
Talk («Привет!»);
Talk («Вот тебе в подарок 1000$, просто так!»);
Money (+1000);
Иначе игра просто зациклится на первом диалоге, и после снятия его, опять появится он же.
Короче, я все понял понял. Ты вообще все делаешь неправильно. Нафига ты мешаешь код и данные? Разбей свой диалог на список и храни только данные (название функции, перс1, перс2, текст, параметр).
А в коде уже переходи к след. элементу списка.
Вон, scorched тебе все правильно сказал.
Грубо говоря делаешь массив структур, где хранятся все необходимые данные и обрабатываешь их по одному.
Спасибо! Не думал под таким углом! Осталось только разобраться как подобный вызов писать.
Пойду гуглить.
Ещё бы можно было бы другие данные от кода отделить!
Например все переменные игры, у меня постоянно в коде торчат, не знаю как их оторвать от кода,
особенно в юнити, где не рекомендуют динамические переменные.
А то когда начинаешь собирать новую игру, то приходится долго очищать старые переменные с прошлого кода, чтоб по новой его использовать)
Например, перейти с классов на какое-нибудь ECS ?
Я раньше почти всё "типа в Entity" программировал, ну то есть на другом движке,
ну там все объекты работали от одного скрипта и это был BlitzMax, Tic-80 или Blitz3d,
но может быть в юнити эта система намного сложнее для понимания.
А в годоте вроде не слышал про ECS вообще.
Ну это парадигма для геймплейного кода, просто в юнитях недавно для неё стали делать встроенные решения и оптимизации.
Добавляй эти действия в массив-очередь (вызовом своих вот этих функций из поста), а потом "воспроизводи" эту очередь по порядку по щелчку мыши или как там у тебя
Спасибо!)
вызов функции через String? забыл как это делается)
надо загуглить, я кажется недавно видел, и может даже спрашивал, но уже забыл)
пока не попрактикуюсь с этим кодом, буду забывать)
надо срочно какой-нибудь мини код написать, чтоб в голове закрепилось)
Можно хранить указатель на функцию и параметры к ней.
В конце концов:
Чтобы ссылаться на функцию по имени во время выполнения (например, чтобы сохранить ее в переменной или передать ее другой функции в качестве аргумента), необходимо использовать помощники
call
илиfuncref
:Ну я имел в виду, что эти твои функции ничего не делают, кроме добавления себя в массив. А по щелчку достаёшь элемент из массива и смотришь, что там надо сделать, это можно обычным match.
В принципе, yield тоже есть в годоте, но я так пока и не придумал, где он мне нужен)
Задержка выполнения функции по таймеру. Для выстрелов
А зачем выстреливать потом с задержкой, если можно выстреливать сразу когда пора выстреливать?..
Эмитируя перезарядку
А в Годот есть yield не по времени, а по нажатию кнопки или изменению какой-то переменной?
то есть тупо код дальше не идёт, пока не нажата кнопка или не изменена переменная
Да есть
А yield можно использовать не по времени, а когда какая-нибудь особая переменная изменится?
тогда может быть много полезных применений, тот же скрипт с диалогом)
Я так понял, функция ставит сама себя на паузу на контрольных точках, а потом её можно продолжить, когда тебе удобно.
ещё бы понять как такие штуки отключать, если вдруг нужно сбросить Yield) пошёл гуглить, может там можно найти вариант
Далеко не уходи: https://docs.godotengine.org/ru/latest/getting_started/scripting/gdscript/gdscript_basics.html#coroutines-with-yield
О! Спасибо)
Еще пример:
Шикарно) Спасибо)
А можно точно такой же код написать, но вместо проверки анимации, была бы проверка переменной?
Например переменная у врага: robbed , то есть враг не исчезнет пока мы не ограбим его карманы, а как ограбим то
robbed = true;
и теперь можно было бы удалять врага, но только используя корутину, а не обычным методом,
хотелось бы глянуть на код корутины, где есть зависимость от переменной,
ибо в этих примерах, я вроде не нашёл подобное
https://docs.godotengine.org/ru/latest/getting_started/scripting/gdscript/gdscript_basics.html#coroutines-with-yield
Внутри класса только if. Если из другого класса, то в голову приходит только использование setget: https://docs.godotengine.org/ru/latest/getting_started/scripting/gdscript/gdscript_basics.html#setters-getters
Или сигналы.