Это копия, сохраненная 13 декабря 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
С изучения документации. Если не можешь в инглиш, и даже в гугл-переводчик, то продолжается перевод официальной документации: https://docs.godotengine.org/ru/latest/
Но вообще, будь мужиком и изучи английский: https://docs.godotengine.org/en/stable/
Вместе с движком обязательно смотри примеры, там есть всё - от платформера до чата. Примеры качаются прямо в движке через свой магазин.
Скачать движок: https://godotengine.org/download/ или http://store.steampowered.com/app/404790/Godot_Engine/
FAQ: https://docs.godotengine.org/ru/latest/about/faq.html
Игры, созданные глобальными кириллами: https://godotengine.org/showcase или https://steamcommunity.com/app/404790/discussions/0/412448792354265655/
Скажи "Годот круто!" https://github.com/Calinou/awesome-godot - подборка дополнений, модулей и минишоукейс от одного из авторов.
Годнота от анона:
Видос в шапку: https://www.youtube.com/watch?v=BAsVI-Yv928
Для приверженцев опенсорца существует возможность распрострянять проекты в незапакованном формате. Просто скачай темплейт с оф.сайта и положи экзешник/эльфешник в папку с проектом, этого достаточно. Дополнительно можешь вшить свою иконку в экзешник. После этого, запустившийся файл темплейта обнаружит рядом с собой файл project.godot и начнет грузить проект из него и из файлов, лежащих в распакованном виде в той же директории.
В версии 3.2 появилась возможность прикреплять pck к бинарнику. Бриллиант для любителей однофайлового продукта!
Редактор персонажей на основе makehuman: https://github.com/Lexpartizan/Go_MakeHuman_dot
Все языки в одном месте: https://vk.com/topic-70467171_35982467
Тест-бенчмарк:
Веб-версия - https://govdot.herokuapp.com
Вишмастер для винды - https://govdot.herokuapp.com/4Anon.rar
Предыдущий тонет там: >>658384 (OP)
Архивы:
1 https://arhivach.ng/thread/207802/
2 https://arhivach.ng/thread/388500/
3 https://arhivach.ng/thread/388501/
4 https://arhivach.ng/thread/388502/
5 https://arhivach.ng/thread/388503/
6 https://arhivach.ng/thread/432708/
7 https://arhivach.ng/thread/433902/
8 https://arhivach.ng/thread/436355/
9 https://arhivach.ng/thread/455461/
10 https://arhivach.ng/thread/479963/
11 https://arhivach.ng/thread/489815/
12 https://arhivach.ng/thread/494513/
13 https://arhivach.ng/thread/515567/
14 https://arhivach.ng/thread/533171/
15 https://arhivach.ng/thread/555441/
https://www.youtube.com/watch?v=8yI05GVuQck
Что может быть сложного в реализации доджгейм, что тебе нужны туториалы? Давай я текстом обесню. Задавай свои ответы, пока кочается.
Поддерживаю.
>Что может быть сложного в реализации доджгейм, что тебе нужны туториалы?
>базовый туториал "dodge game"
Он про это - https://docs.godotengine.org/en/stable/getting_started/step_by_step/your_first_game.html
Этот туториал по факту нужен не для "реализации доджгейм", а для знакомства с интерфейсом движка и стандартным воркфлоу. Текстом ты ему никак нормально не объяснишь, там в туториале картиночками показано что куда тыкать и чего что означает. Это для вкатывающихся в движок, очевидно же.
А сложного... наверное, ему мотивации не хватает пройти туториал до конца)
Ну тогда поддерживаю, хуле.
https://github.com/BenediktMagnus/godot-object-pascal
зочем
Некоторые просто не могут смириться с тем, что некоторые языки протухают со временем.
> Массивы вседа по ссылке
Я перепутал Array который по ссылке и PoolIntArray который по значению. И в тот раз и в этот.
Заходил в годот-тред год назад. Хотел платформер прыгалку на годоте пилить для ведра, но были проблемы с оптимизацией и отрисовкой сплайнов вроде. Проблема схоронилась?
Сплайны всегда шли без тормозов. Чему там тормозить? Я два года назад видал туториал по созданию в годо гоночной игры, в котором дорога генерировалась по сплайну.
>>72334
>Тайлмапы тормозили
Не знаю насчет сплайнов, но если использовать бету 3.2.2 с батчингом, то с тайлмапами стало значительно лучше применительно к пиксельным 2Д проектам.
Количество drawcall-ов упало значительно, если без батчинга их было где-то 300-500 и более для одного тайлмапа, то с батчингом для той же карты получается менее 30.
На винде показывает стабильные 60FPS даже если напихать туда кучу параллаксов и всяких динамических шейдеров (вроде воды или тумана).
На Html5 тоже спокойно вывозит 60FPS, правда при условии если сделать целочисленное масштабирование картинки (придется повозиться с шаблоном экспорта для fixed_size). Тормоза только первые секунд 5 при после загрузки проекта.
На андроиде при стретчинге Viewport то же идет в 60FPS с редкими проседаниями на несколько кадров, при 2Д-стретчинге, похуже где-то 50-55FPS.
Но в принципе можно выставить target fps в 30 и будет все стабильно и без рывков.
Честно говоря я в принципе не уверен, что на андроиде можно достичь стабильных 60FPS, т.к. еще ни разу не видел игрухи в которой они были. Либо все залочено до 30-40 кадров, либо плавает в районе 50-60. Возможно это особенность андроида я хз. Я не нашел пока подробной информации по тому как устроен рендер на андроиде (да и не искал особо, т.к. не в приоритете)
-----
Это я все на своих устройствах тестировал.
И плюс еще я переписал весь код с GDScript'а на C#
>Спасибо, скачаю бету попробую
Только будь готов к небольшим багам. Ничего критичного, но при переходе со стабильной 3.2 пару раз пришлось в конфиг проекта руками залезть и поправить параметры вручную, чтобы убрать ворнинги.
>>72349
>И плюс еще я переписал весь код с GDScript'а на C#
Добавлю, что после месяца работы с C# хрен я теперь вернусь на GDScript. Надеюсь в будущем разрабы годота, откажутся от этого питухоноподобного языка и сделают решетки основным.
> Надеюсь в будущем разрабы годота, откажутся от этого питухоноподобного языка и сделают решетки основным.
И вот бы ещё компиляцию в нативный бинарник завезли бы, наподобие il2cpp.
>If you want to use AOT, then you have to build the AOT Compiler yourself:
Тащем-та поддержка AOT в годоте уже есть, только не работает из коробки, надо самому компилятор собирать. Собственно это была одна из задач которую запросили Майкрософт, когда спонсировали чувака который поддержку C# в годот пилит. Я так понимаю сначала доделают экспорт на обмылки, а потом уже займутся плотно AOT-компиляцией.
Я все думаю как-нибудь собрать, только лень. Не горит и есть более интересные задачи.
Обоже! Изумительно!
>Количество drawcall-ов упало значительно, если без батчинга их было где-то 300-500 и более для одного тайлмапа, то с батчингом для той же карты получается менее 30.
Небольшое уточнение. Сейчас попробовал еще раз на этом же проекте.
При включенном батчинге приблизительно 30 дровколов.
Когда отключил батчинг, то получил где-то 2500 дровколов с небольшими проседаниями FPS. Сначала не мог понять, что за фигня, а потом допер. Я сделал себе анимированную текстурку воды спрайтом 32x32 и растягивал ее методом tile.
Получается когда батчинг включен, то она вся рисуется одним дровколом и все ок. При отключенном батчинге, на каждый участок этой текстуры будет отдельный вызов рисовки, т.к. она будет считаться не единой текстурой, а кучей отдельных спрайтов.
Вот как-то так. Юзайте бету с батчингом.
Сделал зеркало по гайду: https://www.youtube.com/watch?v=xXUVP6sN-tQ
Но оно не показывает тени. Про тени в гайде ничего не говорят, а сам я не знаю как сделать.
А ещё я добавил обрезку виртуальной камере, чтобы зеркала не захватывали объекты позади себя:
> fake_cam.near = fake_cam.global_transform.origin.distance_to(global_transform.origin)
Однако есть один нюанс. Он отображён на пикче. Near рассчитан для центра поверхности и не учитывает углы.
А ещё я пытался поставить два зеркала друг против друга, чтобы увидеть эффект бесконечного туннеля, но увидел только хуй.
Неужели без рейтрейсинга не удастся сделоть игру мечты?
Памахити!
Анон ну какие зеркала тебе, это продвинутые техники которые даже в ааа играх не делают.
Ну почему в 90х могли в зеркала, а щас продвинутые техники?
Я согласен на упрощённый шейдинг, ладно, но как насчёт переотражений?
Вот с этой точки должен быть виден бесконечный туннель. Но мы видим, что на втором переотражении эффект зеркала обрывается. Потому что нет никакого переотражения, ахаха (мем с бородой). Потому что зеркало это вьюпорт-текстура. Получается, мне нужно вручную рассчитывать ход лучей, то есть выполнить программный рейтрейсинг?
Переотражения нужны для геймплея.
Ну какие еще переотражения в 90-х, чел
Так это вроде просто рекурсией делается. Просто рисуешь вьюпорт во вьюпорт.
А там точно зеркало, а не ещё одна комната с синхронно двигающимся персонажем за прозрачной стеной?
Бинго. И тем более никаких теней, даже в версии 2011 года.
Там просто копии комнат были в которых клон игрока бегает. Плюс там вообще все враги и гг спрайтами рисовались.
Нет.
tool
extends AnimatedSprite
class_name door
onready var Collider = $Collider #это статикбоди, блокирующий проход
export(bool) var Open_To_the_left setget Set_Dir
func Set_Dir(dir: bool):
_ Open_To_The_Left = dir
_ flip_h = dir
_ if dir: Collider.position.x = 70 # пишет в консоли: Invalid get index 'position' (on base: 'Nil').
_ else: Collider.position.x = -70 # пишет в консоли: Invalid get index 'position' (on base: 'Nil').
Косяки капитализации букв здесь есть, но они возникли при переписывании текста для поста. В коде все имена верные, заглавные и строчные буквы на своих местах.
Кэп, ты?
В общем, проблема более-менее ясна. На момент срабатывания сетгета дети ещё не инициализированы. То же самое происходит в режиме редактора. Значит надо работать с ними уже после ready.
Как при этом их изменять (да хотя бы двигать) в режиме tool - чёт не понимаю.
Для тул-режима в гдскрипте есть специальные флаги. Не помню какие, гугли. В общем и целом логика такова:
иф тулмод:
_ код тулмода
ельз:
_ код рантайма
Это такие нулевые, что ещё девяностые.
Если ты чего-то не понимаешь - иди в гугл и учи матчасть, пока не поймёшь. Мне за твоё образование твоя мамка не платила.
Сам ты даун, пидрблять, шавка.
и вот эту мастхэв фигню они запихнут только в следующей версии? офигеть.. не ну я за развитие годо, но надеюсь подобные штуки будут в приоритете
Я сначала, собственно и дропнул годот из-за отсутствия батчинга, т.к. производительность по итогу была в жопе. Когда вышел 3.2.2 бета с батчингом, решил сделать второй заход. Пока полет нормальный.
>прочитал вопрос жопой
>ответил тараканам в своей голове
>ТЫ НЕ ПОНИМАЕШЬ УЧИ МАТЧАСТЬ
Классика.
Тащемта решение нашлось. Вот это:
onready var foo = $foo
func bar():
print(foo)
выдаст null, если функция вызывается до готовности или в режиме tool. Зато вот это:
func bar():
print($foo)
работает всегда. Видимо, для большей стабильности в идеале надо делать как-то так:
var foo
func bar():
foo = $foo
if foo != null:
print(foo)
Это, с одной стороны, даст какую-то страховку от непредсказуемых ситуаций, а с другой всё же позволит работать в режиме tool и влиять на потомков до готовности.
И всё же я вот чего не понимаю. Если потомки всё же доступны, то почему в годот вшито требование, чтобы переменные, которые сразу принимают ссылку на них в качестве значения, были обязательно onready? Защита от "выстрела в ногу"? Потому что как-то костыльно приходится её обходить, когда это нужно.
Через сишарп только если. Мне через сишарп удавалось даже внешние окна выводить. Трей там тоже не проблема.
>И всё же я вот чего не понимаю
И все же чекай мануалы:
>https://docs.godotengine.org/en/stable/getting_started/step_by_step/scripting.html
>The _ready() function is called when the node, and all its children, enters the active scene.
Если на пальцах, то _ready() выполняется только 1 раз когда ты открываешь сцену, либо когда кидаешь ноду со скриптом в текущую сцену.
Все остальное время _ready, а так же _enter_tree не выполняется.
Выходов у тебя несколько:
1) После каждого изменения tool скрипта, закрывать и открывать сцену (это еще лайтово, в версии 2 приходилось весь редактор перезагружать)
2) В tool скрипте где нибудь в _process, написать следующее:
_ if Engine.editor_hint:
_ _ if Input.is_action_pressed("ui_cancel"):
_ _ _ _ready()
и после каждого изменения скрипта и сохранения нажимешь Esc и у тебя будет напрямую вызываться функция _ready где переменные уже будут правильно инициализироваться (к сожалению подвесить можно только дефолтные ui action'ы, новые почему-то не цепляются)
3) Твой способ. Инициализировать их по факту по необходимости в _process
------
Народ в свое время уже просил в трекере сделать горячую перезагрузку tool скриптов, но видать до сих пор не сделали.
О, спасибо, анон. Ты говорил не про то, чего я не понял, но случайно задел другой важный момент. Для меня было не вполне очевидно, когда именно вызывается ready в режиме редактора и когда обновляются ноды. И этого в мануалах как раз не уточняется. Про режим запуска всё понятно, но про режим tool там совсем скудно написано, не раскрываются такие вот важные детали. Я эту статейку уже почти наизусть выучил.
Проблема, похоже, уже людям встречалась, решения так и не нашли: https://github.com/godotengine/godot/issues/34098 - аноны костылили юпитерианскую гравитацию, чтобы обмануть баг.
Мой костыль: небольшие зоны, запрещающие движение вверх, если персонаж в воздухе и не нажат прыжок. Пришлось дополнительно добавить галку, чтобы разделить направление влево и вправо. Теперь у меня персонаж поднимается по лестницам нормально, а спускается как школьник, прыгая с верхней ступеньки.
Хе-хе.
Я вот когда переходил на годот с движка в котором были пиксельные коллизии, сильно поразился насколько геморойно делается кинематика в движках с полигональными коллизиями (по сравнению с пикселями)
С учетом многодневного дрочева со всякими move_and_slide, with_snap, collision_shapes и т.д. Я уяснил для себя такую вещь:
Нахуй все виды коллижен шейпов, кроме AABB. Вот серьезно, все остальное вроде капсул, рейшепов и т.д. - говно без задач. Максимум что можно еще использовать это круг, для каких-нибудь мячиков, но и для них тоже часто можно использовать прямоугольник.
С дедовским прямоугольником большинство замороченных случаев решается легко и быстро. Для остального можно добавить рейкастов в нужных местах и поиграться со скоростями (old/current). Ну и естественно геометрию уровня нужно лепить продуманно, чтобы не было мест, неучтенных для кинематики.
------
(все вышенаписанное относится к 2Д, но сколько я не смотрел туториалов где пилили кинематику в 3Д, проблемы там часто те же самые и сдается мне, что решить их можно теми же способами)
-------
Забыл визуализатор скорости включить.
А всё остальное, кстати говоря, именно из таких как у тебя размышлений и родилось дидами:
> Максимум что можно еще использовать это круг, для каких-нибудь мячиков
> Максимум что можно еще использовать это капсуль, для каких-нибудь персов
> Максимум что можно еще использовать это полигон, для каких-нибудь уровней
Вот так диды и предали ААББ.
>Вот так диды и предали ААББ.
Тащемта, деды в свео время и прадедов, которые коллизии по цветам определяли, предали. :)
Кстате да.
>Нахуй все виды коллижен шейпов, кроме AABB
Для пиксельного платформера - может быть. А когда нужно обрабатывать коллизии пуль, вот тут уже полтора пикселя на уголках капсулы имеют значение.
У меня сейчас некоторые физические объекты недостаточно реалистично себя ведут из-за слишком простых форм форм коллизии (полигонами). Падают на самую длинную сторону и не катятся, как их ни пинай, только взрывом снизу вверх получается подцепить. Круглые коллизии нормально катятся.
Не увидел у тебя на пиках визуализатор скорости. Если эти гифки должны анимироваться, то у них это не вышло. Но ты про него сказал, и я почувствовал ужасный стыд, что не сделал раньше такую простую вещь.
Благодаря визуализатору выяснил странность поведения move_and_slide_with_snap по сравнению с move_and_slide. Оказалось, что он не обнуляет вертикальную скорость при нахождении на полу, а просто нипутяет. То есть, после хорошенького разбега по лестнице и остановки на ровной поверхности наблюдается воооот такенный вектор скорости, направленный вертикально вверх, который сбрасывается прыжком в тот момент, когда персонаж достигает края.
Собрал тестовый проект. Баг воспроизводится. Попробовал с прямоугольным коллижен шейпом. Ничего не изменилось. Опытным путём удалось выяснить несколько особенностей:
1. При движении вверх при переходе с более крутой поверхности на более пологую или полностью горизонтальную вертикальная компонента сохраняется, хотя персонаж всё ещё прилипает.
2. Если подойти к краю, прилипать становится не к чему, и персонаж взлетает.
3. Краем считается не только вертикальный обрыв, но и крутой склон.
4. Если набрать скорость на крутом склоне и резко остановиться, то наступит тоже резкий сброс и прыжок.
5. Крутым склоном считается любой круче, чем Vector2(4, 3).
А ещё я обнаружил, что получить нормаль к коллизии при move_and_slide(и _with_snap тоже ) - та ещё задачка. Горизонтальные поверхности коллизий вообще не дают. Пологие склоны дают только изредка и только при вижении вверх. Крутые склоны дают полноценную коллизию при движении вверх; для угла в 45 градусов нормаль колеблется в диапазоне от 0.705 до 0.709 (по обеим осям). При движении вниз коллизий нет.
Попробовал написать фикс, основанный на ареах, срабатывающий по выходу из области. И случилось странное: body_entered и body_exited не срабатывают, пока действует прилипание к поверхности. В воздухе - пожалуйста. Я бы подумал, что это мой косяк, если бы он происходил не в пустом проекте, где полторы строчки кода.
Сейчас разработал такой вариант. У меня же есть луч, сканирующий поверхность, который смотрит строго вниз. Соответственно, с поверхностями он сталкивается под вполне определёнными углами. Это можно использовать для того, чтобы гасить лишний взлёт над горизонтальными поверхностями. Правда, "школьный" стиль спуска всё равно останется, потому что для снапа поверхность в 45 градусов (все мои лестницы) это отвесный обрыв, так что придётся дополнительно корректировать и над лестницами.
Но я устал и пойду спать. Весь день убил на поиск решения.
>Нахуй все виды коллижен шейпов, кроме AABB
Для пиксельного платформера - может быть. А когда нужно обрабатывать коллизии пуль, вот тут уже полтора пикселя на уголках капсулы имеют значение.
У меня сейчас некоторые физические объекты недостаточно реалистично себя ведут из-за слишком простых форм форм коллизии (полигонами). Падают на самую длинную сторону и не катятся, как их ни пинай, только взрывом снизу вверх получается подцепить. Круглые коллизии нормально катятся.
Не увидел у тебя на пиках визуализатор скорости. Если эти гифки должны анимироваться, то у них это не вышло. Но ты про него сказал, и я почувствовал ужасный стыд, что не сделал раньше такую простую вещь.
Благодаря визуализатору выяснил странность поведения move_and_slide_with_snap по сравнению с move_and_slide. Оказалось, что он не обнуляет вертикальную скорость при нахождении на полу, а просто нипутяет. То есть, после хорошенького разбега по лестнице и остановки на ровной поверхности наблюдается воооот такенный вектор скорости, направленный вертикально вверх, который сбрасывается прыжком в тот момент, когда персонаж достигает края.
Собрал тестовый проект. Баг воспроизводится. Попробовал с прямоугольным коллижен шейпом. Ничего не изменилось. Опытным путём удалось выяснить несколько особенностей:
1. При движении вверх при переходе с более крутой поверхности на более пологую или полностью горизонтальную вертикальная компонента сохраняется, хотя персонаж всё ещё прилипает.
2. Если подойти к краю, прилипать становится не к чему, и персонаж взлетает.
3. Краем считается не только вертикальный обрыв, но и крутой склон.
4. Если набрать скорость на крутом склоне и резко остановиться, то наступит тоже резкий сброс и прыжок.
5. Крутым склоном считается любой круче, чем Vector2(4, 3).
А ещё я обнаружил, что получить нормаль к коллизии при move_and_slide(и _with_snap тоже ) - та ещё задачка. Горизонтальные поверхности коллизий вообще не дают. Пологие склоны дают только изредка и только при вижении вверх. Крутые склоны дают полноценную коллизию при движении вверх; для угла в 45 градусов нормаль колеблется в диапазоне от 0.705 до 0.709 (по обеим осям). При движении вниз коллизий нет.
Попробовал написать фикс, основанный на ареах, срабатывающий по выходу из области. И случилось странное: body_entered и body_exited не срабатывают, пока действует прилипание к поверхности. В воздухе - пожалуйста. Я бы подумал, что это мой косяк, если бы он происходил не в пустом проекте, где полторы строчки кода.
Сейчас разработал такой вариант. У меня же есть луч, сканирующий поверхность, который смотрит строго вниз. Соответственно, с поверхностями он сталкивается под вполне определёнными углами. Это можно использовать для того, чтобы гасить лишний взлёт над горизонтальными поверхностями. Правда, "школьный" стиль спуска всё равно останется, потому что для снапа поверхность в 45 градусов (все мои лестницы) это отвесный обрыв, так что придётся дополнительно корректировать и над лестницами.
Но я устал и пойду спать. Весь день убил на поиск решения.
Может быть ты уже перестанешь программировать методом тыка и почитаешь документацию? В частности, что такое параметр floor_max_angle у move_and_slide_with_snap
Не поверишь, до дыр зачитал. Ты один тут такой невнимательный. Речь идёт про обход бага в движке, ссылка на багрепорт выше.
И да, floor_max_angle не влияет на снап. Это тот угол, на который можно взобраться не соскальзывая.
Я для своей недавней игоры спиздил взял вот этот код и основательно его пофиксил
https://www.reddit.com/r/godot/comments/b6a6x0/move_and_slide_with_snap_is_consistently/
И всё работает так, как мне надо. Не совсем понимаю, на что конкретно там чувак жаловался, ибо не силён в инглише. Я убрал большую часть флагов из его кода, заменив стейтами стейтмашины.
мимо
Похоже, он, в свою очередь, спиздил взял код у GameEndeavor'а.
>Не совсем понимаю, на что конкретно там чувак жаловался, ибо не силён в инглише.
Тащемта,
а) если ты не понял, на что он жалуется, зачем сюда это постишь?
б) очень странно, что у него "seems to have fixed it", потому что у меня тоже там угол в 90 градусов, только записан как PI/2.
Сейчас рабочее решение такое.
if old_normal != ground_check.get_collision_normal():#ground_check это луч, прощупывающий почву
_ old_normal = ground_check.get_collision_normal()
_ velocity.y = 0
Всё это в блоке "не во время прыжка или падения", ессно.
Такой ход усмиряет выросший игрек, когда персонаж уже забрался на самый верх. "Школьный спуск" устраняется благодаря снапу.
Но осталась проблема при подъёме на склон: игрек всё равно накапливается, и персонаж подпрыгнет сразу же, если остановиться. Для решения этой проблемы пришлось добавить ещё костыль:
if ground_check.get_collision_normal() != Vector2(0, -1) and velocity.y < 0:
_ if velocity.x > 0: velocity = Vector2(velocity.length(), 0).rotated(-PI/4)
_ else: velocity = Vector2(velocity.length(), 0).rotated(-PI*3/4)
На тестовом проекте работает идеально. С рабочим возникли трудности, теперь уж точно до утра. Лёг спать, а мысли не давали уснуть, пока есть варианты решения задачи.
Утро вечера мудренее. Щас как проснёшься, как выпьешь кофе, да как решишь проблему простым и элегантным способом.
848x480, 0:36
>Для пиксельного платформера - может быть.
Можно подумать какие-то другие нужны
>А когда нужно обрабатывать коллизии пуль, вот тут уже полтора пикселя на уголках капсулы имеют значение.
Чет, так себе аргумент. Если так важна точность попадания, делай отдельных хитбокс персонажу, для расчетов попаданий. Для любого передвижения чем проще форма, тем лучше.>>73521
>Не увидел у тебя на пиках визуализатор скорости. Если эти гифки должны анимироваться, то у них это не вышло.
Х.з. почему так, на вот тогда видео.
>Благодаря визуализатору выяснил странность поведения move_and_slide_with_snap по сравнению с move_and_slide. Оказалось, что он не обнуляет вертикальную скорость при нахождении на полу, а просто нипутяет.
Я даже х.з. что посоветовать. Вообще выглядит как косяк стейт машины, либо неправильно скорость устанавливается. Я х.з., я уже давно экспериментировал с move_and_slide и with_snap. Помню что долго возился, но в итоге пришел к таким параметрам:
velocityNow = MoveAndSlideWithSnap(velocityNow, snap, FLOOR, true, 4, FLOOR_MAX_ANGLE);
snap = Vector2(0,8) (когда на полу)
FLOOR - Vector2(0, -1)
параметр max_slides = 4, опытным путем подобрал. При меньших значениях он начинает цепляться за наклонные поверхности и стыки между полигонами, при больших тоже какие-то проблемы возникают.
FLOOR_MAX_ANGLE = deg2rad(46) (планируется, что наклон 45 градусов, максимум на который игрок может заходить свободно.)
>Попробовал написать фикс, основанный на ареах, срабатывающий по выходу из области. И случилось странное: body_entered и body_exited не срабатывают, пока действует прилипание к поверхности. В воздухе - пожалуйста. Я бы подумал, что это мой косяк, если бы он происходил не в пустом проекте, где полторы строчки кода.
Что-то все тобой написанное как-то совсем дико звучит. Может быть скинешь полупустой проект, чтобы это можно было увидеть.
Какую стейт машину? Проблема воспроизводится в ПУСТОМ проекте. В нём же и исправляется. Потом лечение переносится в рабочий проект.
Кстати. https://dropmefiles.com/Btqug - вот и он, тестовый проект со снапфиксом. Но параллельно возникают другие, менее критичные проблемы:
1. На склонах различная скорость спуска в зависимости от того, забрался персонаж на вершину или нет.
2. На склонах менее 45 градусов скорость несколько отличается от ожидаемой, потому что для фикса любой склон должен быть 45 градусов.
3. На склонах более 45 градусов фикс не работает, потому что луч до них не достаёт. Впрочем, можно его удлиннить.
4. Иногда при какой-то хитрой комбинации прыжка, движения и наклона поверхности возникает ситуация залипания, когда персонаж постепенно выталкивается из земли на высоту прощупывающего луча.
Чувак...
>Какую стейт машину? Проблема воспроизводится в ПУСТОМ проекте. В нём же и исправляется. Потом лечение переносится в рабочий проект.
Блин, ну ебана.
Хочешь я тебе навангую, что выйдет в итоге? Ты будешь на каждый чих дописывать соответствующий фикс физики. Цеплять на перса дополнительные рейкасты или ареа, чтобы с помощью них высчитывать разные столкновения и т.д. В итоге у тебя основной игровой цикл разрастется до неприличных размеров, и ты просто перестанешь в нем разбираться. А любое малейшее изменение будет рушить все. Плюс с учетом тугодумности ГДскрипта, ты немаловероятно можешь перестать укладываться в один фрейм для рассчета физики персонажа (особенно когда мобов поднакидаешь или захочешь на 120фпс перейти).
-------
Если вкратце.
У персонажа есть несколько состояний: IDLE, WALK, JUMP, FALL и т.д. В один момент времени персонаж может находится в одном состоянии.
Так же у персонажа есть кучка флагов, которые обозначают различные его состоянии. Например onGround, onLadder, inWater и т.д. Плюс key флаги - управляющие сигналы, которые посылает пользователь с клавиатуры или AI персонажа (если это NPC к примеру).
Далее отдельный метод (например StateMaster) чекает эти флаги и в зависимости от их комбинаций переходит в нужное состояние или апдейтит текущее. Например: из IDLE в WALK перс переходит если onGround == true, onWater == false, onLadder == похуй, keyX !=0 и keY != -1. А из IDLE в JUMP все то же самое кроме keyX == похуй и keyY == -1.
Для каждого состояния есть методы EnterState и UpdateState. Например EnterIdle или UpdateWalk. (есть еще ExitState, но о них я сейчас не буду, т.к. у тебя голова взорвется и по началу можно и без них обойтись)
При входе в состояние, уставанливается вектор скорости (он же наш желаемый вектор движения), различные переменные (к примеру обнуляется snap при входе в прыжок, и он же восстанавливается при входе в Idle), переключается анимация и т.д.
В апдейте состояния ты делаешь по сути то же самое. Контролишь скорость (например при падении, чтобы не превышала какое-то значение), меняешь направление и т.д.
Физика и коллизии внутри стейтов не проверяются. Только внутренние параметры самого объекта (скорость, флаги и т.д.)
Гравитация (изменение вертикальной составляющей скорости) так же делается в Enter и Update стейтов (естественно там где она нужна)
Теперь сам физический цикл:
1) Проверка ввода и установка key флагов
2) Установка/апдейт состояния (StateMaster)
3) Движение
4) Проверка коллизий.
По первым двум пунктам я уже расписал.
Пункт 3 движение. Тут все просто Velocity = move_and_slide_with_snap(velocity,....). Одна строка и все. Без всяких выборов. По факту если игрок находится в том стейте в котором он двигаться не должен, то velocity уже будет равна нулю и он не передвинется.
Пункт 4. Здесь происходит проверка коллизий и устанавливаются флаги персонажа. Например onGround, onLadder, onWater и т.д. которые по которым в следующем цикле будет определятся стейт персонажа. (собственно этот пункт можно делать в начале физического цикла, перед опросом инпута, но собственно похуй, т.к. цикл и так по кругу крутится, а коллизии все равно кешируются и делаются один раз за фрейм - дело вкуса)
------
Собственно все. И по факту это будет работать без всяких дополнительных костылей.
Важно только запомнить, что стейты устанавливаются только по состоянию флагов персонажа и скорости (коллизии в этом месте не проверяются)
Вектор скорости регулируется только в стейтах и нигде более, коллизии в стейтах не проверяются.
В блоке проверке коллизий, устанавливаются только флаги и все, скорость не трогается.
------
Дополнительно за гравитацию. Бывает, что ее рациональнее в отдельный метод вынести (например если подразумеваются зоны с разной гравитацией). Тогда ее можно применять не в стейтах, а в основном цикле сразу после установки/апдейта состояния (перед передвижением)
>Какую стейт машину? Проблема воспроизводится в ПУСТОМ проекте. В нём же и исправляется. Потом лечение переносится в рабочий проект.
Блин, ну ебана.
Хочешь я тебе навангую, что выйдет в итоге? Ты будешь на каждый чих дописывать соответствующий фикс физики. Цеплять на перса дополнительные рейкасты или ареа, чтобы с помощью них высчитывать разные столкновения и т.д. В итоге у тебя основной игровой цикл разрастется до неприличных размеров, и ты просто перестанешь в нем разбираться. А любое малейшее изменение будет рушить все. Плюс с учетом тугодумности ГДскрипта, ты немаловероятно можешь перестать укладываться в один фрейм для рассчета физики персонажа (особенно когда мобов поднакидаешь или захочешь на 120фпс перейти).
-------
Если вкратце.
У персонажа есть несколько состояний: IDLE, WALK, JUMP, FALL и т.д. В один момент времени персонаж может находится в одном состоянии.
Так же у персонажа есть кучка флагов, которые обозначают различные его состоянии. Например onGround, onLadder, inWater и т.д. Плюс key флаги - управляющие сигналы, которые посылает пользователь с клавиатуры или AI персонажа (если это NPC к примеру).
Далее отдельный метод (например StateMaster) чекает эти флаги и в зависимости от их комбинаций переходит в нужное состояние или апдейтит текущее. Например: из IDLE в WALK перс переходит если onGround == true, onWater == false, onLadder == похуй, keyX !=0 и keY != -1. А из IDLE в JUMP все то же самое кроме keyX == похуй и keyY == -1.
Для каждого состояния есть методы EnterState и UpdateState. Например EnterIdle или UpdateWalk. (есть еще ExitState, но о них я сейчас не буду, т.к. у тебя голова взорвется и по началу можно и без них обойтись)
При входе в состояние, уставанливается вектор скорости (он же наш желаемый вектор движения), различные переменные (к примеру обнуляется snap при входе в прыжок, и он же восстанавливается при входе в Idle), переключается анимация и т.д.
В апдейте состояния ты делаешь по сути то же самое. Контролишь скорость (например при падении, чтобы не превышала какое-то значение), меняешь направление и т.д.
Физика и коллизии внутри стейтов не проверяются. Только внутренние параметры самого объекта (скорость, флаги и т.д.)
Гравитация (изменение вертикальной составляющей скорости) так же делается в Enter и Update стейтов (естественно там где она нужна)
Теперь сам физический цикл:
1) Проверка ввода и установка key флагов
2) Установка/апдейт состояния (StateMaster)
3) Движение
4) Проверка коллизий.
По первым двум пунктам я уже расписал.
Пункт 3 движение. Тут все просто Velocity = move_and_slide_with_snap(velocity,....). Одна строка и все. Без всяких выборов. По факту если игрок находится в том стейте в котором он двигаться не должен, то velocity уже будет равна нулю и он не передвинется.
Пункт 4. Здесь происходит проверка коллизий и устанавливаются флаги персонажа. Например onGround, onLadder, onWater и т.д. которые по которым в следующем цикле будет определятся стейт персонажа. (собственно этот пункт можно делать в начале физического цикла, перед опросом инпута, но собственно похуй, т.к. цикл и так по кругу крутится, а коллизии все равно кешируются и делаются один раз за фрейм - дело вкуса)
------
Собственно все. И по факту это будет работать без всяких дополнительных костылей.
Важно только запомнить, что стейты устанавливаются только по состоянию флагов персонажа и скорости (коллизии в этом месте не проверяются)
Вектор скорости регулируется только в стейтах и нигде более, коллизии в стейтах не проверяются.
В блоке проверке коллизий, устанавливаются только флаги и все, скорость не трогается.
------
Дополнительно за гравитацию. Бывает, что ее рациональнее в отдельный метод вынести (например если подразумеваются зоны с разной гравитацией). Тогда ее можно применять не в стейтах, а в основном цикле сразу после установки/апдейта состояния (перед передвижением)
Нарисовав речушку, понял, что не ебу как обозначить её для персонажа, дабы он на определённом типе тайла замедлялся.
Хелб.
У игрока делаешь переменную int isInWater и два метода EnterWaterArea() и ExitWaterArea(), каждый из которых ее увеличивает или уменьшает соответственно, только в ExitWaterArea() еще делаешь проверку, чтобы isInWater не становилась меньше нуля.
Прикрепляешь к своей реке (ну или кидаешь поверх) Area2D повторяющую форму твоей реки. К ней крепишь скрипт к которому коннектишь сигналы onBodyEntered и onBodyExited от этой же Area2D.
Из скрипта реки вызываешь у игрока методы EnterWaterArea() и ExitWaterArea() по соответствующим сигналам.
Теперь в любое время у игрока проверяешь isInWater и если оно больше нуля - игрок в воде уменьшаешь скорость. Можешь это делать прямо в методах но это зависит от реализации твоего игрового цикла, может оказаться не очень удобно.
----
Еще не забудь если у тебя другие body на карте есть и они могут контактировать с водой, то надо разнести их по разным collision_layers с игроком и чекать коллизию только с нужным слоем, а то у тебя вода у всех подряд в нее входящих будет методы вызывать.
Ассетная консоль слишком оверхеднутая, как на мой вкус. Я сам себе консоль писал однажды.
>>73640
> Подробнее можно?
>>73631
> пользователь пишет кодом команды персонажу, а тот их последовательно выполняет
Команды персонажу пусть будут методами. Ты знаешь названия методов, следовательно можешь их вызвать:
player.callv("some_action", [some_arguments_array])
Ты можешь сделать где-то в зоне общей видимости (в синглтоне) массив, в который консоль ввода добавляет команды, а персонаж этот массив читает, выполняет и удаляет выполненное.
var command_queue : Array = [
{"name" : "some_action", "arguments" : [some_arguments_array]},
{"name" : "another_action", "arguments" : [few_arguments_array]}
]
Основной массив простой, а его элементы - ассоциативные массивы (словари).
Далее, чтобы выполнять команды последовательно, каждую следующую после завершения предыдущей, самым оптимальным решением ввести в код персонажа состояние или флаг BUSY, который он выставляет, когда делает команду. Таким образом, помещаем в process:
if state != BUSY:
if global.command_queue:
state = BUSY
var command : Dictionary = global.command_queue.pop_front()
self.callv(command.name, command.arguments)
Здесь я не делаю проверок на ошибки, полагая, что консоль будет добавлять корректные записи команд в массив.
Теперь сама консоль. Ух, лучше отправлю пост, а то вдруг сбой/миссклик/НЁХ!
Анон, тебе два вопроса:
1. Как использование стейт-машины спасёт от бага внутри move_and_slide_with_snap?
2. С чего ты взял, что у меня в основном проекте нет стейт-машины?
Так вот, сотона, теперь консоль.
Нам нужно читать данные из текстбокса. Соответственно делаем сцену с текстбоксом и коннектимся к его сигналу... или (я щас подсмотрел в свой код) в инпуте проверяем нажатие события ui_accept (надо переписать на сигнал text_entered а то хуйня получается всегда с этим инпутом).
Так или иначе, ты печатал какие-то буковки в консоль и вот любым образом сдетектировал нажатие клавиши Enter и теперь в консоли если есть текст, ты его берёшь и начинаешь с ним работать:
if new_text:
var command : Array = new_text.split(" ", false) # эта строка нам порежет входную строку на слова используя пробелы как разделитель. Очевидно, ты не должен использовать имена и аргументы с пробелами.
Теперь, что нам делать с массивом? Мы ожидаем, что пользователь ввёл строку: "консольная_команда_добавления_в_очередь имя_действия аргумент_1 аргумент_2 и_еще_аргумент". Нам нужно проверить первый пункт массива на соответствие известным консоли командам, в данном случае, команде на добавление в очередь:
if command:
if command[0] == "add_command":
Остальные параметры мы можем проверить здесь, или в персонаже, наверное логичнее в персонаже, давай вернёмся в предыдущий пост и напишем так:
if state != BUSY:
if global.command_queue:
state = BUSY
var command : Dictionary = global.command_queue.pop_front()
if self.has_method(command.name):
self.callv(command.name, command.arguments)
Теперь возвращаемся обратно в консоль. У нас уже есть массив вида:
[
add_command,
some_action,
1,
2,
false
]
Нам нужно превратить это в вышеописанную структуру. Консольная команда нам не нужна. Удаляем её. Следующий аргумент рассматриваем как имя метода, создаём новый словарь и пишем ему "name" = pop_front() это вернёт первый аргумент и удалит из массива, как описано в доках. Весь остальной массив без задней мысли запихиваем в поле "arguments" : command
Ну вот и всё. Как то так. Дерзай.
Так вот, сотона, теперь консоль.
Нам нужно читать данные из текстбокса. Соответственно делаем сцену с текстбоксом и коннектимся к его сигналу... или (я щас подсмотрел в свой код) в инпуте проверяем нажатие события ui_accept (надо переписать на сигнал text_entered а то хуйня получается всегда с этим инпутом).
Так или иначе, ты печатал какие-то буковки в консоль и вот любым образом сдетектировал нажатие клавиши Enter и теперь в консоли если есть текст, ты его берёшь и начинаешь с ним работать:
if new_text:
var command : Array = new_text.split(" ", false) # эта строка нам порежет входную строку на слова используя пробелы как разделитель. Очевидно, ты не должен использовать имена и аргументы с пробелами.
Теперь, что нам делать с массивом? Мы ожидаем, что пользователь ввёл строку: "консольная_команда_добавления_в_очередь имя_действия аргумент_1 аргумент_2 и_еще_аргумент". Нам нужно проверить первый пункт массива на соответствие известным консоли командам, в данном случае, команде на добавление в очередь:
if command:
if command[0] == "add_command":
Остальные параметры мы можем проверить здесь, или в персонаже, наверное логичнее в персонаже, давай вернёмся в предыдущий пост и напишем так:
if state != BUSY:
if global.command_queue:
state = BUSY
var command : Dictionary = global.command_queue.pop_front()
if self.has_method(command.name):
self.callv(command.name, command.arguments)
Теперь возвращаемся обратно в консоль. У нас уже есть массив вида:
[
add_command,
some_action,
1,
2,
false
]
Нам нужно превратить это в вышеописанную структуру. Консольная команда нам не нужна. Удаляем её. Следующий аргумент рассматриваем как имя метода, создаём новый словарь и пишем ему "name" = pop_front() это вернёт первый аргумент и удалит из массива, как описано в доках. Весь остальной массив без задней мысли запихиваем в поле "arguments" : command
Ну вот и всё. Как то так. Дерзай.
1) Если ты про баг когда перс внезапно подпрыгивает, при движении вверх по склону. Возникает он тогда, когда при остановке персонажа обнуляют только горизонтальную скорость забывая о вертикальной. В итоге скорость ебашит вверх, снап вниз и по ходу в какой-то момент скорость перевешивает. По крайней мере в тех примерах с гитхаба, где писали про этот баг так и было. Исправляется тем что при остановке скорость обнуляется полностью, а не только по горизонтали. Тут дело не в наличии стейт машины, а в понимании того, что ты делаешь. И судя по тому, что ты скидывал ты так и не разобрался, как работает move and slide и т.д. А все твои костыли работают неправильно судя по тому, что вектор скорости у тебя постояно смотрит хер знает куда, а не вдоль поверхности.
2) Ты бы не понаписал такого, как в примере, который ты скидывал. Ну или обоссал бы ту реализацию, которуб я описывал, т.к. она далеко не идеальепая (хотя и работает)
Баг возникает тогда, когда персонаж уже поднялся по склону и перешёл на горизонтальную поверхность. При этом velocity.y остаётся такой, будто он всё ещё поднимается в гору. Но, несмотря на высокое значение игрека, персонаж всё ещё прилипает к горизонтальной поверхности, потому что снап.
То есть, баг в том, что снап не обнуляет большой отрицательный игрек на горизонтальных поверхностях. Хотя предназначен именно для этого.
И ты посмотри всё-таки пример. Я там специально вынес "вкл/выкл багфикс" в экспорт.
>То есть, баг в том, что снап не обнуляет большой отрицательный игрек на горизонтальных поверхностях. Хотя предназначен именно для этого.
Схуяли? Он предназначен, чтобы при движении прилипать в направлении вектора snap и все. Скорость он обнулять не должен. Со скоростью ты ебешься сам.
Я смотрел. И видел. Но сейчас уже комп выключил и спать ложусь. Если завтра не лень будет еще гляну и попробую расписать, что не так.
Место всей этой хуйни, я пишу свой текстовый редактор, потому что текущий текст-едит не может лайну задать цвет. Есть ли способы, кроме ебанутого?
Есть способ. У меня пикрелейтед. Снизу командная строка, без цветов, а сверху ричтекстлейбл, в котором можно всё красиво раскрасить ББкодами.
> текущий текст-едит не может лайну задать цвет
Падажжи, я только что дотормозил до этого фрагмента. поясни, что именно ты хочешь? Выделение текущей строки с курсором или выделение цветом определенной строки независимо от выделения?
Моя проблема в том, что я не могу подсветить строчку в текст-едит красненьким, если там ошибка.
Хочу сделать красным выделить строку в текст-едите. Любую строку. Но это не возможно. Поэтому я взял, и хуячу каждый раз новую панель в датагрид, охуевая от своего говнокодинга.
Вот мы и пришли к ключевому моменту. На самом деле всё это время мы спорили об этом.
Вот смотри. Move_and_slide обнуляет скорость при столкновении с препятствием. Именно для этого он и нужен. Ведь он мог бы просто останавливать кинематика, а со скоростью ты ебёшься сам - но нет, он именно обнуляет игрек, когда персонаж касается горизонтального пола. Точно такого же поведения я ожидал и от снапа.
Кстати, если снап не влияем на скорость, то в нём нет смысла. Потому что, если я вручную обнулю скорость, то получается тот самый снап, причём правильно работающий.
> я взял, и хуячу каждый раз новую панель в датагрид, охуевая от своего говнокодинга
>>73705
> подсветить строчку в текст-едит красненьким, если там ошибка
Но ведь в редакторе годота ошибки подсвечиваются красным, а там именно тот же самый текст-эдит. Просто открой исходники на гитхабе и глянь, как это реализовано у Хуана. Делов-то. Прелести опенсорца.
> Move_and_slide обнуляет скорость при столкновении с препятствием.
Нет.
> Именно для этого он и нужен.
Нет! НЕТ. ХОСПАДЕ НЕЕЕТ!
Действительно. Я щас погуглил. Есть проблема. Забыли выставить метод.
https://github.com/godotengine/godot/issues/34165
Ждём.
Как мне там вставить метод самостоятельно? Я не хочу ебашить свои собственные костыли из 14 lineedit, сохраняя в мемори строки и двигаясь стрелками обновлять их на свежие строки. Или ещё хуже, создавая милльон лайнедитов.
Самое очевидное, пофиксить исходники и пересобрать движок. Или писать игру на плюсах, что тоже потребует как минимум перелинковки предкомпиленного движка с твоими модулями. Но так идёт по пизде весь принцип визивига в редакторе. Потому что вместо редактора ты будешь в ИДЕ сидеть. Надо проверить, выставлен ли метод в шарпе? Тогда ты сможешь перейти на шарп.
Вот как-то так. Я уже засыпаю на клаве.
Качаю с#. Но как-то хуйня выходит. Где функционал епта? Все сидят и пилят всякую херню на своем гитхабе. Нахуй им, блять, этот вулкан сдался, если нет сука коробочного выпиливания расчета объектов, которые не видит игрок и даже базового z-индекса у тайлов в тайлмапе.
Это же опенсорц. Если тебе не нравится - форкай и допиливай то, что считаешь нужным. Сможешь хоть DirectX туда прикрутить. Какие проблемы?
Я планировал делать игры, а не движки. Да и опенсорц это войны коммитеров, и какой-нибудь ебанутый вахтер, а не "допиливай что хочешь".
Сэкономлю тебе время. В C# тоже такого метода нет. Проверил сейчас на 3.2.2 beta3
Прозрачные тайлы с нужной маской вокруг я херачить точно не хочу, так что если нет некостыльного решения, пойду ручками раскидывать, но какого хрена?
Используй лучше Tiled вместо встроенного редактора. Он намного пизже и там любой автотайлинг настроить можно.
Вот тебя-то мне и нужно. Я пробовал тайлед, но либо не разобрался, либо. Вот скажи, автотайлы экспортируются оттуда? Мне нужно в игре изменять тайловый "террейн". Соответственно, мне нужны действующие автотайлы в формате годота, но как я понял, при экспорте из тайледа выходит статический тайлмап.
>Вот скажи, автотайлы экспортируются оттуда?
Насколько я знаю нет. Технически можно попробовать либо постиимпорт-скрипт написать, либо сам плагин для tiled-а переделать (он на GDScripte написан). Но у меня пока такой задачи не стоит, в будущем возможно займусь.
Тхнкс, но уже вытянул из него абсолютно всё, что мне нужно, даже одностороннюю проходимость.
А спрыгивание сквозь платформы без отключение физического коллайдера, вангую, всё равно не делается.
Товарищи, а кто-нибудь пользовался WAT-плагином? Я пробовал на 3.2.2. beta3, но что-то он вообще не работает. Интерфейс включается, но не могу ни скрипты подключить, ни даже каталог для тестов выбрать.
Вот в этих 2-х строчках тип поменяй, там же пишет отладчик что попап присваивали кнопке.
1 тест какой-то не проходит тестовый, но мне некогда смотреть.
Оу, спасибо огромное, Анон.
Я прощелкал этот момент. Видел сначала эти ошибки, но после первого запуска они почему-то исчезают и не светятся в выводе. Сделал как ты сказал и все заработало, и даже под C# чего-то тестится.
Буду теперь курить мануал по тестированию. Я пока в этом нуб, так что если есть какие-нибудь советы, то буду благодарен.
--------
>>74110
>Забыл сказать, WAT качал с гитхаба, может он на пару дней свежее ассетовского
Да, я сразу качал с гитхаба, тем более что мне версия под C# нужна (WATSharp), ее в ассетах нету. Но там тоже эта ошибка и была.
Научи хорошему. Критикуя - предлагай.
>Плохому учишь.
Почему?
Для меня метод рабочий, проще варианта не нашел. Если знаешь - поделись.
Благодарю.
Видел несколько способов, но не уверен в выборе.
Зависит от того, насколько геймплей должен быть сосредоточен на платформинге. Но в общем и целом тема полностью раскрыта у Game Endeavor'а, делай по его туторам.
>насколько геймплей должен быть сосредоточен на платформинге
В планах создание лестниц(и возможность стрельбы с них из одноручного), карабкание вбок, плавание. Не уверен, что всё доживёт до релиза, но кто знает.
Не слишком дохуя хочу?
Хочу сделать шейдер, суть такова. Есть фон, на каждом уровне свой, состоит из тайлов. Фон смещается при движении камеры. Сдедующим слоем идут всякие разные объекты, которые этот фон заслоняют. А ещё выше - наш шейдеристый герой. Задача: сделать так, чтобы сквозь некоторые места в герое был виден фон, но без всех других объектов поверх. При том, что сам герой отрисовывается выше этих всех объектов, и вокруг него вполне нормальный прозрачный контур, за которым видно объекты, закрывающие фон.
Есть какие-нибудь мысли, как такое можно провернуть?
>Годаны, каким способом лучше всего реализовать движение главгея в платформере?
Стейт машина. Удобнее никто еще не придумал. Все остальное костыли. Из выбора здесь только организовывать ее всю в пределах одного класса, или выносить каждый стейт в свой класс. Мне по душе больше первый вариант, но я байтоеб и мне так удобнее.
---
>>74886
>В планах создание лестниц(и возможность стрельбы с них из одноручного), карабкание вбок, плавание. Не уверен, что всё доживёт до релиза, но кто знает.
>Не слишком дохуя хочу?
Не не слишком - джентельменский набор. Если разберешься как правильно делать стейты и нормально их спроектируешь, то добавление новых действи персонажу будет легким и приятным делом.
Ну а хули ты хотел. Не все ж тут сверхразумы вроде тебя, и нубы с тупыми вопросами в таких вещах - явление очень частое.
Не-не, Дэвид блейн. У Гонки есть интересные видео, в частности по шейдерам. Но вот конкретно этот совет хрень поная. И в комментах под видео расписали почему.
> Есть какие-нибудь мысли, как такое можно провернуть?
Манипулировать слоями рендера.
show_begind_parent
light_mask
Что-то типа этого.
С дивана советую. Не обоссывайте.
этим местом надо сидеть на диване, а не читать
Мне не нужно, чтобы объект скрывался позади родителя. Он вообще должен быть на переднем плане так-то, чтобы ничего его не закрывало. Но сквозь некоторые окна на нём должно быть видно фон, игнорируя все прочие объекты между сабжем и фоном.
Насколько я понимаю, фон во время своей отрисовки должен откладывать себя в текстуру, потом эту текстуру берёт нужный объект, накладывает на себя согласно отдельной текстуре-маске. Но
а) Я не нашёл упоминаний, что такое вообще возможно. Хотя в доках вообще довольно скудно описаны шейдеры.
б) Есть сомнения в быстродействии такого метода. Потому что а как передать текстуру напрямую из шейдера в шейдер? А если не напрямую, то через скрипт будет прям медленно.
В текущей реализации говно. При всём уважении к гуманитариям (художникам, дизайнерам), не будьте даунами, потратьте пару дней на изучение простого, как добавление эффектов слою в фотошопе, языка GDScript и не ебите себе и вашему кодеру мозги с вижуал-лапшой.
Хуаном не предполагалось, что ты будешь корректировать кости в редакторе годота. Поменяй как тебе надо в блендере и переимпортируй. Ещё есть аддон на гизмы для костей. Возможно он тебе поможет. Устанавливается через вкладку АССЕТЛИБ.
В годо всё - ноды. Даже кости. Философия движка же.
Если кому интересно.
Прогнал тест анона с тайлмапами через V3.2.2. beta 3
1 webm - без батчинга
2 webm - с батчингом
Количество draw calls пишется под FPS
А если речь про двадэ?
А меня кто-то в прошлом треде спрашивал, почему я не перехожу на GLES3, ведь двойка этажи залупа для маломощных тостеров, не могущих в нормальный графон. Вот почему.
Только, чтобы потом не было вопросов. Я тестировал конкретно часть с тайлмапами, т.к. меня только они интересовали. Что там по остальным тестам по отдельным спрайтам, я х.з - сами выясняйте.
Там фпс-лок, иначе была бы разница. Или vsync отключи, или где-то в настройках проекта target fps
ФПС локается где-то на уровне рендера по частоте монитора. По моим личным субъективным ощущениям. Когда я на мониторе выставляю 144 герца, то и в движке у меня ФПС внезапно вырастает до 144. Я не знаю, нормально это или нет?
>Я не знаю, нормально это или нет?
Нет. Используй _PhysicsProcess вместо _Process. Тогда у тебя частота игрового фрейма не будет привязана к фреймам рендера.
>Там фпс-лок, иначе была бы разница. Или vsync отключи, или где-то в настройках проекта target fps
Мне вломы видосы по второму разу запиливать, поэтому просто цифры:
1) vsync = off; batching = off
draw calls = 3300...3400
fps = 190...210 (_physics_process)
fps = 73...74 (_process)
2) vsync = off; batching = on
draw calls = 40...45
fps = 390...400 (_physics_process)
fps = 75...77 (_process)
-------
Это все к кейсу с тайлмапами.
-------
>>75317
>Ваще не в тему совет. Советовать колбэк физики вместо того, чтобы советовать всинк.
Все в тему. Если у тебя игра ускоряется в зависимости от частоты обновления монитора, так быть не должно. Игре вобще должно быть похуй на рендер. Если ты будешь считать все в _physics_process, то так и будет. Даже если у тебя рендер будет 30FPS, то игра все равно будет работать с той же скоростью, как и на 60FPS, пострадает только плавность картинки, анимации и прочий визуал.
Та же фигня и с увеличением частоты.
Вообще vsync отключается в Project -- Project Settings -- Display -- Window -- Vsync -- UseVsync
Еще всинк может лочится на уровне видеокарты, тогда придется лезть в ее настройки.
Но, отключать всинк в игре - это то еще мудачество в подавляющем количестве случаев - не надо так.
>просто цифры
забыл написать, что физика на 60 залочена, при больших значениях просадки больше.
Найден обходной путь: RemoteTransform(2D). Немного медленно получается, потому что надо переключаться туда-сюда, зато анимация редактируется по линеечке при любом дереве.
Выгружаю уровень.
Загружаю новый уровень.
Паренчу туда персонажа.
Результат: персонаж не издаёт звуки, которые у него в потомках. Звуки уровня слышны прекрасно. А вот сам перс почему-то онемел.
У меня есть некоторые соображения на данный счёт, которые буду проверять. Но хотелось бы спросить здесь. Анон, если бы у тебя такое случилось, ты бы где искал проблему?
Ах да. Если загружать не другой уровень, а тот же самый (но старой версии всё же queue_free сделать предварительно), то звуки не исчезают.
Но новый уровень точно не виноват, потому что он тестовый и пустой, там нет ничего, кроме ровного пола до горизонта.
И да. Двадэ.
Анончики, дайте совет по интерфейсу.
Кидаю на сцену VBoxContainer
Делаю ему Size Flags - Vertical - Fill, чтобы он у меня растянулся на всю высоту окна. Потом кидаю в этот контейнер два элемента.
Как сделать так чтобы они прилипали к разным границам экрана? Один к верхней, второй к нижней. Нихрена не пойму, уже все галки перетыкал, но они липнут друг за другом и с одной только стороны.
Все, сам разобрался. Кинул в этот VBoxConteiner еще два VBoxConteiner'а и у них уже задал Aligment'ы в top и bottom.
Блин, ну и мутный этот ваш фронтенд.
> fps = 190…210 (_physics_process)
Да как блять? Кто из вас двоих меня наёбывает? Ты или пикрелейтед? Откуда там 100 - 200 если по дефолту физика залочена на 60 физических_фреймов_в_секунду и во всех движках рекомендуется этот параметр уменьшать.
А вот интересно, можно ли в годоте реализовать переменный фреймрейт для отдалённых объектов? Как в некоторых играх. Чтобы разгрузить систему, в некоторых играх делают, что когда мобы очень далеко, они на 10-15 фпс ебошат и даже меньше, что вызывает дичайший угар у игроков и лецплееров, когда они успевают это заметить.
>Откуда там 100 - 200 если по дефолту физика залочена на 60 физических_фреймов_в_секунду
Физика считается, кадры рисуются. На один физический фрейм, прорисовывается несколько одинаковых фреймов рендера.
В скобках просто указано в каком процессе я гонял основной цикл.
Я вообще честно говоря в проекте анона не разбирался, там gdscript и прочая хуйня, так я х.з. что за цифры, меня больше количество дроу колов интересовало, чем фпс.
>>75414
>во всех движках рекомендуется этот параметр уменьшать.
Я вот в своем платформере физику на 120 гоняю. Брат жив, зависимость есть.
Сам спросил — сам проверил.
Спойлер: стоит, даже на 120 фпс задержка сильно меньше. Пойду теперь оптимизировать всё живое.
Ну это, как в процессоросрачах. ФПС вроде одинаковый, но у ин... в одном случае у тебя есть запас на случай нагрузки, а во втором - нет и под нагрузкой фпс просядет.
> нихуя не получается. Уже в тупую копипащу код, спрайт не хочет двигаться.
Спрайт и не должен двигаться. Спрайт - это объект для отрисовки текстуры. У спрайта есть позиция, но на практике у спрайтов позиция всегда либо 0;0 либо какая-либо изначально выставленная и не меняется. В локальных координатах, разумеется (это подсказка, да).
А у тебя уже есть готовая к релизу игра, на которую ты желаешь это проприетарное nvidia vxgi навесить? Тогда вперёд - пишешь в нвидию, заключаешь контракт, оплачиваешь, получаешь SDK, скачиваешь исходники годота, и, юзая архитектурный паттерн "адаптер" имплементируешь vxgi, затем конпелируешь движок, либы, тулзы, проверяешь чтоб всё работало. И... Поступаешь на работу в нвидию! Жизнь удалась!
Хотя стоп, я вас путаю. Под vxgi обычно имеют nvidia voxel cone tracing, а что именно с своей реализацией voxel cone tracing в godot?
Пиздец, анончик! Ну ты дал стране угля!
А из названия в инпут мапе можно вытянуть её сканкод?
Да. InputMap.get_action_list("dat'_yobu")[0].scancode
Ох и намотает же сейчас костылей на мой велосипед...
> намотает
> костылей
> на мой велосипед
Обычно такое бывает, когда ты сформировал задачу, под неё сформировал сомнительное решение, и начал искать варианты решения.
ВМЕСТО ТОГО, ЧТОБЫ СПРОСИТЬ У АНОНОВ О ЗАДАЧЕ
Я уже догадался, что задача - сделать конфигуратор управления.
При наличии десятков мануалов и туториалов, ты выбрал Путь Костыля!
Не моё дело тебя судить. Засим откланиваюсь.
У самурая нет задачи, только путь.
При нажатии некоторых кнопок следует издать звуки с минимальной и, по возможности, одинаковой задержкой. Чтобы отвязаться от fps, я хочу вызвать их через _unhandled_key_input как можно быстрее. Чтобы исключить неравномерную проверку условий (до одной кнопки будет две проверки, до другой — пять, это вроде как ощущается), я хочу вызвать это дело по сканкоду. В то же время, чтобы локализовать костыль, сканкоды я собираюсь держать в отдельной таблице, а все действия держать в стандартном виде в настройках проекта, аки в туториалах.
Бекапы с более традиционным инпутом у меня есть, не переживай.
Нихуя не понятно, но очень интересно! Хуячь, анон!
https://dropmefiles.com/CzT2T
Так чего, никто не знает? Мне просто нужно, чтобы между объектами была зависимость.
я не понимаю, что оно значит. Решил переделать с нуля. Чтобы тестить каждый добавленый узел. Пока что не багает, но предупреждения висят
> я не понимаю, что оно значит
Размеры тел регулируй масштабированием формы коллизии. А ты масштабируешь само тело. Это неправильно.
Крч все херово.
Я сделал куб, который у меня отвечает за пол.
Сделал кучу объектов, которые не связаны друг с другом. Они немного прыгают по полу, а потом проваливаются в текстуры. Я хз что это за говно и как это править. 3Д физика вообще тут работает?
Скачай официальные демки, посмотри как там сделано. Я месяца два назад создавал сцену с кубами, ничего не проваливалось.
Поменяй их на цилиндры. Кубы работают действительно нормально. Цилиндры и сферы - нет.
Ты что-то делаешь неправильно, у меня всегда персонаж это капсуль ( цилиндр + две полусферы) и он никуда не проваливается. Покури ещё мануалов.
У тебя стоит не rigid-body, а character. Он не может вращаться. Rigid может.
Блэд, объяснити нормально, как правильно импортировать модельки из блендера в годо? Куча каких-то форматов, куча какого-то мусора, какие-то источники света и лампочки, материалы постоянно отклеиваются, моделька в блендере серая, а в годо синяя, задолбался уже, неужели нельзя просто в два клика импортировать и ничего потом не редактировать??
Теперь ещё более забавный баг. Не понимаю, что делаю не так:
https://dropmefiles.com/owxId
1. Формат - gltf (2). Нормально работает экспорт gltf+textures separately, по умолчанию стоит бинарный он похуже. Отмечу что в экспортере есть баги, которые постоянно фиксят, так что пробуй свежие беты блендера если какие то проблемы (но не забывай делать бекапы и блендера, и моделей.)
2. Лампочки и камеры удали в блендере, зачем они в модели? Они нужны в сцене. В модели ничего лишнего и не должно быть. Еще советую почистить иерархию сцены, и применить все трансформации.
3. В годо синяя моделька, потому что по дефолту подключено окружение с синим небом. Можешь почитать тут https://github.com/godotengine/godot-proposals/issues/348
https://www.youtube.com/watch?v=8kwnCxK8Vc8
Советую самому настроить небо как хочешь один раз и потом переиспользовать.
Материал как то отвалился, но там фикс был элементарный, типа открыть материал и выбрать в нем текстуру.
>1. Формат - gltf (2).
Лучше использую obj, он без косяков.
>Советую самому настроить небо как хочешь один раз и потом переиспользовать.
Пытался изменить стандартный, испортил, не смог вернуть обратно, создал проект заново, больше не трогаю. :(
>>76217
>у меня всегда персонаж это капсуль ( цилиндр + две полусферы)
Как заставить этот капсуль НЕ ПОДПРЫГИВАТЬ НА ВЫСТУПАХ?
2Д (хотя, наверное, в 3Д то же самое). Имеем один ригидбоди потомок другого ригидбоди. Поворачиваем родителя. Будут ли трансформироваться вектора функций apply_central_impulse и apply_torque_impulse согласно повороту родителя или же они задаются в глобальных координатах? И трансформируется ли linear_velocity через трансформацию родителя?
Надеюсь, что правильно понял задачу.
Я бы сделал так.
1. AnimationPlayer с двумя однокадровыми анимациями: с максимальным давлением и с минимальным (если ноги анимированные, то для каждой анимации по две версии с разным давлением). Скажем, с максимальным давлением ноги согнуты, с минимальным прямые.
2. AnimationTree с нодой Blend2, у которой на входы подаются одновременно две версии анимаций. Допустим, в in идут прямые ноги, в blend согнутые.
3. В зависимости от получаемого давления изменяем соотношение смешивания (blend_amount).
С таким подходом можно регулировать не только визуальную аимацию приседания, но и коллизии. AnimationPlayer корректно работает с коллизиями, меняя их точно и гладко, не вызывая подпрыгивания и проваливания сквозь поверхности.
>Нельзя так делать крч.
А как же, по-твоему, делать рэгдоллы? И как для них делать скелетную анимацию с использованием IK (которое не работает без иерархии)?
В общем, можно, нужно, физика корректно обрабатывается.
Я хочу сделать так, чтобы я подавал сигнал на сустав, а он сгибался, двигая нижнюю часть руки.
Понял три вещи:
1) Нужно ставить центр координат ригидбоди туда, где будет центр масс. Иначе цилиндры никогда не упадут, т.к. дефолтный вектор гравитации всегда направлен на центр координат.
2) Не суй вещи с одними и теми же масками колизий в одну иерархию. Если маски разные - заебца, можно.
3) Джоинты тема, но если ты подаешь усилие в нижнюю части руки, когда к ней привязана кисть и кисть другой объект, то эта рука почему-то требует в десятки раз больше усилий, чем без кисти.
> использую obj, он без косяков.
Он не может хранить анимацию, также в нем вроде нет полей под pbr материалы..
> Пытался изменить стандартный, испортил, не смог вернуть обратно, создал проект заново, больше не трогаю. :(
Дефолтный трогать и не надо, создаешь ноду WorldEnvironment, в ней редактируешь и сохраняешь как новый файл. А значит, если что то испортил, можно загрузить другое окружение, в частности сделать новый проект и скопировать оттуда.
>>я уже передумал делать игры
>Дааа, эт не твое походу))
Ты не понимаешь, реально невозможно что-то сделать, когда единственно возможный стек программ не хочет тебя слушаться. Существуют комфортные для меня программы, которые всегда делают то, что я хочу, и имеют все необходимые мне инструменты. И, похоже, годо с блендером не имеют того, что мне нужно...
Вот даже банальный пример: захотел построить глубоко вложенное дерево так, чтобы назначать один материал сразу множеству объектов в дереве, чтобы они объединялись в одну сущность в рантайме. И что я вижу? Я могу собрать такое дерево, но оно не будет иметь рычагов доступа к его элементам, просто потому что движок на это не рассчитан, и все эти сотни нод будут висеть в рантайме без дела, нагружая и без того слоупочный игровой цикл. Как мне это исправить? Отбрасывать идею, пилить плагин (разбираясь в тонне чужого кода), писать свой движок? Да ну нафиг...
>>76338
>Он не может хранить анимацию
Зачем мне хранить анимацию, если я хочу просто модельку в стиле "из кубиков" импортировать?
>также в нем вроде нет полей под pbr материалы..
Я даже не знаю, что это такое, мне должно хватать обычных материалов, настраиваемых в движке.
>Дефолтный трогать и не надо, создаешь ноду WorldEnvironment, в ней редактируешь и сохраняешь как новый файл.
"Испортил" в том смысле, что выглядеть стало отвратительно, а не "перестало загружаться".
>можно загрузить другое окружение, в частности сделать новый проект и скопировать оттуда
Ну, так я и сделал, просто хотелось что-то другое, в частности тумана немного добавить...
Ничего не понял в твоем "банальном примере", но вот как сделано у меня: в дереве есть Spatial нода, в которой добавлено много других Spatial нод. И примитивный скрипт, который заменяет все эти ноды на конкретные домики. Занимать это будет от силы строчек пять. Цикл "для всех" children, удалить из этого дерева, добавить в другое дерево, все. Единственное, может быть понадобится вызывать это через call_deferred.
Также я пытался понять, что такое "не будет иметь рычагов доступа к его элементам".
На примере замены материалов: вот такой простой скрипт добавляет в редакторе поле для задания материалов. В сочетании с моим предыдущим постом вроде бы и должно получиться то что ты хочешь.
SB - staticbody
J1 - joint (со всеми разлоченными осями)
RB1 - rigidbody
J2 - joint (c залоченой x осью, остальное разлочено)
RB2 - rigidbody
Все вещи связаны друг с другом через джоинты.
Когда я даю усилие на RB2 по z, то rb2 поднимается вверх и все хорошо. Но если я даю усилие на RB1 по x, то её лочит J2, место перемещения в бок и не дает ничего делать, хотя на самом деле должен так же перемещаться в бок.
Как это обойти?
Я закачал свой тестировочный проект сюда.
При нажатии стрелки вниз, вы начнете крутить руку. Все будет нормально. Когда нажмете на стрелку вверх, тогда будете пытаться её поднять, но она не подымется из-за лока по осям х и у.
https://dropmefiles.com/f2dTi
Я обрадовался, думая что ты гений, потому что я совсем про этот приоритет забыл. Но он не помог.
Попробуй собрать движок сам и запустить из студии.
Ну, в голову приходит разное. Шейдер, который роняет драйвер видяхи. Цикл, который добавляет в массив больше 5000-10000 объектов. Бесконечная рекурсия.
Неплохо бы писать версию которой пользуешься и языки (c#, gdnative), да и фичи (2д, 3д, физика, скелетная анимация, навигация, аудио)
>>76481
Разве вопрос был
>помогите найти мою ошибку
? Тащемта в моём случае молчаливый краш вызывали поломанные префабы. Из-за системы наследования в них что-то поломалось; воспроизвёл в точности точно такой же набор объектов, но переделав заново - не падает.
А теперь повторю два вопроса, которые действительно имеют значение:
1. Как отлавливать молчаливые падения?
В моём случае - я просто бегал по уровню, пытался понять момент падения и какие взаимодействия в этот момент могут происходить; потом выстроил пустой тестовый уровень и так же бегал по нему. Но это как-то не круто. А вот это:
>Попробуй собрать движок сам и запустить из студии.
выглядит столь же действенно и обоснованно, как, если не можешь запомнить ПДД, искать проблему в двигателе.
2. Есть какие-то распространённые ошибки разработчиков, вызывающие краш без отладки?
Тут спасибо за некоторые примеры. Хотя бесконечная рекурсия тут явно лишняя, она вызывает сначала зависание, а не просто краш.
Вообще, я тут подумал, родился третий вопрос:
3. А как специально уронить Годо без отладки?
Есть ли готовые игры в стиме, посмотреть что можно сделать на нем
> Я на убунте, запускаю из стима последнюю версию
Не пизди, это я на убунте, запускаю из стима, ничего не зависает. Ты движкосрачер, выкатившийся из своего шизо-загона. Щас господин модератор укажет тебе нужное направление, мразота.
Ну тише, тише, не стоит агриться, из-за того шизика.
Запусаешь, идешь смотреть сериальчики, а в стиме тикает время, будто ты мамкин геймдев.
>оьновления автоматические
Чет сомнительное преимущество. Ладно бы это была игрушка, но автоматически обновлять инструментарий разработки - такое себе.
>>77419
Вобщем заметил, что если пекарню рестартануть, и сразу запустить годот, то всё работает вполне неплохо, а вот когда она уже настоялась, то зависает каждые 5 мин буквально. Вы конечно можете сказать, что дело в пекарне, но кроме годота никто так себя не ведет, а у меня есть и посерьезнее идешки.
Имеем анимацию поворота конечности. Угол поворота может быть любой, AnimationPlayer никак не ограничивает это значение. И вот тут-то и зарыта свинья.
Допустим, в одном кадре анимации значение поворота 175 градусов, а в следующем -175. И эта анимация проиграется с проворотом по всей окружности, потому что аниматионПлеер не знает, что такое lerp_angle. Допустим, в рамках одной анимации этого ещё можно избежать. А что делать, когда нужно сделать плавный переход из нескольких анимаций, в общей сложности охватывающих полный оборот? Допустим, (в моём случае) это все возможные направления прицеливания.
Нигде в доках, связанных с анимацией, не увидел каких-либо опций для замыкания диапазона углов поворота. Этот вопрос вообще нигде не поднимается. Как его принято решать в цивилизованном обществе?
Как я соскучился по тредиковскому непониманию.
Ты слово ДОПУСТИМ в начале предложения видел?
Допустим, я беру углы поворота от -180 до 180, тогда при переходе от -179 на 179 пройдёт не по кратчайшему пути в 2 градуса, а прокрутит на все 358. Но если я использую другой диапазон, скажем, от 0 до 360, произойдёт то же самое, только на участке между 359 и 1. AnimationPlayer не умеет корректно интерполировать углы поворота. Вот в чём проблема.
Еще раз повторю - если тебе надо чтобы пошло по кратчайшему пути в 2 градуса, то надо идти не -179 до 179, а 181 до 179. Это вроде бы 7 класс школы?
Не пойму, это ты тупишь или я непонятно объясняю?
Ну, возьму я вместо диапазона (-PI, PI) диапазон (0, TAU). Что изменится? Проблема зона переместится с Vector2.LEFT на Vector2.RIGHT.
Попробую перефразировать.
Если бы это происходило в коде - вообще не проблема. В коде есть lerp_angle, есть wrapf. Но это происходит в анимации. Требуется при помощи блендинга нескольких анимаций охватить полный круг, чтобы в любой момент можно было плавно повернуть из любого направления на любое. Но если этот блендинг проходит через проблемную зону, то анимация смешивается неправильно, с проворотом в обратную сторону на почти полный круг.
>>77523
Я не понял, кто из вас двоих не прав. Или оба. Но я с дивана вкину свой вариант:
1. После того, как анимация проиграла в скрипте проверяем значения вращений на задвоенность кругов (365 = 360 + 5, вычитаем полный круг, оставляем 5 и так далее) вызов функции проверки, при желании можно в конец анимаций насовать.
2. Все анимации рассчитаны на два полных круга и при блендинге могут плавно наворачивать второй круг, вместо того, чтобы поехать в обратную сторону, потому что 365 это 5)
Вот! Нашёлся вникающий человек.
1. Из скрипта что-то крутить не вариант, потому что
а) скрипт работает только с деревом анимаций, но не с отдельными деталями. Любые попытки поменять углы поворота будут немедленно затёрты этим же деревом.
б) Анимация никогда не доигрывает до конца, она работает в непрерывном цикле смешанных состояний, причём пропорции смешивания меняются каждый фрейм.
2. В принципе, более жизнеспособно, однако создаёт два больших гемора:
а) придётся наплодить в два раза больше анимаций, крайне усложнив дерево.
б) Переходные положения потребуют невероятного количества костылей в коде.
В общем, пока вот такое решение придумал. Оно будет замедлять события на транзишенах, но зато никаких проворотов, можно вертеть анимацией сколько влезет.
Примечания по картинкам (это два представления одного и того же, если кто не понял). Анимации anim_up_l и anim_up_r - отличаются, потому что персонаж смотрит в разные стороны. Поэтому между ними нужен транзишен в 0.5с. То же самое про анимации anim_down_l и anim_down_r. Анимации anim_right_u и anim_right_d это в точности одна и та же анимация. Транзишен между ними нужен для симметрии, чтобы не городить лишний код. Анимации anim_left_u и anim_left_d это одна и та же анимация, но с разницей в 360 градусов по корневым узлам; таким образом, нижняя часть блендится с anim_left_d, верхняя блендится с anim_left_u, а между ними происходит мгновенный переход.
Вроде должно сработать.
> никакой разницы не будет?
Ты имеешь ввиду делать уровень не кусочками, а просто набором огромных текстур?
Дистрибутив будет больше в десятки раз.
Необязательно, если у тебя платформер или рпг в ретро стиле, то там и без генерации тайлы. К тому же, если у тебя одна картинка, тебе придется как то к ней коллиизии и прочую логику приделывать, а тайлы - это клетки, ты всегда можешь проверить какой там тайл и какие у него свойства.
Не знаю, может, там была какая-то лютая компрессия. Бета2 запускалась гораздо медленнее.
У меня вроде ничего не поменялось - сам редактор так и запускается мгновенно, а большой уровень грузится с минуту. Может какой то баг поправили для конкретного железа.
Тридэ? GLES3? Потому что у меня двадэ в GLES2, ну там батчинг.
А как в стратегиях?
Двачую, тоже не понял вопрос. Ну делай не 4-direction а 8-direction, или на гексах.
К KinematicBody2D прицепи Area2D c CollisionPolygon2D (Можешь и с CollisionShape2D, но это на мой взгляд это хрень бесполезная, я ей не пользуюсь, по крайней мере была в предыдущих версиях движка). У Area2D есть нужные тебе сигналы.
Если нужно будет, то форму и положение полигона можно менять через скрипт из самого аниматора.
>Результат будет эквивалентен тому, чтобы не ставить sync_to_physics и ловить коллизии с move_and_collide. Только гемора меньше.
Ну так по условиям задачи move_and_.... не работают в данной ситуации.
>И, возможно, срабатывать будет хуже, так как area2d не то чтобы любит, когда его двигают.
И не надо ее двигать. Двигать надо коллижн-полигон, который к ней прикреплен.
>>78355
>А это вообще какое-то сильное колдунство.
Know your nodes.
1280x720, 0:08
Попытался сделать лифт, а на нём is_on_floor() не работает.
Ну как не работает... На видеорилейтед не видно, но спрайт персонажа очень быстро переключается между состояниями "прыжок"/"идле".
А) Это лечится?
Ж) Где я проебался?
Вот говнокод передвижения персонажа: https://pastebin.com/99FMrk4a
Ну, тут как всегда - только выплакался о проблеме, и как раз поставил этот ролик.
Завтра подкручу платформы тогда.
Сейм щит, бро. Я думаю, что процесс формулировки проблемы как-то помогает её решить. А когда отправляешь свой вопрос, всплывает мысль: а достаточно ли я гуглил? - и идёшь гуглить ещё.
Короче, вопросы, вопросы...
Парни, киньте адекватным гайдом про сохранения.
Просто, без задней мысли сохраняешь айди (создай словарь айди-сцена), координаты и нужные тебе параметры в JSON, а при чтении (загрузке) по айди инстансиш нужный объект в нужном месте с нужными параметрами.
https://docs.godotengine.org/uk/stable/tutorials/io/saving_games.html
Читал этот. Тоже такое себе. Там при загрузке будет множество подводных камней.
>>78471
К сожалению адекватных гайдов я не нашёл, поэтому я сделал собственную систему сохранения и сейчас напишу тебе мини-гайд по ней.
Игровой мир это автозагружаемый синглтон. Он содержит в себе всё, что нужно для игры: список локаций и телепортов между ними, список предметов в сундуках, позиции и состояния врагов, и т.д. Во время игры все интерактивные объекты пишут в игровой мир изменения своих состояний. Таким образом, функция сохранения это всего лишь сохранение данных игрового мира. Функция загрузки это запись в игровой мир данных из сейв файла. Но разумеется, при сохранении игровой мир отвергает попытки записи от интерактивных объектов, а после загрузки игровой мир инициирует перезагрузку локации (или перерасстановку интерактивных объектов, если локация та же, что и была).
В первой версии системы, которую я использовал в мистере Твиггле, данные игрового мира были монолитны и в сейв-файл попадал полностью весь сценарий игры со всеми диалогами, что тупо, если у тебя огромная игра (представь себе, что при сохранении, например скайрима, в сейв файл записывается копия содержимого всех esm/esp/bsp файлов, тупо же). Поэтому я сделал вторую версию системы, в которой есть игровой мир-эталон, и добавленные данные. Система прозрачно подменяет выдачу данных интерактивным объектам в зависимости от того, содержатся ли требуемые данные в добавленной области, если нет, данные берутся из эталона, если нет в эталоне, система берёт дефолтное значение, записывает его по искомому пути в добавленной области и возвращает. Файлом сохранения является, разумеется, только добавленная область с данными.
И само собой, данная система мыслилась, как совместимая с моддингом, в любой момент можно создать несколько областей добавленных данных и искать данные в них по очереди, задаваемой списком подключённых модов. Таким образом, при отключении модов, их данные эффективно и естественно удаляются из будущих файлов сохранений.
Читал этот. Тоже такое себе. Там при загрузке будет множество подводных камней.
>>78471
К сожалению адекватных гайдов я не нашёл, поэтому я сделал собственную систему сохранения и сейчас напишу тебе мини-гайд по ней.
Игровой мир это автозагружаемый синглтон. Он содержит в себе всё, что нужно для игры: список локаций и телепортов между ними, список предметов в сундуках, позиции и состояния врагов, и т.д. Во время игры все интерактивные объекты пишут в игровой мир изменения своих состояний. Таким образом, функция сохранения это всего лишь сохранение данных игрового мира. Функция загрузки это запись в игровой мир данных из сейв файла. Но разумеется, при сохранении игровой мир отвергает попытки записи от интерактивных объектов, а после загрузки игровой мир инициирует перезагрузку локации (или перерасстановку интерактивных объектов, если локация та же, что и была).
В первой версии системы, которую я использовал в мистере Твиггле, данные игрового мира были монолитны и в сейв-файл попадал полностью весь сценарий игры со всеми диалогами, что тупо, если у тебя огромная игра (представь себе, что при сохранении, например скайрима, в сейв файл записывается копия содержимого всех esm/esp/bsp файлов, тупо же). Поэтому я сделал вторую версию системы, в которой есть игровой мир-эталон, и добавленные данные. Система прозрачно подменяет выдачу данных интерактивным объектам в зависимости от того, содержатся ли требуемые данные в добавленной области, если нет, данные берутся из эталона, если нет в эталоне, система берёт дефолтное значение, записывает его по искомому пути в добавленной области и возвращает. Файлом сохранения является, разумеется, только добавленная область с данными.
И само собой, данная система мыслилась, как совместимая с моддингом, в любой момент можно создать несколько областей добавленных данных и искать данные в них по очереди, задаваемой списком подключённых модов. Таким образом, при отключении модов, их данные эффективно и естественно удаляются из будущих файлов сохранений.
А как предлагается восстанавливать места объектов в дереве?
>координаты и нужные тебе параметры
А если этих параметров много? В смысле прям много. Больше, чем есть смысл перечислять.
>>78486
Спасибо, познавательно. Но я тут понимаю, что для моего случая вариант "все интерактивные объекты пишут в игровой мир" не годится. Много разрушаемых физических объектов, пули, взрывы, боты.
>>78503
а) не пробовал, потому что ковыряться в чужом коде это ну такое, туториалы нужны ради самой концепции, как это вообще задумано.
б) щас глянул, мне годот предлагает из представленных на пикче только Local Game Save, других ассетов в списке нету.
> Много разрушаемых физических объектов, пули, взрывы, боты.
Почему не годится, очень даже годится. Главное - правильно расставить приоритеты и частоту записи в область данных. Скажем, положение пули, если оно не имеет значения для игры нет смысла и сохранять. А сохранять есть смысл боту, что он агрится, и что он последний раз видел игрока вот по этим координатам. Если горит дом, нет смысла ему спамить в АПИ игрового мира сообщениями "я горю" каждый фрейм, достаточно один раз передать сообщение о возгорании и гореть себе спокойно.
Для экшеновых шутаноидов придётся именно что спамить, потому что положение каждой пули в каждом кадре имеет значение.
Крч я погуглил ещё. Видимо, мой вариант - это дампить всё происходящее целиком в ресурсный файл. Как бы меня это ни напрягало, но уровень целиком придётся хранить там. И возиться с тем, чтобы не дать годоте запихать в него же все картинки и звуки с уровня.
Никто не сохраняет в шутанах положения пуль в заданную микросекунду, нахера? И вообще сохраняйся в чекпоинтах.
> Никто не сохраняет в шутанах положения пуль в заданную микросекунду, нахера?
Вообще говоря, если речь о шутанах, то таки сохраняет. На ютубе я неоднократно видал, как лецплееры сохраняются " на смерти", за секунду до того как пуля влетит в голову. Очевидно, что если бы пуля не сохранялась, она бы не прилетала в голову после загрузки.
Пули это обычные мгновенные рейкасты, прожектайлы используют только для медленно летящих ракетниц, так что тут все просто - он сохранился когда враг уже довернул на игрока и "прицелился", и прошел кулдаун стрельбы.
> И вообще сохраняйся в чекпоинтах.
Что такое чекпоинты? Чем они отличаются от... эээ... не_чекпоинтов?
Это означает, что сохраняется всего несколько объектов, таких как враги, ракеты, а не сотни летящих пулек, что очень сильно все упрощает.
Чекпоинт - это когда ты можешь (авто)сохраниться только в определенных точках на карте. А не нажимать квиксейв в любой момент времени. Это делает все намного проще. Во-первых, это дает время игроку подготовиться к новой попытке, а не вот так как выше описали когда ты загрузился но ты уже мертв. Во-вторых, геймдизайнер может контролировать что происходит вокруг в сцене (например сбросив состояние босса). В-третьих, устраняются некоторые эксплойты, в халфе вроде спидраны делают на постоянных нажатиях сейв-лоад-сейв-лоад и так скипают куски карт.
>И вообще сохраняйся в чекпоинтах.
Фубля. Фунахуй.
Когда я играю, меня бесит, что игра не даёт сохраняться тогда, когда я хочу. Кто в кого играет? Вот, так что, создавая свою игру, я хочу по максимуму избавиться от этого дерьма.
По поводу положения пуль. Для ясности. Я хочу от сохранений получить такую точность, чтобы игра после загрузки сейва выглядела и вела себя в точности так же, как в момент сохранения. Чтобы летящая пуля продолжила лететь, а бот шёл с тем же заданием в том же направлении, не пересканируя заново весь мир. Меня раздражает, когда после загрузки персонаж заново передёргивает затвор, костёр заново загорается, и вообще происходит пересчёт всего происходящего.
>>78547
>Пули это обычные мгновенные рейкасты
В зависимости от поставленной задачи. Если нужна какая-никакая баллистика, то пули летят. Если нужно максимально ускорить бой, то не летят. Если понерфить точность игрока, то можно замедлить пули, чтобы игроку пришлось брать упреждение по движущимся целям. Если облегчить вычисления, то прожектайлы наш выбор. Если у нас игрок это Нео, способный уворачиваться от пуль, то надо чтобы было от чего уворачиваться.
Крч не надо так категорично.
Не только в халфе, кстати.
мимолюбитель спидраны на ютубчике посмотреть
А вообще, игроки часто хуесосят сохранение на сейвпойнтах. Так что совет спорный. Не каждому жанру подойдёт.
Возможно, кому то покажется более удобным компромиссное решение: F5 можно жать, когда хочешь, но игра сохраняется только вне боя. При каждом окончании боя может срабатывать опциональное автосохранение.
Крутая задача. Думаю именно моим вышеописанным способом она и решается в больших играх. Это фактически ленивые вычисления. В момент нажатия F5 у тебя уже подготовлены данные для записи, потому что все боты, пули и костры в игре постоянно записывали свои данные пока ты играл. С точки зрения менеджера сохранений подход ленивый, просто взял словарь, ту_жсон его и в файл. С точки зрения игровых объектов подход трудолюбивый. Посчитал что-то, переместился, поменял состояние, сразу пишешь отчёт в глобальный "лог".
>материалы постоянно отклеиваются
О, сегодня столкнулся, возможно у тебя из-за этого же была проблема. Все оказалось довольно просто, есть два разных способа получить PBR картинку, и соответственно два разных способа хранить данные материалов. Годот использует Metallic+Roughness, поэтому когда импортируешь модель с Specular+Glossiness текстуры слетают, потому что не подходят. В gltf указано, какой материал используется - pbrMetallicRoughness или KHR_materials_pbrSpecularGlossiness
Сложность в том, что, похоже, автоматическая конвертация невозможна... Точнее возможна, но компьютер не всегда угадает, что из блестящего является металлом (например, снег - не является). Плюс specular - это нефизическая характеристика "отражательности" и художник-так-видит может зафигачить туда значения, которые вылезут из допустимого диапазона при конвертации.
Ручная же конвертация описана тут https://marmoset.co/posts/pbr-texture-conversion/ Она заключается в том, чтобы создать маску, на глаз соответствующую металлическим частям, и по этой маске запечь specular в базовую текстуру. Ну а roughness получается инверсией glossiness, правда, там может быть нелинейная формула, а квадратный корень.
Что требуется сохранить?
1. Глобальные переменные. Их мало, можно просто перечислить как переменные внутри класса и потом легко восстанавливать.
2. Физику (ригидбоди). С этими ребятами проблема в том, что нельзя просто так задать им положение и скорость, физический движок обидится и начнёт безобразничать. Ригиды надо сохранять целиком, чтобы какие-то их инкапсулированные свойства тоже сохранялись.
3. Инстансированные сцены, подчиняющиеся скриптам. У них есть дочерние ноды, которые в процессе жизнедеятельности как-то изменяются; соответственно, это тоже должно фиксироваться в файле сохранения.
4. Момент анимации. Чтобы после загрузки персонаж пребывал в той же позе и в той же фазе. Это важно, потому что влияет на геймплей. Анимация плавная, не покадровая, кое-где выполненная в виде перехода от любой позиции к заданной.
5. Положение нод в дереве. При инстансировании уровня надо удалять из него всё, что состоит в группе "save" и подгружать на место этих объектов сохранённые.
6. Взаимосвязи между нодами. У босса есть сигнал о смерти, этот сигнал соединён с выходом с арены, который откроется при смерти босса. Если кто-нибудь из них подгрузится не на своё место в дереве, сигнал не дойдёт. Или физика, соединённая джоинтами, развалится, потому джоинты работают через NodePath. А ведь есть ещё заинстансенные ноды, которые могут быть связаны между собой как по ссылке, так и по имени, значит после загрузки это всё должно совпадать.
И я бы рад это всё упростить, но ведь это отразится на геймплее, что недопустимо.
Короче, есть только один бог - инкапсуляция. Выписывать всё это отдельным кодом - код получится больше, чем сама игра. И будет куча трудноотлавливаемых багов. И при малейшем изменении в коде игры будет ломаться код сохранения. Значит нужно брать просто копии нод и целиком засовывать их в сейв. В принципе, самый большой уровень на данный момент весит пол-мегабайта, и я снова убеждаюсь, что проще будет сохранять уровень целиком.
Иначе как тут вообще справляться?
Что требуется сохранить?
1. Глобальные переменные. Их мало, можно просто перечислить как переменные внутри класса и потом легко восстанавливать.
2. Физику (ригидбоди). С этими ребятами проблема в том, что нельзя просто так задать им положение и скорость, физический движок обидится и начнёт безобразничать. Ригиды надо сохранять целиком, чтобы какие-то их инкапсулированные свойства тоже сохранялись.
3. Инстансированные сцены, подчиняющиеся скриптам. У них есть дочерние ноды, которые в процессе жизнедеятельности как-то изменяются; соответственно, это тоже должно фиксироваться в файле сохранения.
4. Момент анимации. Чтобы после загрузки персонаж пребывал в той же позе и в той же фазе. Это важно, потому что влияет на геймплей. Анимация плавная, не покадровая, кое-где выполненная в виде перехода от любой позиции к заданной.
5. Положение нод в дереве. При инстансировании уровня надо удалять из него всё, что состоит в группе "save" и подгружать на место этих объектов сохранённые.
6. Взаимосвязи между нодами. У босса есть сигнал о смерти, этот сигнал соединён с выходом с арены, который откроется при смерти босса. Если кто-нибудь из них подгрузится не на своё место в дереве, сигнал не дойдёт. Или физика, соединённая джоинтами, развалится, потому джоинты работают через NodePath. А ведь есть ещё заинстансенные ноды, которые могут быть связаны между собой как по ссылке, так и по имени, значит после загрузки это всё должно совпадать.
И я бы рад это всё упростить, но ведь это отразится на геймплее, что недопустимо.
Короче, есть только один бог - инкапсуляция. Выписывать всё это отдельным кодом - код получится больше, чем сама игра. И будет куча трудноотлавливаемых багов. И при малейшем изменении в коде игры будет ломаться код сохранения. Значит нужно брать просто копии нод и целиком засовывать их в сейв. В принципе, самый большой уровень на данный момент весит пол-мегабайта, и я снова убеждаюсь, что проще будет сохранять уровень целиком.
Иначе как тут вообще справляться?
>В принципе, самый большой уровень на данный момент весит пол-мегабайта, и я снова убеждаюсь, что проще будет сохранять уровень целиком.
Ну полметра это как бы вообще не много.
>>78579
>Иначе как тут вообще справляться?
Либо сохранения только вне боя или вне активных фаз уровня, когда сброс большей части объектов не критичен. Либо чекпоинты.
Тут надо просто смотреть какой именно способ больше подходит под твой геймплей. Опять же, при все нелюбви к чекпоинтам, вполне может быть ситуация, когда возможность сохраниться в любой момент будет руинить геймплей. К примеру сохранение на боссфайтах не всегда хорошая идея, т.к. может испортить весь челендж.
>Либо сохранения только вне боя или вне активных фаз уровня, когда сброс большей части объектов не критичен. Либо чекпоинты.
Терпеть не могу, когда игры не дают возможности сохраняться в любой момент. Кто хочет челлендж, тот в состоянии сам не пользоваться сохранениями; для тех, кому нужен особый стимул, вводится ачивка, поощряющая прохождение без сейвов в определённых местах, и специальные ультрахардкорные режимы. Искусственное ограничение сохранений - ужасный рудимент консолей 90х, которые имели весьма ограниченный объём носителя под это дело. Если игрок хочет сейвскамить на боссах, это его выбор. Если игрок хочет сохранить и выйти вот прямо сейчас, это его выбор.
Нет, если я не справлюсь с сохранением в нынешнем виде, придётся сделать сохранять просто между уровнями и всё. Но это совсем не тот игровой опыт, который я хочу передать.
Одна из пикч отвалилась.
Там был скриншот из видео, где тот англоязычный поц делает движущиеся платформы. У него в той строке ошибки никакой не было. ЧЯДНТ, я не заметил. Оттого и бугурт.
Ну, Globals это очевидно файл где он держит все глобально видимые переменные, значит, это autoload singleton в технологии годота
Жёваный крот, как же тяжко.
Я же просто хотел скопипиздить код лифтов, неужели я так много прошу...
Ну блджад ты не можешь завести другую константу вместо UNIT_SIZE? Серьезно, это даже не 5 секунд.
Могу, если в теории.
Однако сейчас совершенно не хочется пердолиться с кодом.
Да и в целом не слишком-то хочется.
На скорости 1.5 речь превращается в
>ывфывывыывыввфффыыфыввфвыыфвфыв
А на годоте все ассеты бесплатные? У вас вообще можно зарабатывать деньги продажей ассетов на ассетсторе?
В официальном - да, хоть там есть фильтр по цене, но в FAQ написано что они не собираются делать платные. Ну зарабатывать можно на каком нибудь патреоне.
Меня тоже раздражает. И его стиль кодинга тоже. Но по содержанию он максимально правильные вещи говорит, весьма сжато и по делу.
> У вас вообще можно зарабатывать деньги продажей ассетов на ассетсторе?
Тебе очень сильно придётся заморочиться с сокрытием кода ассетов. Ибо они легко декомпилируются, а значит легко своруются.
Я уже задолбался... Ну вот инструкция
https://docs.godotengine.org/en/stable/development/compiling/compiling_with_mono.html
поставил Mono
пишу scons tools=yes module_mono_enabled=yes mono_glue=no
Я не понимаю как мне указать mono_prefix
Префикс в линуксе - это устоявшееся обозначение не_эмулятора, которым является и вайн и моно. Как я это понимаю. Тебе пишет - не найдена установленная моно. Если она у тебя установлена в нестандартном месте, укажи путь к ней в конфиге, используя вот этот вот кейворд моно_префикс. Поскольку ты компилишь в винде, вся мощь линукса тебе недоступна и несмотря на то что ты честно установил моно рекомендуемым образом, прописать пути к ней вручную тебе всё равно придётся.
Если моно установлено через инсталлятор, то оно прописывается в реестре, у меня при сборке никакой префикс не требовало.
в godot готовый проект получается недекомпилируемым?
как формируется размер exe?
не как в гамаке?
есть ли настоящая компиляция в нативный код без скриптового интерпретатора как в гм? (именно логика игры, скриптовые моменты в расчет не беру)
> в godot готовый проект получается недекомпилируемым?
Это задаётся в настройках.
> как формируется размер exe?
Никак, все экзешники поставляются предкомпилированными, называются в нашей терминологии "шаблонами экспорта". Размер примерно 20 мегабайт, плюс-минус.
> есть ли настоящая компиляция в нативный код без скриптового интерпретатора как в гм?
Только если ты будешь писать игру на крестах.
>>78880
> и какие языки можно использовать при разработке?
Официально:
гдскрипт
сишарп
сикресты
Неофициально:
питон, го, раст, жабаскрипт и ещё куча недопиленных сторонних реализаций. На свой страх и риск.
получается, что весь движок готовой игры - всегда примерно 20мб exe + ресурсы снаружи или в добавку к размеру exe?
>кресты
можно ли подключать внешние длл как в гамаке и работать с памятью, использовать winapi?
есть ли стандартные функции типа работы с файлами, датой, реестром?
> всегда примерно 20мб exe + ресурсы снаружи или в добавку к размеру exe?
Раньше было только снаружи в пцк-архиве, теперь можно приклеить архив к экзешнику. В шапке описано.
> можно ли подключать внешние длл как в гамаке и работать с памятью, использовать winapi?
Разумеется, в крестах можно всё.
> есть ли стандартные функции типа работы с файлами, датой, реестром?
Есть с файлами, датами, насчёт реестра не знаю, это не кроссплатформенная фича и скорее всего нет, но гугл в помощь.
> > как формируется размер exe?
> Никак, все экзешники поставляются предкомпилированными, называются в нашей терминологии "шаблонами экспорта".
Это неправда, я прошлых тредах писал флаги компиляции для отключения 3д, видеокодеков и прочего, доводя размер apk до 6Mb.
> есть ли настоящая компиляция в нативный код без скриптового интерпретатора как в гм? (именно логика игры, скриптовые моменты в расчет не беру)
Есть, либо через gdnative подключением твоих dll, либо через модули, добавив их при компиляции самого движка.
Это для вопрошающего новичка инфа лишняя. Но да, каюсь, не упомянул.
>И его стиль кодинга тоже
Посмотрел создание стейтмашины от него - что-то замудрённое с кучей участков непонятных мне магических рун.
Посмотрел стейт-машину от другого поца - три-четыре нововведения.
Много думал.
>верно ли, что мобы должны думать не в _physic_process, а по тикам отдельного медленного таймера
А ты можешь ответить на вопрос "зачем" они это должны делать?
Им нужно реагировать на действия игорька и менять состояние: проверять, достанет ли атака, не нужно ли подпрыгнуть выше/спрыгнуть вниз, или может он вообще за экран свалил, и надо остановить всё лишнее.
Если у тебя платформер с тремя одноклеточными крабами, то тебе и в процесс сойдет, если тактический шутер где команды планируют тактику - то да, лучше раз в секунду просчитывать наверное.
В принципе там платформер с крабами, но таймер прямо целиком убирает в нодах врагов _physic_process, так что лучше оставлю как есть.
Ну я понимаю что Хуан во всю утонул в лайтмапах и ги, но что еще делают по движку?
Я что-то делаю не так?
Год назад видел такой, хз как сейчас.
Нет.
Поле editor_description у ноды что-нибудь делает, или туда можно беспрепятственно насрать полезной информацией?
Если тебе метаданные нужны, то в ноды встроен удобный механизм метаданных. Изучи get_meta, set_meta, может это тебе больше подойдёт?
Тоже иногда нужно что-то и даже терминов не знаю, как гуглить.
1. Показано, как регистрировать и разрегистрировать кнопку в редактор. Ее можно размещать в разных местах - в 2д, в 3д редакторе, в окошке пропертей объектов, отдельной вкладкой в свойствах проекта, и в панельку в углу где запуск игры, это задается флагом CONTAINER_...
2. Как передавать функцию в другую функцию, что позволяет обобщить алгоритм перебора всех нод рекурсивно, но с разным действием.
3. Как пользоваться всплывающими меню. Ну в общем как и везде - очистить, наполнить строками, подписаться на событие, получить номер пункта меню на который кликнули.
4. Как получать текущие выделенные ноды в редакторе.
5. Как клонировать/перемещать ноды в редакторе. Главная фишка - кроме назначения потомками (add_child) надо также назначать владельца (set_owner)
> выложу может кому пригодится
Это всё есть в официальных туториалах. Может было бы продуктивнее выкладывать то, чего нет в официальных туториалах?
>Это всё есть в официальных туториалах.
Что ты называешь официальными туторами? Видосы какие-то? На сайте документации тутора ни на один из перечисленных 5 пунктов нет.
Я хз, почему-то я видел. Разумеется, не всё в секции туториалов, что-то из списка в секции документации, что-то в секции описания классов. У меня сложностей с пониманием вышеописанных пунктов не возникло. Но то я, мне под 40, за плечами годы ентерпрайза на дельфях. Так что ну хз, пили если делать нехуй.
Щас не смогу сказать, я составлял себе списочек в районе февраля-марта, щас на работке, не до геймдева. Если не забуду, вечером загляну в тред скопипащу.
Не забыл, но так впадлу этот списочек искать. Пойду лучше в нойту катану ещё пару каток.
Я правильно понял что для каждого вида объекта/врага/пули мне нужно создавать новую сцену.
Необязательно, можно сказать есть такие пути:
1. Ты можешь создавать отдельную сцену для каждого вида объекта/врага/пули, и к каждой прикрепить свой скрипт
1а. Ты можешь создать сцену на каждый класс - например одна сцена на всех врагов, которым ты задаешь разные изображения, и возможно более ветвленая логика (например, если одни враги умеют только бегать, а другие бегать и подпрыгивать)
2. Ты можешь создать только одну сцену, в которой будет главный скрипт, управляющий всем. А скриптом добавлять/удалять/двигать ноды-спрайты, назначать им картинки и т.д.
Получается самый менее заковыристый это первый?
Какой путь наиболее правильный, или они все равноценны?
Для новичка проще, но для более сложных игр может получиться слишком много сцен и повторяющихся скриптов.
> Какой путь наиболее правильный?
В любой непонятной ситуации самый правильный путь - это путь проектирования и документирования.
Ты ещё забыл вариант, что скрипт можно расширять в дочерних сценах. Типичный случай: создать сцену с базовым скриптом, а к ней несколько наследующих сцен, которые и скрипт наследуют, но имеют свои скрипты, хоть и наследующие родительские, но с каким-то более накрученным функционалом.
Продолжаю курить туторы. Я конечно знал что игры и программирование это сплошь и рядом математика, но векторы блять, я ебал, скалярное произведение, нормали, вычитание, складывание векторов.
>но векторы блять, я ебал,
Da ty ohuel, pes. Векторы это самая мякотка. Я в прошлом своем движке страдал из-за отсутствия векторов и приходилось самому вручную городить всю эту математику. И как же я писал кипятком когда перешел на годот и узнал, что тут все это из коробки работает.
Сабжем* быстрофикс
Можно, в каком то из прошлых тредов писали. Суть в том что рисуешь тень шагами. Соответственно там где у тебя просветы тени не надо.
Но мне кажется тут уже проще делать в 3д, орто камерой вид сверху.
Просто зашел поныть перед сном какой же я тупой. Весь вечер убил на поиск какого нибудь гайда по поиску пути для врага, а не тупо вектор в сторону игрока + движение, который я пойму. Вот вроде есть гайд по клику мыши, ок, понятно, вот координаты мыши, вот код, вот нода навигация2D, вот тайлы. А как без тайлов? А если я кину просто ящик с колайдером на пути, он его обогнет? А как слежение не за мышкой, а за персонажем? Вроде понятно, вместо положения клика мыши отслеживаем положение персонажа, но как подсосать положение персонажа из другой сцены? А можно ли без NavigationPolygon как то? Почему так сложно, хули я тупой такой? В итоге от нечего делать рисовал себе тайлсет пол вечера, а зачем? А хрен его знает его знает.
>А как без тайлов?
Будь няшей, если найдёшь материалы по теме, поделись с тредиком. Меня вот этот же вопрос интересует, только ещё и с видом сбоку. Просто я к нему пока не приступал, другие части пока разрабатываю.
Вроде что то такое попадалось на глаза. Сам я глянул первую минуту, так что отвечать то ли это что тебе надо не стану. Но враг идет за игроком, запрыгивает на препятствия, в конце видео итог работы лучше видно. Тайлы тут чисто для построения уровня кажись.
https://www.youtube.com/watch?v=WXC8eBCEbho
Гонки клёвый. Посмотрю с утреца, на свежую голову.
>>80044
Как же я тебя понимаю.
Пока гуглил пазфайдинг, нагуглил это. С гуглпереводчиком все понятно. http://gameprogrammingpatterns.com/state.html#finite-state-machines-to-the-rescue
> официальные примеры
Ты про демки что можно скачать через обзорщик проектов? Подобного не нашел, вот прям чтобы демка с преследованием игрока врагами с поиском пути. Да и нагуглить именно такого не смог, все что находил это поиск пути из статичной точки А в точку В или на клик мыши, ну и все это на одной сцене, а мне бы заодно понять как подсасывать из разных сцен координаты и тд, или пазвайдинг прописывается на главной сцене и уже на этот скрипт тянутся ссылки на врагов и игрока или как, ну и практически все на тайлах.
Ну или я жопой как то гуглил все это дело
>все что находил это поиск пути из статичной точки А в точку В
Ну а собственно в этом весь пасфайндинг и есть. Можешь его сделать отдельным модулем и скармливать ему в качестве точки A положение врага, а точки B положение игрока. Возвращая или координаты или действия которые должен совершить враг.
>а мне бы заодно понять как подсасывать из разных сцен координаты
Ну либо делаешь у игрока public метод по которому можно получить его координаты напрямую и запрашиваешь их по необходимости. Либо через какой-нибудь глобальный менеджер который сам отслеживает положение игрока, либо так же запрашивает их по тому же методу.
>Если в двух словах, анонче, что есть стейтмашина и как её проще реализовать?
Блин, попытался расписать и понял, что получается простыня, поэтому попробую совсем вкратце.
1) Есть аватар игрока - player.
2) У player'а есть набор состояний (стейтов) (например IDLE, RUN, JUMP, FALL, DIE) Для каждого состояния есть процедура входа в него, процедура его обновления и процедура выхода из него.
3) Каждый момент времени player может находится только в одном из этих состояний.
4) В основном цикле player'а проводится проверка ввода от игрока и флагов состояния (например, на_земле, в_воздухе, в_воде и т.д.)
5) Далее в зависимости от состояния ввода игрока и флагов состояния определяется переходит ли player в другой стейт или остается в текущем. В зависимости от этого либо происходит выход из одного состояния и переход в другое, либо апдейт текущего.
6) Все передвижения player'а или любые другие действия (вроде взаимодействия с физикой или коллизии) производятся только в обновлениях стейтов. Т.е. к примеру если player находится в стейте RUN, то мы двигаем его вправо влево (в зависимости от ввода). Если в стейте IDLE, то никуда не двигаем, а просто обновляем анимацию. И т.д.
7) Повтор начиная с 4-го пункта.
------------------
Для врагов все то же самое, только вместо ввода от игрока берутся команды от модуля AI. Т.е. можно в принципе взять тот же скрипт player, и посылать ему команды от модуля AI в виде нажатия клавиш и у тебя уже готовый враг, с почти тем же скриптом.
---------------
Ну и применять стейт машину можно вообще для всего. Например какие-нибудь движущиеся платформы. Или даже предметы на уровне. Просто для каждого будет свой набор стейтов и флагов состояния.
---------------
Возможно это не самый оптимальный способ, но один из самых простых которые я знаю.
Так же, дальше уже возможны более крутые варианты вроде совмещения нескольких машин в одном персонаже. Например отдельная стейт машина для передвижения и отдельная для атаки и т.д. Либо переключения с одной на другую.
>Если в двух словах, анонче, что есть стейтмашина и как её проще реализовать?
Блин, попытался расписать и понял, что получается простыня, поэтому попробую совсем вкратце.
1) Есть аватар игрока - player.
2) У player'а есть набор состояний (стейтов) (например IDLE, RUN, JUMP, FALL, DIE) Для каждого состояния есть процедура входа в него, процедура его обновления и процедура выхода из него.
3) Каждый момент времени player может находится только в одном из этих состояний.
4) В основном цикле player'а проводится проверка ввода от игрока и флагов состояния (например, на_земле, в_воздухе, в_воде и т.д.)
5) Далее в зависимости от состояния ввода игрока и флагов состояния определяется переходит ли player в другой стейт или остается в текущем. В зависимости от этого либо происходит выход из одного состояния и переход в другое, либо апдейт текущего.
6) Все передвижения player'а или любые другие действия (вроде взаимодействия с физикой или коллизии) производятся только в обновлениях стейтов. Т.е. к примеру если player находится в стейте RUN, то мы двигаем его вправо влево (в зависимости от ввода). Если в стейте IDLE, то никуда не двигаем, а просто обновляем анимацию. И т.д.
7) Повтор начиная с 4-го пункта.
------------------
Для врагов все то же самое, только вместо ввода от игрока берутся команды от модуля AI. Т.е. можно в принципе взять тот же скрипт player, и посылать ему команды от модуля AI в виде нажатия клавиш и у тебя уже готовый враг, с почти тем же скриптом.
---------------
Ну и применять стейт машину можно вообще для всего. Например какие-нибудь движущиеся платформы. Или даже предметы на уровне. Просто для каждого будет свой набор стейтов и флагов состояния.
---------------
Возможно это не самый оптимальный способ, но один из самых простых которые я знаю.
Так же, дальше уже возможны более крутые варианты вроде совмещения нескольких машин в одном персонаже. Например отдельная стейт машина для передвижения и отдельная для атаки и т.д. Либо переключения с одной на другую.
> что есть стейтмашина
Конечный Автомат или Автомат Конечных состояний (далее КА) - это такой алгоритм, который кагбе гоняет перфоленту с состояниями вперёд-назад по читающей головке. Таким образом КА в каждый момент времени может иметь только одно из набора состояний на твоей виртуальной "перфоленте".
> и как её проще реализовать
Самая простая реализация: В качестве перфоленты энум с состояниями. В качестве читающей головки один огромный свич/мач, в котором перечислены все состояния и дан код (в примере ниже даны функции, которые вызываются, твои функции, которые ты тоже должен описать), что делать при достижении данного состояния, включая переключение состояний.
enum {IDLE, THINKIN, SINGIN, PULLIN, PUSHIN}
var state: int = IDLE
func process(delta: float):
match state:
IDLE: call_idle()
THINKING : call_thinking()
SINGIN : play_song()
PULLIN : pull()
PUSHIN : push()
В ассетлибе же встречаются более сложные машины состояний, основанные на нодах, что делает их совместимыми с редактором движка - ты просто накидываешь состояния в чайлды машине, в панели с иерархией сцены, а стейтмашина в своей работе делает активной выбранную ноду. Соответственно, каждая нода-состояние обладает своим скриптом, работающим, когда она активна, в неё можно насовать своих нод и так далее.
> делаешь у игрока public метод.
То есть просто прописать в скрипте поиска пути для врага "preload("res://Player.tscn")" и так брать координаты нельзя?
Нет. Этой командой ты просто сделаешь копию объекта Player, которая никак не будет связана с той, сценой которая у тебя будет инстанцирована в дереве сцен.
Я хз как у тебя там все устроено, но в простейшем случае, будет что-нибудь вроде:
private Player player;
player = (Player)GetNode("путь к ноде игрока в дереве);
далее либо тупо берешь свойства ноды
private Vector2 coords = player.Position;
либо через метод который сам пропишешь:
private Vector2 coords = player.GetCoordinates();
------------
Опять же я хз как у тебя враг определяет игрока, может быть он получает ссылку через сигнал тогда еще проще вроде:
player = (Player)GetNode(body.GetPath());
(где body содержит ссылку на объект который тригернул сигнал)
------------
>В ассетлибе же встречаются более сложные машины состояний, основанные на нодах, что делает их совместимыми с редактором движка - ты просто накидываешь состояния в чайлды машине, в панели с иерархией сцены, а стейтмашина в своей работе делает активной выбранную ноду. Соответственно, каждая нода-состояние обладает своим скриптом, работающим, когда она активна, в неё можно насовать своих нод и так далее.
Вроде бы просили на пальцах объяснить, я попытался описать сам принцип. Делать можно как хочешь, хоть на нодах все делай, хоть в один скрипт запихивай - принцип одинаковый.
А я твой пост и не комментировал. Я его даже не читал. Я к своему посту дополнение писал так-то.
Насколько я понимаю тут надо шейдеры использовать? Или есть еще какие-нибудь способы?
Тащемта это новое - всего лишь хорошо забытое старое.
И, к слову, ирл такой троллинг очень хорошо работает против истерящих хамов.
Именно что у меня пока ничего ничто не определяет, ибо я годот трогаю день 4ый и первые дни тупо читал туторы в основном, но кажись жопой. Хотеть какой нибудь жирненький учебник на страниц так 1-1.5к с примерами и тд.
1280x720, 0:16
По мне так хоть какая то живость, еще бы один другой кадр вперед на пиксель сдвигался, чтобы изобразить шатание при хотьбе.
Ну так-то интересно, конечно, но я не очень-то ебу, как в этом движке полноценно работать со спрайтами. Как во встарбаунде, шобы все в одном файле лежали, сделать можно?
Спасыба слющий да.
Не, ну серьёзно, как-то даже непривычно, что не обзывают нубом и не посылают сходу нахуй в гугол.
Иди спать. Утро вечера мудренее. Я ушол.
В 3.1 точно не было. Спрайтшиты можно было только в простой Sprite добавлять и анимировтаь их через AnimationPlayer.
А в AnimtedSprite все кадры приходилось по одному закидывать (поэтому я им и не пользовался и не знал что добавили эту фичу)
2. Автокомплит тоже не завезли? Как сделать?
3. Как вообще нормально на C# под годот кодить?
4. Вот этот гайд https://giulianob.svbtle.com/godot-csharp-setup свежий, по нему ок будет, если настроить?
И ещё. Почему везде рекомендуют конвертить сейвы в json (и ебаться с сопутствующим преобразованием)? Не лучше ли исользовать File.store_var(data)? Какие подводные?
С расширением C# вроде бы нормально работает сейчас, но все равно не так удобно, как с документацией внутри годота
> Не лучше ли исользовать File.store_var(data)? Какие подводные?
json - это готовая, признанная во всём мире веб-макак, система сериализации и что важно де-сериализации. С удобным как человеку, так и парсеру форматом.
Со сторе-варом ты будешь ебаться, изобретая свой велосипед сериализации. Не как что-то плохое. Если нравится, ебись. Только почему только сторе-вар? Нарисуй на бумажке свой собственный байтоёбский формат: 4 байта на заголовок, затем, инт, инт, флот, паскальстринг 255 символов, инт, инт, флот, флот, буль, флот, буль. Затем соответствующими сторе_ сохроняй бинарные данные согласно твоему формату, а соответствующими гет_ извлекай из сохранения.
В VSCode автокомплит нормально работает практически везде.
Не работает только в интерполированных строках и в методах вроде CallDefeed и т.д где параметры в кавычках идут. Ну и пути нод тоже ручками вставлять надо будет.
Мне нужно выловить одновременное нажатие двух клавиш, но делать буфер ввода из говна и палок мне не хочется.
А просто задать в настройках проекта комбинацию клавиш и выводить "if Input.is_action_pressed('ui_shift+K')"?
Комбинации буквенных клавиш так задать нельзя. И это немного другое, это нажатие K при нажатом шифте, а не одновременный клац по обеим кнопкам, а мне нужно именно одновременное нажатие, как в тех же файтанах любят делать.
>Это один кадр, или один тик физики?
>Мне нужно выловить одновременное нажатие двух клавиш, но делать буфер ввода из говна и палок мне не хочется.
Я х.з. как правильно, но я обрабатываю весь игровой инпут в Physics_Process. Все работает, все одновременные нажатия отрабатываются. Брат жив зависимость есть.
Я тоже там обрабатываю часть его, но это докидывает непредсказуемую задержку, которая вроде как заметна, особенно с учётом того, что в _physic_process и без того много веселья.
И да, одновременные нажатия регистрируются, но тайминги получаются совсем суровые.
>но это докидывает непредсказуемую задержку, которая вроде как заметна,
Я хз, у меня достаточно динамичный платформер. С физиков в 120 и скоростью передвижения в 180 (180 пикселей в секунду). Никаких задержек не замечал, даже до того как всяческие джамп-буферы и т.д для нажатий прикрутил, все отлавливалось замечательно.
>>81019
>И да, одновременные нажатия регистрируются, но тайминги получаются совсем суровые.
А как ты одновременные нажатия определяешь? Ну, т.е. даже в динамичном файтинге, все равно надо будет буфера прикручивать, т.к. дребезг и прочая хрень. Плюс учитывай, для многих современых стандартных клавиатур, обработка одновременных нажатий - большая проблема. Для некоторых предел уже на 3-х клавишах наступает в определенных рядах.
Ор. какой дребезг в 2к20? Он на уровне микросхемы клавиатуры и драйвера отсекается.
В общем, лучше всё-таки сделать нормальные буфера.
Ну ладно, пока для состояния «proof of concept» управления должно хватить.
Это о-о-очень плохо будет работать, когда у тебя 42 комбинации.
>Если ты не знаешь, что у меня повреждено, пидорас косорукий, зачем бинтовать пытаешься?
Ну, как пожелаешь.
> Это один кадр, или один тик физики?
Если чекать в _process - один кадр
Если чекать в _physics_process - один тик физики
> Мне нужно выловить одновременное нажатие двух клавиш
var a : bool = Input.is_action_just_pressed("my_A_event")
var b : bool = Input.is_action_just_pressed("my_B_event")
var x : bool = Input.is_action_just_pressed("my_X_event")
var y : bool = Input.is_action_just_pressed("my_Y_event")
if a and b and x and y: do_fatality()
Ага, а вот если чекать в любом другом месте, например в _unhandled_key_input — то хрен его разберёт.
Алсо, в такой манере будет много ифов, что не ня, поэтому я заебошил такой говнокод:
new_action = 0
new_action += int(Input.is_action_just_pressed("deg_1"))(9new_action + 1)
new_action += int(Input.is_action_just_pressed("deg_2"))(9new_action + 2)
new_action += int(Input.is_action_just_pressed("deg_3"))(9new_action + 3)
new_action += int(Input.is_action_just_pressed("deg_4"))(9new_action + 4)
(ну и так далее, лишь бы не больше 10). Он выдаёт число вида 123, если нажаты 1, 2 и 3, и вообще ведёт себя вроде как хорошо, даже без буфера.
Но, блджад, всё равно до вывода звука много времени проходит. Надо сравнить со старым билдом, в котором была предыдущая версия костыля. По идее новая параша >>> старой параши, но я уже как-то ни в чём не уверен.
Во первых, не забывай про вакабамарк.
Во вторых, наверняка задержка из-за клавиатуры. Как я понял из своих опытов, там юзается простой текстовый ввод с клавиатур, не знаю, как это называется, но для игор он не подходит.
Ну там видно, где умножение потерялось.
Ввод как ввод, согласно документации, он true только в течении одного кадра, в который нажалось действие, вот только у меня как-то слишком часто получается его триггернуть со своими 120fps. Но и на физику он не завязан, благо её я могу проверить.
Короче, тема мутная, пойду читать мануалы по буферам ввода, оба костыля, по большому счёту, дают недостаточно контроля над инпутом. Да и основная задержка действительно, скорее всего, не в моём коде, и я зря его так пытаюсь напидорасить.
А как вообще делают комбинации клавиш в файтингах? Чисто в псевдокоде, без привязки к движку?
А если он почти проиграл то дребезг ануса?
>поэтому я заебошил такой говнокод
На С# можно было бы посто битовыми флагами такую проверку просто замутить. Но в гдскрипте по моему такого функционала нету.
Это надо быть каким то супербогом чтобы нажать прям одновременно в кадр.
Наверное имелось все же что то в таком духе (псевдокод):
var a_pressed_time : float = 999999
var b_pressed_time : float = 888888
TRESHOLD = 25 #milliseconds
...
process(delta):
var now = get_system_time_msecs()
if (Input.is_action_just_pressed("my_A_event")) :
a_pressed_time = now
if (Input.is_action_just_pressed("my_B_event")) :
b_pressed_time = now
...
if(abs(a_pressed_time - b_pressed_time) < TRESHOLD):
cccombo()
Ну это примерный скелет, так то я за data driven разработку, т,е, будут массивы которые загружаются из файла с настройками где геймдизайнер просто текстом и цифрами описывает.
>if(abs(a_pressed_time - b_pressed_time) < TRESHOLD):
>cccombo()
Зачем вы гланды через жопу достаете, есть же таймеры для этого.
Ты ж не софт для шатлов пишешь. Даже если "раз в сто лет" у тебя таймер на микросекунду объебется, ничего страшного не произойдет.
Таймеры - лишняя сущность. Лишние такты проца, лишние байты оперативки. Особенно ООП-таймеры с накладными расходами на поиск таймера в куче, а потом ещё на поиск метода в нём. В то время, когда у тебя уже есть и работает главный цикл и в нём автоматически подсчитываются микросекунды.
Учись думать как геймдевелопер, залётный ентерпрайзер.
Всё равно нужен будет код, обрабатывающий эти массивы. Я не вижу разницы. Неважно, откуда берутся данные, из файлов на диске в массивы или из числовых констант, логика-то обрабатывающая данные всё равно нужна. Вот я и вопрошаю за эту логику. За алгоритм.
И ещё, датадрайвен выдумали в студии нотидог, когда пытались обойти аппаратные ограничения третьей плойки для анчартеда. Я чот сильно сомневаюсь, что этот лайфхак универсален и везде нужен. Но если чо, я в целом не против описывать игру метаданными, которые игровая логика поднимает из файлов и действует соответствующе. Просто за громкими словами, типа ЕЦС, ДОД, обычно ничего стоящего нет.
Нанофпс там, нанофпс тут. Вот уже и оптимизация. Вот так это и происходит.
Ты слишком байтоеб, выдыхай. Твое дрочево с рассчетом интервала времени и его проверкой каждый фрейм для каждой комбинации, не намного оптимальнее будет.
Вообще если подумать то это же конечный автомат.
(набросал кривоватенько)
Есть всего два способа по нему путешествовать
1) если нажали ожидаемую кнопку одной из комб
2) если не нажали ни одной ожидаемой кнопки и вышел таймаут
Я им в принципе не доверяю. Может не создаться объект таймера, может зависнуть, может не вызвать событие, может вызвать событие повторно.
Таймеры, наоборот, экономят такты проца, бузивайтер.
ну и 3) нажали кнопку, но не ожидаемую
Хочется бить в ебало за такие посты. Вот такие мудаки сидят в студиях, которые выпускают игры по графону на уровне скайрима 2011 года, но тормозящие на топовых пеках.
А раз это конечный автомат, то можно попробовать реализовать его на встроенных инструментах редактора - анимации с вызовом метода, анимационное дерево со стейтмашиной. Ммм... Звучит как челендж. Завтра попробую.
Можно, но я бы все же генерил его автоматически из данных про тайминги ударов.
У-у какие мы злые. Ты лучше подумай на досуге, о том что хуйней маешься и оптимизируешь совсем не то, что нужно.
Ты лучше подумай на досуге, о том что хуйней маешься и поучаешь в интернетах людей умнее и старше себя, щегол, блять. Выглядит уёбищно.
Так это работает, чёрт возьми, хоть тайминг и получается жестковат. В реальных файтингах как раз все движения считают в кадрах, коих раньше было по-консольному немного, и там, вполне вероятно, так в прошлом и делали. Сейчас, наверное, всё-таки от ФПСа это дело отвязали, и точно так же отдельно считают такты физики.
>>81065
Ну-у-у-у не то чтобы совсем... А что, есть готовые решения?
>Ну-у-у-у не то чтобы совсем... А что, есть готовые решения?
Если конкретно для миди-клав, то видел, что-то подобное в ассетах. Но сам не пробовал. Там чере миди-инпут-ивенты наверное все делается.
---------
Вообще, пытаться такое на обычной клаве делать, гиблое дело. Т.к. у большинства пользователей стоят стандартные клавы, для которых часто даже 3 одновременно нажатые клавиши обработать уже предел.
> наверное
Выше же прямым текстом с примерами кода написали, что сейчас делают с вычисляемыми в реальном времени задержками. Это и правильнее, ибо железо у всех разное.
После каждого нажатия, считанного в текущем фрейме, стейтмашина инпута переводится в режим ожидания следующего нажатия, если нажатие не происходит за сконфигурированное время в миллисекундах, стейтмашина сбрасывается к началу. Если прилетело ошибочное нажатие, которого не нашлось в списке комбо, она так же сбрасывается на начало. Стейтмашина осуществляет поиск по списку известных на данном этапе игры комбо, и если находит, передвигается по этому комбо на следующий шаг, в дальнейшем поиск будет происходить из ограниченного первыми кнопками набора комбо. Если игрок выполнил все нажатия кнопок вовремя, генерируется сигнал комбо, или вызывается функция, приписанная к выбранному комбо в метаданных, тут уже на вкус и цвет.
Накидал блок-схему, но забыл тайм-аут на ней показать. Ну, пусть это будет домашним заданием тебе.
Во-первых, откуда у меня пользователи, лол? Во-вторых хоть узнают, что такое NKRO. Ну а в-третьих даже офисные 3KRO клавиатуры в наши дни часто разведены так, что стрейфиться влево, нажимая E, и перезаряжаясь в приседе на них всё-таки можно.
Демка с миди-инпутом работает примерно
>>81142
Ладно-ладно. Я не знаю, как устроены файтинги сейчас. Но когда-то они точно делались через кадроёбство, оттуда и рассказы про кадры неуязвимости.
Алсо, твой автомат не сренькнет, если в одном кадре два нажатия?
> Алсо, твой автомат не сренькнет, если в одном кадре два нажатия?
Если всё учесть в коде, то не сренькнет. Согласно диздоку, как должна действовать игра при одновременном нажатии? Вот так и реализуешь. Надо, чтоб все одновременные клавиши добавлялись в стек? - делаешь. Надо чтоб только первая? - делаешь. Надо чтобы сбрасывалось на старт? - делаешь.
>Ну а в-третьих даже офисные 3KRO клавиатуры в наши дни часто разведены так, что стрейфиться влево, нажимая E, и перезаряжаясь в приседе на них всё-таки можно.
Не на всех сочетаниях клавиш. Это сильно рандомно. Она может обработать к примеру одновременно "влево+вверх+Z+C", а вот "вправо+вниз+X+C" уже нет.
>681150
>Во-вторых хоть узнают, что такое NKRO
Нет, просто будут думать "плохо сделано, тупо".
Технически, вообще не стоит рассчитывать. более чем три нажатия. А все, что больше делать через последовательность, а не одновременность. Либо сразу писать - "покупайте гейпад".
-----------
А я тогда в системных требованиях буду писать «клавиатура с поддержкой 6KRO и выше», лол.
>Ну а в-третьих даже офисные 3KRO клавиатуры
И да, в основном сейчас стандарт это 6KRO для офисных и дешевых клав, но и они через жопу сделаны. Сейчас вот только проверил, на простом логитече. "влево+верх+A+S+D+F" нажимаются свободно - 6 нажатий. А вот если поменять влево на вправо, то нажимаются только 4 нажатия "вправо+вверх+A+S", а кнопки D и F не обрабатываются.
Так что советую перед тестом своей игры, протестировать конкретно клавиатуру, все ли комбинации тобой задуманные она потянет. А то будешь пердолиться с отладкой кода, а дело будет даже и не в нем.
----------
Алсо у USB NKRO тоже свои приколы есть. Насколько я понимаю там опрос часто через какие-то костыли делается. Т.к. проблемы с самой спецификацией USB (где-то на хабре статья была). Некоторые клавы просто тупо делают дубли себя в системе и притворяются сразу 4-мя клавиатурами, чтобы засылать кучу нажатий. Ну и задержка может присутствовать, так что ты вполне возможно не будешь получать каждый тик из своих 120, нажатия.
Да у меня-то игросральная механика с NKRO и 1000Hz опроса. Ровно такая, которая сама себя дублирует в диспетчере устройств, и никаких проблем.
Комбинаций я не так уж и много собираюсь впилить, и длинных среди них не планируется, так что страдать будут только самые инвалидные клавы.
Да это всё заебца, когда пилишь игру для себя. Но не стоит забывать, что играть в твою инди-игру будут нищеброды (Потому что состоятельные парни будут играть в ААА-экшоны от бохатых студий, прфы в веге). Такшта, думой.
А зря. Ван Гог прекрасно знал, что его картины никто покупать не будет, и ничего. Мы с тобой, впрочем, нихуя не вангоги.
Как задашь правила перехода в автомате, так он и будет переходить, тащемта.
https://godotengine.org/article/csharp-vs-and-vscode
Пацаны. Там, это, нормальный дебаг для Годота под VSCode подогнали, для тех кто в C# пишет.
Плюс автодополнение улучшили, теперь пути к нодам и прочие параметры в кавычках тоже подхватываются на лету (правда интерполированные строки все так же сосут)
Почему нельзя сделать нормальную генерацию проекта для студии, а не через жопу с makefile? Хуан же так доказывал какое крутое это scons
Вот я хочу пошагово пройтись по коду - как блядь это сделать?
и ни строчки как это настроить. У меня например не раб, хотя я плагин поставил
>и ни строчки как это настроить. У меня например не раб, хотя я плагин поставил
-------
1) Пик 1
2) Пик 2 (сделать для каждого проекта, либо скопировать сгенерированный json в каждый проект, где нужен дебаг, в каталог .vscode)
3) Пик 3
4) Перезагрузить годот и vscode
5) Запускаешь годот, открываешь проект в vscode, жмешь F5 и радуешься.
А, ну я х.з. тогда - не пользуюсь ею для годота.
Пока никак
The minimum required Godot version is 3.2.3, which is not yet released at the time of this writing. While the extension may work to some extent with Godot 3.2.2, there might be issues. Also Godot 3.2.2 can't launch Visual Studio when selecting a script.
Да, я понял уже, посмотрел формулировку.
Анон, а есть какие нибудь open source проекты годот игр под андроид? Конкретно какое-нибудь 2Д с кучей разных объектов (враги, предметы и т.д.)
Хочу сравнить со своим проектом и понять, что я делаю не так, потому что слишком сильно проседает производительность при определенных условиях.
Я пробовал такие сравнения делать, но нихуя не понел. Чужой проект он как чужая женщина. Карочи, разбивай свой проект на модули и проводи модульные тесты. Их не зря придумали.
К обычному спрайту можно карту нормалей прикрутить. Карта нормалей должна соответствовать прикрученной к нему же текстуре. Затем в параметрах анимации указываешь, сколько строк и столбцов в твоей текстуре и получаешь готовый для анимирования анимплеером объект. Разумеется, речь идёт о том, что текстура и карта нормалей это СПРАЙТ-ШИТ, содержащий фреймы анимации.
>Ну а в-третьих даже офисные 3KRO клавиатуры в наши дни часто разведены так
что я не могу одновременно всплывать (space) и двигаться вперёд-влево (W+A). Вперёд-вправо (W+D) могу.
Могу ошибаться, ибо опыта не так много.
И чего ты от нас ждешь? Что все бросятся тебя уговаривать? Тут у каждого свой самописный движок за плечами, ничем не удивил.
>Пользуешься 3.2.2 с батчингом и глес2?
Да. 3.2.2 стейбл моно. (пользовался ей еще с первых бет)
----
Я уже честно говоря сильно склоняюсь забить хер на этот ебучий андроид и ограничится пк + веб. Там проблем нету.
------
>>81457
>Я пробовал такие сравнения делать, но нихуя не понел. Чужой проект он как чужая женщина. Карочи, разбивай свой проект на модули и проводи модульные тесты. Их не зря придумали.
Да разобраться не проблема, я всякого говнокода в свое время повидал.
Там же некуда разбивать. По факту один простой уровень на тайлмапе (2Д платформер). Аватар игрока на стейт машине. Весь код на C#.
Сделал объект collectable (монетки, алмазы) с простейшей стейт машиной. Они могут лежать на месте, падать вниз и собираться игроком. Когда их на уровне несколько штук, вроде все работает. Если же их штук 30 закинуть, то начинаются дикие тормоза. Хотя я их уже упростил до предела, выкинул анимацию (хотя по рендеру там всего 29 дроуколов на все уходит), почти все поля в статику перевел, убрал всяческие проверки и т.д. Все равно, тормоза уменьшаются только если совсем коллизии и взаимодействие убрать (но нахрен мне тогда такие объекты нужны, я хотел сделать, что-то вроде колечек в Сонике)
Я просто думаю если я еще и врагов добавлять начну у которых намного сложнее все, чем у монет будет организовано, то вообще пиздец будет. Притом, что на пк и даже на вебе таких тормозов нету.
Вот я и хочу посмотреть чужие проекты. Как-то же народ под андроид игры на годоте делает, может у меня затык в чем-то одном (очень сильное подозрение у меня на сам тайлмап и проверку коллизий с ним), либо там вообще все по другому делать нужно, может там модули какие нужны, я х.з.
Коллизии на физическом движке что ли?
А они у тебя между собой случайно не коллизятся? Тогда очень легко улететь в O(n2)
То есть правильно понял что выделенный регион карты нормалей следует за регионом текстуры? Прост еще не тестил сам, только проснулся.
Это то видно, уже пихал туда одиночную нормал мапу, прост не знал что туда тайлсэт нормал мап запихать можно, чтобы под каждый кадр спрайта своя нормал мапа была.
Не думаю, что есть синхронизация физики. Буллетовская физика недетерминирована, поэтому если запустить ее на двух разных компах она рассинхронизируется. В Годоте есть RPC, что означает, у тебя будет сервер который все считает, и клиент которому сервер удаленно вызывает функции. Если ты в эти функции вынесешь движение объектов, то должно получиться. Не помню, что там по интерполяциям из коробки.
В 3.2.2. впилили новую подсистему мультиплеера. В чейнджлоге подробности.
Надо завести переменные окружения
SCONS_CACHE=C:/путь_к_папке_где_хочешь_хранить_кэш
SCONS_CACHE_LIMIT=5000
Лимит в мегабайтах, т.е. в моем варианте 5Гб. Можно поставить 10-15 если есть место. Стереть можно в любой момент.
>Коллизии на физическом движке что ли?
>А они у тебя между собой случайно не коллизятся?
Между собой нет. Они мало того, что отдельны друг от друга, но и находятся на разных слоях.
Но дело похоже все таки в физическом движке, а именно в том, что большое количество kinematic2dbody + движение через move_and_.... и ведет к затыкам. Я попробовал их в простые объекты переделать и двигать напрямую, вычисляя коллиизии через обычные рейкасты, намного лучше производительность стала.
По моему, это очевидно. Впрочем, всегда не лишне добавить указание на фичу в хинт. Хуан, сделой!
> намного лучше производительность стала
Естественно. Физический объект помимо коллизий ещё кучу физических параметров вычисляет. Каждый кадр физики! Так что, если надо просто систему частиц запилить, со своим, управляемым поведением, то в данном конкретном случае не грех и велосипед изобрести.
Если у тебя монетки - окружности, то там можно еще быстрее проверять, через Vector3.distance_squared_to()
Поясни, плиз, за квадрат дистанции. Я курил мануалы, но так и не понел. В чём геометрический смысл?
Я только понял, что квадрат дистанции сложная задача и реализован на плюсах с выводом вычисляющего этот квадрат метода в АПИ.
Чот почитал туторы, и кажись тут тоже свои велосипеды на синхронизацию физики мутить придётся.
Жаль BYOND (если кто слышал) такое говно, но вот то что он автоматически сцены всех игроков синхронизирует это в нём было охуенно.
Хотя в роадмапе у них такое есть, если это то о чём я думаю
Попробуй покурить мануалы по синхронизации физики на чистом буллете. Возможно, после них ты сможешь получить доступ к его фишкам через синглтон-обёртку PhysicsServer?
Уже есть. Еще предложения?
Смысл в том, что расстояние между двумя точками (а в случае кругов это то же самое, только уменьшенное на радиус кругов) равно корню из некоей формулы. Но вычислять корень дорого, а поскольку для этой задачи нам не.важно найти расстояние, а только факт что sqrt(x)<d, то мы заменяем на sqrt(x)×sqrt(x)<d×d, т.е. x<d2, т.е. distance squared. Где d зачастую константа (например когда хитбокс игрока и хитбокс монетки всегда постоянного размера)
Во, теперь понял. Анон - лучший учитель!
Это копия, сохраненная 13 декабря 2021 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.