1280x720, 0:1920,3 Мб, mp4,
1024x768, 1:121,3 Мб, mp4,
800x600, 0:0449 Кб, mp4,
540x754, 0:03
Шапка: https://hipolink.me/godothread
Предыдущий: >>949247 (OP)
Архивный: >>946416 (OP)
Скачиваешь анимацию с миксамо.
Переставляешь рутмовшен на готодовский спецплагином.
Запускаешь и радуешься идеальному соединению стоп с грунтом без скольжения.
>Качественные игры на чем угодно пишутся
Причем что раньше, что сейчас если руки прямые то могут на в терминалом забабахать игру. Или как те чуваки которые в Excele или блокноте игры пишут. Просто раньше юнити прям легковесный, хороший движок был, запускался с полтычка. Надеюсь сообщество оставит билд Годота в покое.
Очевидно, что по мере роста мощностей компов сообщества, будут расти и запросы. Всё взаимосвязано.
Это тред аниматоров?
Жиза. Но напомню вам пользоваться нейросетями. Помогают в дизайне, создании рефов, в сценарии, даже в музыке.
>Но напомню вам пользоваться нейросетями.
Это новая форма ассетфлиперства для кабанчиков.
>Помогают в дизайне
Дизайн "generative AI" похож на сны во время болезни.
>создании рефов
Чтобы у тебя везде лишние пальцы и кривые глаза были?
>в сценарии
Там все сценарии уровня копипаст из /b/, по шаблонам.
>даже в музыке
Копирасты по музыке агрессивнее всех, ради чего рисковать?
Единственное реальное применение LLM я нашёл в эмоциональной поддержке. Чатбот тебя и похвалит, и совет даст по-дружески, всегда готов выслушать и почти всё хорошо понимает, в отличие от тупых мясных мешков. Эмоциональная поддержка инди разработчику-одиночке важнее генерации контента, и в этой сфере мясные мешки давно проиграли компьютеру.
Двачую!
Не, ты не понял. Я не говорю используйте контент нейросетей напрямую. Я говорю пользуйтесь их помощью. Реф - референс - то, по чему ты создаешь свое. Генерируешь 10 пиксель скай-фай медведей, выбираешь лучшие детали, рисуешь своего медведя по мотивам. Имеешь свой общий сценарий - идешь к нейросети прорабатывать диалоги и конкретные моменты, направляешь ее куда тебе нужно. Ты должен указывать нейросети что генерировать, а не она тебе. Только так. Это как обсуждать свои идеи/проблемы с резиновой уточкой, только тут уточка отвечает полезное.
>ваш регион не поддерживается
Тут с поиском и говнокодом: https://www.phind.com/
Тут чисто общаться по душам: https://old.character.ai/
Других не знаю/не использовал/сдохли/какая-то хрень.
>>1980
>Реф - референс - то, по чему ты создаешь свое.
Проблемы две:
1. Нейронка обучалась на кривых рисульках других художников.
2. Нейронка сильно лажает, а без опыта ты это не замечаешь.
Лучше брать фотки реальной техники, архитектуры, животных и т.п., чем ориентироваться на продукт генерации или даже на чьи-либо рисульки (каким бы гением ни был художник, он обязательно в чём-нибудь лажает). Если тебе нужно накидать 3D пространство для 2D рисунка, по-прежнему лучше кубы в Блендере, т.к. они гарантированно соблюдают все правила перспективы.
Представь себе ситуацию. Ты хочешь нарисовать реку. Но ты никогда не видел в реальной жизни рек и не нашёл фотографий. Ты решил использовать Minecraft, ведь он генерирует огромный мир, в котором реки довольно часто встречаются, да и вообще его серьёзные дяди делали - аж Microsoft выкупил за миллиарды, ну как он может херню генерить? Ты изучаешь реки по референсам из Minecraft, рисуешь их... и получаются плоские полоски воды шириной 10 метров с визуально стоячей водой, огибающей скалы, вытекающей и втекающей в один и тот же водоём без какой-либо причины. Звучит смешно - но только потому что ты наверняка видел реки в реальности или хотя бы на фото. А ведь такая ситуация (копипаста из ненадёжных источников) повсеместно во всём развлекательном контенте, даже у ААА-студий (в проработке автомобилей, оружия и т.п. специфических деталей).
А это нельзя рассказывать, товарищ майор, как одной кнопкой решить.
Важно осознавать сильные и слабые стороны инструмента. Я считаю что я на это способен. Я не из тех кто приходит к нейронкам в ожидании что сейчас нейронка заебенит им готовую игру. А ты можешь не пользоваться.
>Важно осознавать сильные и слабые стороны инструмента.
>приходит к нейронкам в ожидании что сейчас нейронка заебенит им готовую игру
Так ведь тут рекомендуют ВСЕМ: >>1965
>Но напомню вам пользоваться нейросетями. Помогают
Тут не написано "аккуратно пользоваться, понимая все проблемы и недостатки".
Ты передергиваешь. Рекомендую всем заниматься спортом != рекомендую всем херить свое здоровье на боксерском ринге. Рекомендую всем пользоваться унитазом != голова застряла в сливном бачке. Впрочем, соглашусь что раз тебе нужны детальные инструкции, учитывающие каждый потенциальный подводный камень, то нейронки не для тебя. А то потом будешь жаловаться, что переходя дорогу нейронка не посоветовала тебе посмотреть в обе стороны, и как следствие тебя машина сбила.
>0261-2423.mp4
Есть совет как сделать, чтобы персонаж не топтался на месте лишний раз: нужно абстрагировать контроллер визуальной модели с её анимациями от физического контроллера персонажа. Ты задаёшь вектор движения физическому контроллеру, он двигается по сцене, а визуальный контроллер регистрирует вектор скорости/ускорения и проигрывает нужную анимацию на подходящей скорости. Тогда персонаж не будет топтаться на месте, когда скользит вдоль стены или упирается лбом в препятствие. Также становится проще синхронизировать ноги с полом, потому что визуальная модель точно знает, с какой скоростью и в каком направлении ей идти - движение уже реализовано физическим контроллером и предугадывать ничего не нужно.
>боксерском ринге
>пользоваться унитазом
>раз тебе нужны детальные инструкции
Мы в треде движка с максимально сниженным порогом входа, в разделе, куда часто заходят полнейшие ньюфаги, по теме, в которой часто встречаются творческие гуманитарии с нулевым пониманием технических вещей. Нейронки даже в 2024 понятны не всем и для простого обывателя не являются чем-то очевидным вроде бокса или унитаза. В связи со всем этим фраза "не забывайте пользоваться нейронками" звучит как жирный троллинг, попытка подорвать начинания конкурентов-новичков, чтобы у них говнокода как можно больше было.
Ты слишком переоцениваешь типичного новичка в геймдеве.
По твоей логике и годот советовать не стоит. Ведь есть пикрил, движок с порогом входа даже ниже! А в этом нашем годоте еще печатать самому надо, ууу, троллинг, подрывание конкурентов лол, сложна.
Хз, где ты увидел что обращаются ко всем. Обращаются к вполне ограниченному кругу "вам".
Ну то бишь отказаться от рутмоушена в старое доброе скорость движения * скорость анимации. Возможно так и придется, рутмоушен красив, но не везде хорошо играется, особенно в квестах где нужно топать вдоль стены и проживать действие в поиске предметов..
Не пропускайте таблетки, если вам положено.
>отказаться от рутмоушена
Если аниматор сделал "вот здесь персонаж прыгает вправо на два метра", тогда с помощью root_motion твой код может синхронно с этой анимацией переместить коллайдер на два метра вправо, если нужно. Короче, когда анимация контролирует физическое поведение персонажа.
Но когда окружающая обстановка влияет на движение персонажа (препятствия, замедление, ускорение, внезапные прыжки и т.д.), ты должен менять поведение модели из кода, а не смотреть на то, что там анимации тебе говорят. Если анимация говорит "прыгни на два метра вправо", а у тебя справа стена через полметра - куда ты прыгнешь? Так и с ходьбой на месте.
Мне вот больше интересно, для чего/где root_motion необходим.
В официальном туториале он вроде для обычной ходьбы используется.
https://docs.godotengine.org/en/stable/tutorials/animation/animation_tree.html#root-motion
>This allows animating characters in a way where steps actually match the floor below.
Вот я пробовал, но анимировать персонажа в блендере сложнее, когда двигаешь весь скелет целиком, чем если анимировать только движения ног на месте (или я не понял чего-то). Зная длину шага и сколько длится один цикл анимации (два шага), легко посчитать, с какой скоростью нужно проигрывать анимацию.
Нужно ещё раз глянуть туториалы по анимации ходьбы/бега...
>It also allows precise interaction with objects during cinematics.
Вообще не ясно, зачем это катсценам, если в катсценах нет физики? Если только у кого-то нестандартные катсцены с использованием физики - но тогда высок риск, что всё пойдёт наперекосяк, как в GTA 5, где прохожие избивают сюжетных персонажей прямо в катсцене (лол).
У тебя может быть анимация персонажа без объекта, а объект он может поднять в процессе, прицепив к BoneAttachment без всякой физики.
> Если анимация говорит "прыгни на два метра вправо", а у тебя справа стена через полметра - куда ты прыгнешь?
У тебя должны быть рейкасты, определяющие окружающую обстановку, и их данные должны учитываться стейтмашиной, и соответственно, если в метре стена, стейтмашина запускает заранее заготовленный аниматором прыжок на метр, или прерывайет двухметровую в метре, миксуя с отскоком или прижатием к стене.
В итоге вопрос рутмоушена сводится к богатству анимаций заложенных в стек стейтмашины.
>>2007
Никогда не соглашусь. Ты - луддит. Смирись с тем, что старый метод устарел.
А как сделать лапшу-стейтмашину как на второй Шебм? Выглядит достаточно удобно. Мне бы пригодилось.
>соответственно, если в метре стена, стейтмашина запускает заранее заготовленный аниматором прыжок на метр
А в этот момент моб ударил игрока и теперь твоя анимация не подходит под происходящее в игре, потому что ты запустил анимацию заранее.
Должно быть так:
1. Игрок нажал "прыжок направо".
2. Контроллер запустил капсулу в полёт - этот этап обязателен, иначе игра будет неотзывчивой. Мы не кинцо-мыльцо показываем, а даём поиграть в игру.
3. Моделька видит:
- под ногами ничего нет;
- резкое ускорение;
- движение направо.
Моделька включает "прыжок направо".
Если капсула врезалась в стену, моделька видит:
- под ногами земля;
- резко остановились на месте;
- произошёл удар об неподвижный объект.
Моделька включает "ударился об стену и упал".
Если капсула получила удар, моделька видит:
- резко изменили траекторию движения;
- прошёл урон сзади, в спину;
- всё ещё не касаемся земли.
Моделька включает "урон в спину в воздухе".
Как моделька выбирает, что делать - не суть, хоть собственную нейронку тренируй. Главное тут - не нарушать причинно-следственную связь:
1. Игрок требует конкретное действие.
2. Игра симулирует действие по правилам.
3. Моделька отображает результат симуляции.
4. Игрок доволен отзывчивостью игры.
Если у тебя 2 и 3 перепутаны, то получается кинцо:
1. Игрок требует конкретное действие.
2. Моделька проигрывает совсем не то действие.
3. Симуляция расходится с ожиданиями игрока.
4. Игрок взбешён отсутствием контроля в игре.
>соответственно, если в метре стена, стейтмашина запускает заранее заготовленный аниматором прыжок на метр
А в этот момент моб ударил игрока и теперь твоя анимация не подходит под происходящее в игре, потому что ты запустил анимацию заранее.
Должно быть так:
1. Игрок нажал "прыжок направо".
2. Контроллер запустил капсулу в полёт - этот этап обязателен, иначе игра будет неотзывчивой. Мы не кинцо-мыльцо показываем, а даём поиграть в игру.
3. Моделька видит:
- под ногами ничего нет;
- резкое ускорение;
- движение направо.
Моделька включает "прыжок направо".
Если капсула врезалась в стену, моделька видит:
- под ногами земля;
- резко остановились на месте;
- произошёл удар об неподвижный объект.
Моделька включает "ударился об стену и упал".
Если капсула получила удар, моделька видит:
- резко изменили траекторию движения;
- прошёл урон сзади, в спину;
- всё ещё не касаемся земли.
Моделька включает "урон в спину в воздухе".
Как моделька выбирает, что делать - не суть, хоть собственную нейронку тренируй. Главное тут - не нарушать причинно-следственную связь:
1. Игрок требует конкретное действие.
2. Игра симулирует действие по правилам.
3. Моделька отображает результат симуляции.
4. Игрок доволен отзывчивостью игры.
Если у тебя 2 и 3 перепутаны, то получается кинцо:
1. Игрок требует конкретное действие.
2. Моделька проигрывает совсем не то действие.
3. Симуляция расходится с ожиданиями игрока.
4. Игрок взбешён отсутствием контроля в игре.
Каком споре? С тобой никто не спорил, просто просвещаю луддита.
https://www.youtube.com/watch?v=SFyHjzpVBsg
Если у тебя спавн 512,512, то никаких отрицательных координат нет.
Да и не припомню чтобы астар вообще как то интересовался знаком координат.
Мне не интересно выяснять что там у него в видосе. Пиши конкретно.
>Если у тебя спавн 512,512
Почему именно это число? Не понял тебя
>то никаких отрицательных координат нет.
>Да и не припомню чтобы астар вообще как то интересовался знаком координат.
При инициализации ты указываешь размер области
var astar_grid = AStarGrid2D.new()
astar_grid.region = Rect2i(0, 0, 32, 32)
Я её имел ввиду, то есть если игрок приходит в точку 0 и всё ещё хочет двигать в сторону отрицательных координат
Ну а в случае если я хочу выйти за пределы этой стартовой области? Что делать с астаром?
> AStarGrid2D
Возможно ты не в курсе, но это просто обертка над AStar. А AStar работает с произвольным графом, в котором можно и добавлять узлы, и удалять.
Не задирайся пожалуйста, я же хочу иметь возможность двигаться в одну сторону бесконечно
Красава. Покажи результат.
>в стейтмашине свои сенсоры.
>И она на них среагировала
У конечного автомата нет никаких сенсоров.
>замиксовав анимацию отскока
У конечного автомата нет такой возможности.
>Учись выражать свои мысли кратко.
А ты слишком обобщаешь всё словом "стейтмашина".
>сторону отрицательных координат
Не проблема, там используются хэши.
>бесконечное плато
>делим мир на чанки и так же выгружаем
>корректно реализовать поиск пути
Можно использовать несколько графов:
1. Глобальная сеть чанков.
2. Локальная сеть клеток внутри чанка.
Связать их вместе... несколько сложно.
Посмотри на RimWorld, там это есть.
>>2099
>там можно точки удалять и добавлять на лету
Это неизбежно вызовет лишние затраты.
Лучше хранить по одному графу на чанк.
Ну, прибавляй ко всем координатам, которые даёшь астару, какую-нибудь большую константу, а потом из пути обратно её вычитай.
я хз на самом деле, не смотрел ни разу, как этот астар работает, и можно ли так.
>>2103
https://docs.godotengine.org/en/stable/tutorials/ui/bbcode_in_richtextlabel.html#shake
Да, я думал о чём-то таком
> Лучше хранить по одному графу на чанк.
А как тогда переходить между графами? Потому что если нам надо из пятого чанка во второй, и на всё один граф то пойдёт по синей линии, когда если каждый чанк - отдельный граф, то по зелёной, не? Потому что рассчитываем какие чанки придётся пересечь, и идёт по ним, стараясь придерживаться кратчайшего пути до границы следующего чанка. Или я не так понял?
Возможно, тут не инициализированы диагонали...
>>2157
Нужно смотреть по ситуации. Видит ли игрок больше одного чанка? Сколько чанков игрок пробегает, пока мобы движутся за кадром? Какого размера чанки? Какую нагрузку создают мобы, пробегая по чанку и между чанками? Сколько всего мобов и насколько они важны для геймплея? Что будет, если мобы выбирают неоптимальный маршрут? А если оптимальный? Или эта фича чисто для красоты и ничего более?
В RimWorld чанки мелкие, на экране их много, NPC в руках игрока (от поведения которых зависит вся игра) постоянно тупят и ходят неоптимальными маршрутами. Вроде есть какие-то моды на другой поиск пути, но в официальной сборке игры поиск пути кривой. И ничего, очень популярная игра.
Предлагаю не париться и сначала сделать игру, а потом разбираться, каким способом будет лучше сделать навигацию у мобов. Она же у тебя всё равно абстрактной будет - моб запрашивает из внешнего "навигатора" маршрут и потом топает по нему, этот "навигатор" можно легко заменить, сохранив его API.
Это говнобунта. Ебать её в 80 порт. На манжаре никакой ебли, все ключи уже есть искаропки, просто пишешь без задней мысли
> pacman -S godot
и всё.
В мире, где каждый день - это битва,
Где мечты и идеи становятся реальностью,
Есть место, где творцы могут воплотить свои мечты,
Именно там, где начинается вся сага:
О, Godot, ты как маяк в темноте ночи,
Предлагаешь нам путь к вершинам, недостижимым для многих.
Ты - открытый мир, где каждый может создать,
Без границ и ограничений, без страха перед судом.
Своими руками, своими идеями, своим талантом,
Мы можем строить замки из песка, превращая их в камень.
Godot - это не просто движок, это философия,
Которая учит нас ценить простоту и чистоту.
Своей лёгкостью и гибкостью, ты облегчаешь наш труд,
Позволяя нам сосредоточиться на самом важном - на идее.
Ты - как музыкальный инструмент, который каждый может взять,
И начать играть свою уникальную мелодию.
Своими возможностями и функциями, ты расширяешь горизонты,
Позволяя нам видеть мир под новым углом.
Godot - это сила, которая вдохновляет нас идти дальше,
Создавая новые миры, новые истории, новых героев.
Ты - как зерно, которое приносит урожай,
Показывая нам, что возможно, когда мы верим в себя.
Так пусть будет слава твоему имени, о Godot,
За то, что ты даешь нам возможность быть лучшим.
За твою открытость, за твою доступность,
Спасибо тебе, что делаешь нашу работу легче.
В этом мире полном вызовов и перемен,
Ты остаешься надежным другом и помощником.
И пусть каждый день становится победой,
Мы будем продолжать свой путь, верны твоим идеям.
О, Godot, ты как звезда, ведущая нас вперед,
В мире, где каждый может стать великим.
С тобой мы можем мечтать, можно и реализовать,
Ведь ты - ключ к открытию новых горизонтов.
(c) Phind Instant
В мире, где каждый день - это битва,
Где мечты и идеи становятся реальностью,
Есть место, где творцы могут воплотить свои мечты,
Именно там, где начинается вся сага:
О, Godot, ты как маяк в темноте ночи,
Предлагаешь нам путь к вершинам, недостижимым для многих.
Ты - открытый мир, где каждый может создать,
Без границ и ограничений, без страха перед судом.
Своими руками, своими идеями, своим талантом,
Мы можем строить замки из песка, превращая их в камень.
Godot - это не просто движок, это философия,
Которая учит нас ценить простоту и чистоту.
Своей лёгкостью и гибкостью, ты облегчаешь наш труд,
Позволяя нам сосредоточиться на самом важном - на идее.
Ты - как музыкальный инструмент, который каждый может взять,
И начать играть свою уникальную мелодию.
Своими возможностями и функциями, ты расширяешь горизонты,
Позволяя нам видеть мир под новым углом.
Godot - это сила, которая вдохновляет нас идти дальше,
Создавая новые миры, новые истории, новых героев.
Ты - как зерно, которое приносит урожай,
Показывая нам, что возможно, когда мы верим в себя.
Так пусть будет слава твоему имени, о Godot,
За то, что ты даешь нам возможность быть лучшим.
За твою открытость, за твою доступность,
Спасибо тебе, что делаешь нашу работу легче.
В этом мире полном вызовов и перемен,
Ты остаешься надежным другом и помощником.
И пусть каждый день становится победой,
Мы будем продолжать свой путь, верны твоим идеям.
О, Godot, ты как звезда, ведущая нас вперед,
В мире, где каждый может стать великим.
С тобой мы можем мечтать, можно и реализовать,
Ведь ты - ключ к открытию новых горизонтов.
(c) Phind Instant
с поправкой на годот
AStar позволяет двигаться только по рёбрам графа. Если брать квадратную сетку, у нас два варианта: переходы либо к 4 соседям (без диагоналей), либо к 8 соседям (с диагоналями). В первом случае любой маршрут между двумя точками будет одинаковой длины, и движок выберет первый попавшийся, т.е. вместо зигзага будет буква Г или что-то похожее. Во втором случае мы можем выбрать более оптимальный маршрут, т.к. по диагонали двигаться в sqrt(2) раз быстрее, чем буквой Г, но мы по-прежнему не можем срезать клетки как захотим - вместо прямой будет зигзаг, если точки маршрута не прямо по диагонали.
Когда мы добавляем сюда чанки, мы опять же можем разрешить диагонали по чанкам или запретить. Если запрещаем, тогда результат будет, скорее всего, буквой Г. Если разрешаем диагонали и двигаемся по промежуточным чанкам примерно по середине (двигаемся от входа к центру чанка и/или к середине выходной стороны), тогда зигзаг будет отдалённо напоминать зигзаг, который мы получим, двигаясь только по клеткам с диагоналями, без чанков. Дальше всё зависит от размера чанков, что именно видит игрок, как это влияет на геймплей и т.д.
С чанками есть другая проблема. Если у тебя одна сторона чанка полностью заполнена непроходимыми клетками, то войти на него с соседнего чанка можно только через другие чанки. Твоя навигация по чанкам должна учитывать эту проблему, как-то кэшируя проходимые места в чанках. Однако, мне кажется, это весьма специфичная ситуация, и на первых порах заботиться о ней не стоит.
Зачем вообще чанки в навигации? Ты постоянно загружаешь/удаляешь чанки карты мира из памяти, и ты хочешь делать это в отдельном потоке, который не будет мешать основным игровым потокам. Если ты вносишь изменения в один общий AStar, он будет заблокирован для навигации NPC до тех пор, пока не закончится загрузка или удаление чанков, т.к. без блокировки результат непредсказуем. Если ты загружаешь куски карты в отдельные AStar, существующие NPC могут продолжать запрашивать навигацию в уже имеющихся участках карты, т.к. блокировать их нет необходимости. Блокируется только глобальная навигация по чанкам, но эта блокировка короче по сравнению с загрузкой чанка (скажем, чанк имеет 16x16 клеток, а одновременно загружается не более 3-4 чанков).
Конечно, нужно проводить реальные тесты и сравнивать, какой подход/параметры лучше, но для этого лучше уже иметь игру с оформленным геймплеем. Преждевременные оптимизации только зря замедляют разработку проекта, но знать о потенциальных проблемах в будущем всё же нужно.
AStar позволяет двигаться только по рёбрам графа. Если брать квадратную сетку, у нас два варианта: переходы либо к 4 соседям (без диагоналей), либо к 8 соседям (с диагоналями). В первом случае любой маршрут между двумя точками будет одинаковой длины, и движок выберет первый попавшийся, т.е. вместо зигзага будет буква Г или что-то похожее. Во втором случае мы можем выбрать более оптимальный маршрут, т.к. по диагонали двигаться в sqrt(2) раз быстрее, чем буквой Г, но мы по-прежнему не можем срезать клетки как захотим - вместо прямой будет зигзаг, если точки маршрута не прямо по диагонали.
Когда мы добавляем сюда чанки, мы опять же можем разрешить диагонали по чанкам или запретить. Если запрещаем, тогда результат будет, скорее всего, буквой Г. Если разрешаем диагонали и двигаемся по промежуточным чанкам примерно по середине (двигаемся от входа к центру чанка и/или к середине выходной стороны), тогда зигзаг будет отдалённо напоминать зигзаг, который мы получим, двигаясь только по клеткам с диагоналями, без чанков. Дальше всё зависит от размера чанков, что именно видит игрок, как это влияет на геймплей и т.д.
С чанками есть другая проблема. Если у тебя одна сторона чанка полностью заполнена непроходимыми клетками, то войти на него с соседнего чанка можно только через другие чанки. Твоя навигация по чанкам должна учитывать эту проблему, как-то кэшируя проходимые места в чанках. Однако, мне кажется, это весьма специфичная ситуация, и на первых порах заботиться о ней не стоит.
Зачем вообще чанки в навигации? Ты постоянно загружаешь/удаляешь чанки карты мира из памяти, и ты хочешь делать это в отдельном потоке, который не будет мешать основным игровым потокам. Если ты вносишь изменения в один общий AStar, он будет заблокирован для навигации NPC до тех пор, пока не закончится загрузка или удаление чанков, т.к. без блокировки результат непредсказуем. Если ты загружаешь куски карты в отдельные AStar, существующие NPC могут продолжать запрашивать навигацию в уже имеющихся участках карты, т.к. блокировать их нет необходимости. Блокируется только глобальная навигация по чанкам, но эта блокировка короче по сравнению с загрузкой чанка (скажем, чанк имеет 16x16 клеток, а одновременно загружается не более 3-4 чанков).
Конечно, нужно проводить реальные тесты и сравнивать, какой подход/параметры лучше, но для этого лучше уже иметь игру с оформленным геймплеем. Преждевременные оптимизации только зря замедляют разработку проекта, но знать о потенциальных проблемах в будущем всё же нужно.
Теперь переходи на другую нейронку, и пили аудиотрек с этим текстом.
Затем переходи на третью и пили видеоклип по саунду.
Ну и если всё получится - то место в ОП посте следующего треда твоё.
>>2235
Спасибо за ответы, пока что занимаюсь генерацией карты, но подумываю о том, как я планирую делать открытый мир, а значит и навигацию по нему. Так то я согласен, сначала нужен кор геймплей луп, а потом уже такого рода крутости. В крайнем случае всегда можно пойти путём слабых и сделать как в том же Caves of Qud, где нет бесшовного перемещения между чанками, т.к. каждый чанк - отдельный экран
> нет бесшовного перемещения между чанками
Нахуй оно не нужно никому, все уже наигрались в пустые миры с автогенерируемыми квестами. Народ хочет геймплея, а не дрочильни. Да, я говорю за всех, ишо?
Ладно, ладно, делаю я геймплей, делаю!
Лучше сначала сделать небольшой фрагмент карты, условно 100 на 100 клеток, лучше даже вручную его нарисовать, чтобы не мучиться генерацией. На этом маленьком участке формируешь базовый геймплей, чтоб игроку хорошо игралось даже в ограниченном пространстве. Уже потом будешь масштабировать геймплей на бесконечную процедурную карту.
К примеру, ты можешь обнаружить, что горы и реки преодолевать слишком скучно, и нужно куда больше открытых пространств, а у тебя генератор настроен лабиринты из препятствий делать. Придётся снова ковыряться в генераторе. А если бы тестировал на статичных участках карты, мог бы заранее оценить, какой именно генератор карты тебе нужен.
Можно, конечно, идти путём Майнкрафта и подгонять геймплей под имеющийся генератор ландшафта. Но для этого генерация должна быть самодостаточной, т.е. развлекать независимо от геймплея (ландшафты Майнкрафта просто приятно видеть).
Не знаю, как вы, а я подожду 4.4.
Попробовал совместить портрет Годетты с артом Хизер из СХ3. Больно модельная внешность получается.
Первый раз кто-то другой отправил за меня, либо он сам ее нашел. Я это заметил по взлету в стате итча. Вторую отправлял сам через форму: https://stayathomedev.com/submit-your-game/
А, еще надо сделать игру.
946x624, 0:02
Уже подобрал модельку для противника дальнего боя - сотрудник микрокредитной организации, танцем раскидывает долговые расписки под ногами игрока, призывая агрессивных коллекторов ближнего боя.
>жаль, что далеко не все понимают все фичи Godot))) действительно продвинутые знания))) не так уж много геймдевов в наше время, кто знает, почему это такой интересный и необычный движок)))
>шрифт у лейбла не автоскейлится при изменении масштаба окна
Как ты "масштаб окна" меняешь?
Если ты про ту фичу, что где-то в настройках проекта - там несколько разных режимов. Как минимум один из них никак не влияет на Control-ноды, т.е. весь GUI остаётся без изменений - это важно для 3D игр и 2D игр с гладкими шрифтами. Если у тебя пиксельный шрифт и ты хочешь увеличить его в 2/4 раза, то нужно выбрать другой режим масштабирования.
>TIME чтобы удобно синусить
>Чтобы не делать var time; time += delta
https://docs.godotengine.org/en/stable/classes/class_time.html#class-time-method-get-ticks-msec
А что лучше/эффективней, каждый фрейм свой тайм собирать или дергать эту функцию? А то хуй знает, может она медленно работает.
Дёрни и то, и другое 100000 раз в цикле и оцени разницу.
var iterations: int = 100000
var start: int = Time.get_ticks_msec()
var test1: int
for i in iterations: test1 = Time.get_ticks_msec()
print("Time.get(): %d ms" % [Time.get_ticks_msec() - start])
start = Time.get_ticks_msec()
var test2: float
for i in iterations: test2 += 0.0167 # 1/60
print("+= delta: %d ms" % [Time.get_ticks_msec() - start])
>в кроватке неудобно дергать
Так ты штаны спусти, неудобно ему...
>Time.get(): 15.938 ms (0.000159 ms per iteration)
>+= delta: 8.323 ms (0.000083 ms per iteration)
>difference: 7.615000 ms (0.000076 ms per iteration)
Что и следовало ожидать. Но у Time свои преимущества.
Как я понял, встроенный IK может только вращать.
Так IK и может только вращать. Это такой механизм типа пантографа. А ты что придумал, поршни какие-то линейно слайдить или что?
В Blender можно настроить так, что кости тянутся, если не могут добраться до цели поворотом.
В 2D если только вращать в плоскости экрана, получаются только примитивные марионетки...
>А ты что придумал
Ладно, херню какую-то я придумал.
Идея была в том, чтобы кукожить спрайты так, будто они вращаются в 3D, оставаясь при этом 2D.
Как вообще это их Live2D делается-то без перемещения костей в 3D пространстве?
версия двига 3.5.2
Скорее всего проблема на бэкенде. Если я верно помню тебе нужна поддержка CORS, иначе не секьюрно. Я бэкенд для сбора статов делал вот так, на питоне: https://pastebin.com/LPGnqAWJ попробуй сделать аналог под пхп.
Если игра браузерная ты можешь нажать ф12 и посмотреть на что она жалуется в веб-консольке.
>не фурычит, если в HTML5 экспортируют
Так ты в консоль браузера посмотри, или выводи результат операции через print() в консоль.
Как минимум в Firefox можно подробно изучить каждый запрос, проходящий через браузер - заголовки, содержание, адрес, ответ сервера и т.д.
Не знаю как у них, но вообще разные варианты в голову приходят.
Вариант 1 - нет никакого 3д, есть просто параллакс слоев.
https://www.youtube.com/watch?v=QSeWeyoZ6AM
Вариант 2 - используется проекция из 3д в 2д.
Честно говоря не нашел простого описания, но кажется какие то просто 2д искажения будут совпадать с 3д поворотами.
https://www.youtube.com/watch?v=LZr4ayi1v18
Хм... Попробую сформулировать задачу.
Есть точка А, фиксированная в пространстве, и точка Б, которая может быть в любом месте заданного Rect2. В скелете всего 3 узла + 3 ребра (последнее ребро свободно вращается). Первый узел в точке А, а последний узел нужно переместить в точку Б, да так, чтобы средний узел расположился где-то... как-то так, чтобы натянутые PNG картинки не разнесло по всему экрану.
Я думал, "щас накину IK и всё ок будет", но IK слишком ограничивает движение, плюс выворачивает средний узел туда, куда мне не надо. Я подумал, "ладно, ща набросаю свой велосипед", но так и не понял, как именно двигать кости, потому что когда я двигаю Rest Pose, спрайты совсем не деформируются, а если менять Scale, спрайты корёжит.
Я решил принять единственное решение - забить на эту задумку.
Жопа.
>исправил в ловеркейс одну вечность назад
Попробуй это:
1. Закрой редактор.
2. Вынеси .godot из проекта.
3. Открой проект в редакторе.
4. Экспортируй заново.
Должно помочь с кэшем файлов, но это не точно.
>при запуске из редактора все работает
Там с кэшем какие-то проблемы после введения "uid".
Не рекомендую переименовывать, перемещать или даже удалять файлы через Проводник Windows или любой другой менеджер файлов кроме встроенного в Godot. Встроенный менеджер файлов автоматически обновляет все ссылки в других файлах и кэше редактора... или хотя бы пытается их обновить, но количество косяков при его использовании ощутимо меньше, чем когда меняешь файлы извне.
На винде не все так просто. Если ты переименуешь файл в Файл, то такое переименование вовсе не все проги обнаружат - case insensitive, блин.
Как минимум попробуй в совсем другое название переименовать.
Ну, с локтями в IK всегда проблема, для них используют специальный магнит (в блендере он называется pole target?), не помню есть ли он в IK годота, давно не занимался.
>не все проги обнаружат - case insensitive
О, точно. В tscn-файлах при этом остаётся старое название. Я это решал ручной правкой всех tscn-файлов, но теперь просто пользуюсь встроенным менеджером файлов, чтобы он всё сам автоматически обновлял.
Просто меняй position, не?
>1. Закрой редактор.
>2. Вынеси .godot из проекта.
>3. Открой проект в редакторе.
>4. Экспортируй заново.
Помогло, пасиба аноне. Можно работать дальше.
Свали нахуй в свой загон, блядь.
Разгадка проще, чем ты думаешь.
Ты пытаешься удалить зуб через желудок.
Ригид боди не мувают. Ригидбоди сами летают по симуляции физики, а ты придаешь им импульсы.
А тела, которые летают по управлению, делаются CharacterBody/KinematicBody.
Да, конечно можно иногда ригидбоди телепортировать и это описано как сделать. Но это исключение.
>как простой 3Д ригид бади двигать
>ангуляр велосити у него менять
Конкретно поля скорости лучше только читать.
https://docs.godotengine.org/en/stable/classes/class_rigidbody3d.html
>add_constant_torque
>apply_torque
>apply_torque_impulse
>kinematic RigidBody
Это какая-то путаница у юнитеков, RigidBody по определению не является Kinematic. Его можно переключить в режим кинематика, но это как микроскопом гвозди забивать, большинству игроделов не нужно. Для большинства персонажей хватит CharacterBody, который раньше в Godot назывался KinematicBody. RigidBody нужен для объектов, которые двигаются строго по физике, вроде шариков в бильярде, или когда тебе нужно сделать симуляцию сложного физического объекта с ракетными двигателями и т.п.
Алсо, синтаксис на скриншоте отвратительный. Кто такое любит?
>m_
>GetComponent<RigidBody>();
>Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"))
Такая-то вырвиглазная гадость, аж тошнит.
>в доке тебе не мешает
Хорошие доки, мне очень часто помогали.
Туториалы на ютубе не смотрю - только доки.
>>2829 (Del)
>И как простое кинетик бади в него эволюционировало
Если тебе просто подвигать-повертеть что-то без физики:
docs.godotengine.org/en/stable/classes/class_animatablebody3d.html
>гавнина с кучей бойлерплейта
Она чтобы ТЫ не писал лишний бойлерплейт (значение знаешь?).
>хотя видимо таким не является
Почему? Оно как раз для человечков.
>>2814 (Del)
>Один и тот же запрос в гугл, первая сылка
Каким гуглом пользуешься? Пикрил норм ищет.
Почему ты до сих пор здесь?
Он просто цундере.
>Н-не то что бы мне нравился этот движок...
>Н-не пойми неправильно, другой движок лучше!
>И-использую его просто потому что он бесплатный!
>В-вот найду альтернативу лучше - сразу уйду! Вот!
>И в-вообще... тут всё не так, как мне хотелось!
Классика.
Сап, годач!
Как зделоть автоматическое переключение интерфейса при изменении метода ввода? Ну знаете, как в современных играх, когда играешь с джойстика - подсказки джойстиковые, когда играешь с клавы - подсказки клавиатурные.
Вот я накидал образец, для выбора между клавой и мышью. Работает. В дальнейшем туда можно воткнуть остальные типы инпутов. Но не изобретаю ли я велосипед?
Для тултипов и подсказок легче не строки, а набор иконок. При переключении методов контроля ты просто меняешь спрайтщит двумя строками кода.
https://kenney-assets.itch.io/input-prompts-pixel-16
Про непосредственно обработку ввода - хз насколько у тебя там комплексно. У меня в своем проекте получилось объединить тач-инпут и мышь+клавиатуру в один общий код без избытка условий. Но тут нужен тонкий подход.
Тут уже только морду бить, сорян.
В коде всё описано. Регистрируются 10 инпутов от нового метода и происходит переключение. Лимит в 10 нажатий взят с потолка и подлежит донастройке.
>>2893
> получилось объединить тач-инпут и мышь+клавиатуру
Очевидно что и у меня так же будет. Просто пример показал, как между клавой и мышкой на лету переключается режим.
Я пробовал отдельными файлами - жесть, очень запутывает, не смог разобраться и удалил всё.
Мне нравится комбинированный подход из тырпрайза:
Все стейты из одного класса скажем, RelayState, или допустим, назовём его LambdaState. Кто знаком с современными веяниями, уже догадался, куда я клоню. Поля нашего стейта - это Callable. При создании стейтов, ты прописываешь код в вызывающем классе. Например:
> var idle_state = RelayState.new(on_idle_update, on_idle_enter)
А сами функции здесь же.
А конструктор RelayState выглядит так:
> var _update_callback: Callable
> func _init(on_update: Callable = null, on_enter: Callable = null, on_exit: Callable = null) : _update_callback = on_update ...
И у него методы апдейта входа и выхода выглядят так:
> func update(): if _update_callback: update.call()
Таким образом стейты обладают свойством ссылочного типа, и им не нужны длинные матчи-свитчи, и при этом вся логика не растекается по файлам, но ничего не мешает её по файлам разнести. Просто наследуешься от RelayState и описываешь логику внутри.
> > func update(): if _update_callback: _update_callback.call()
Быстрофикс.
Алсо, в трёшке тоже так можно (если у тебя трёшка), просто кода будет больше.
>При создании стейтов, ты прописываешь код в вызывающем классе.
Если ты лишаешься возможности таскать состояния мышкой в дереве сцены, не используешь систему наследования, и не группируешь методы вместе с описанием класса, то зачем тогда классы?..
>func update(): if _update_callback: update.call()
Откуда этот update() вызывать?
Одному состоянию нужен _process().
Другому состоянию нужен _input().
Третьему состоянию нужен _physics_process().
Четвёртому вообще нужен _integrate_forces().
Из-за этого просто state.update() вызвать не выйдет.
>Регистрируются 10 инпутов
Зачем? Если пользователь один раз нажал кнопку на геймпаде - очевидно, он уже взял в руки геймпад и собирается на нём играть. Если пользователь нажал кнопку на клавиатуре - очевидно, у геймпада села батарейка и он пересел за клавомышь.
Лишняя задержка по нажатиям контринтуитивна и я долго не мог понять, почему у тебя так много кода ради простого if/else переключателя.
Конечно, бывают фантомные нажатия от глючных устройств. Но, во-первых, это уже проблема лично пользователя, а не твоя, а во-вторых, от этого будет намного больше проблем в других местах игры - особенно если ты пытаешься это замаскировать.
Само переключение подсказок у тебя не должно занимать больше одного кадра, даже если ты какие-то текстуры заново рендеришь с нуля.
Раньше писал такой стейт на шарпе, щас переписал на гдскрипте, вышло еще короче, и даже ифы не нужны, см. пик. Оказалось, Callable не может быть null, но конструктор с дефолтами хочется. Я вышел из ситуации элегантно. А поскольку nc не null, а пустой делегат, то ифы убираем за ненадобностью.
> лишаешься возможности таскать состояния мышкой в дереве сцены
Нахуй не нужон.пнг
> не используешь систему наследования
Используй систему композиции.
> не группируешь методы вместе с описанием класса
Группирую.
> Откуда этот update() вызывать?
Из player.gd.
> просто state.update() вызвать не выйдет
Придётся пилить полный пример. Ты не до конца понимаешь силу делегирования.
> Зачем?
Чтобы играть геймпадом, получая экренные подсказки для геймпада, при этом подруливать мышкой (или прожимать клавой), и чтобы подсказки не переключались геймпад-КВМ-геймпад-КВМ.
>Чтобы играть геймпадом, получая экренные подсказки для геймпада, при этом подруливать мышкой (или прожимать клавой)
Аааааа, что это за гей-мерский БДСМ?
Если ты такой сухопутный осьминог, что можешь двумя руками держать геймпад, одновременно с этим двумя ногами печатать на клавиатуре, и при этом ещё тазом двигать мышку - вряд ли тебе нужны какие-то подсказки, ты и сам кого хочешь научишь игре лучше любых экранных подсказок.
Подсказки на экране нужны для ленивцев, которые развалились на диване в полусне, и не способны запомнить две кнопки - A = "да" и B = "нет", поэтому игра им должна непрерывно напоминать.
Короче, не усложняй.
>не нужон
Как тогда лапшу состояний развешивать?
>композиции
Так у тебя же RefCounted, они не имеют встроенной системы композиции в отличие от Node. Велосипед?
>>Откуда этот update() вызывать?
>Из player.gd.
>Придётся пилить полный пример. Ты не до конца понимаешь силу делегирования.
Я не понимаю, как у тебя абстрактный код может учитывать все нюансы каждого состояния, которые могут выходить далеко за рамки "вошёл, обновил, вышел" и должны быть связаны со структурами движка, а не работать где-то в вакууме отдельно от всего.
Про Callable не нужно объяснять, я их использовал неоднократно ещё до выхода 4.0. Вопрос не в них, а в организации графа конечного автомата, чтобы это не превращалось в головную боль и костыли.
> Я не понимаю, как у тебя абстрактный код может учитывать все нюансы каждого состояния
Обесняю:
>>2925
> Одному состоянию нужен _process().
Нет, _process нужен ноде.
> Другому состоянию нужен _input().
Нет, _input нужен ноде.
> Третьему состоянию нужен _physics_process().
Нет, _physics_process нужен ноде.
> Четвёртому вообще нужен _integrate_forces().
Нет, _integrate_forces нужен ноде.
Понял теперь?
>>2933
> Вопрос не в них, а в организации графа конечного автомата, чтобы это не превращалось в головную боль и костыли.
У нод своя композиция, у стейтов своя композиция. Она же граф. Она же дерево.
Между деревом нод и графом состояний есть точка, стейтмашина, которая переключает внутри себя куррент-стейт. Также стейтмашина при своем создании делегирует стейтам все необходимые данные. Ноды работают со своими коллбэками. Стейты работают со своими коллбэками.
Всё логично, просто и разграниченно.
Теперь понял?
Еще раз. Коллбэк наподобие _integrate_forces вызывается у ноды. А будет ли она в состоянии его вызывать - это задаётся через стейтмашину.
Перефразирую.
> Еще раз. Коллбэк наподобие _integrate_forces вызывается у ноды. А а с какими данными нода обработает код - это задаётся через стейтмашину, куррентстейтом.
>Нет, _integrate_forces нужен ноде.
Так, давай конкретнее.
Вот у меня есть RigidBody, и у него есть состояние бытия по имени FartForwardState. Это состояние должно брать state из _integrate_forces, прикладывать к нему силу fart и таким образом ускорять RigidBody вперёд. Также у этого объекта есть ещё более 9000 состояний бытия, которые я потом сделаю, но пока сфокусируемся на главном.
Ты предлагаешь сделать так:
>func on_fart_forward_update(): ??? # тут нужен прямой доступ к rb_state из _integrate_forces
>var current_state = RelayState.new(on_fart_forward_update)
Что я должен сделать?
>func _integrate_forces(rb_state): current_state.update()
Это не учитывает rb_state, я не могу его передать в обработчик состояния, а обработчик состояния не может его откуда-то взять, ведь rb_state существует в актуальном состоянии только в _integrate_forces.
Хрень какая-то. Проще через match, раз уж мы не можем передвигать состояния в дереве сцены.
Вообще, простейший конечный автомат:
>func _integrate_forces(rb_state):
>match current_state:
>State.FartForward: блаблабла
>State.DoBarrelRoll: блаблабла
>State.SelfDestruct: блаблабла
Здесь State - это просто enum. Правильно? Всё сгруппировано в одном месте, просто и логично, однако, это невозможно настраивать в рантайме.
Если мы создаём отдельный класс State:
>func _integrate_forces(rb_state):
>current_state.update(rb_state)
Всё остальное - в обработчике update состояния. Позволяет нам добавить сколько угодно классов прямо в рантайме, не трогая эту строчку в коде.
Но такой подход плохо сочетается с кучей разных обработчиков нод Godot, ведь в каждом отдельном обработчике могут быть разные параметры:
>_input, _unhandled_input - event: InputEvent
>_process, _physics_process - delta: float
>_integrate_forces - state: что-то там
И т.д. Что может понадобиться завтра - я не знаю.
Я пытался прокидывать обработчики туда-сюда, но получается лютая лапша на куче костылей. Тупо некрасиво и запутывает, кто кого где вызывает.
>>2947
Ещё очень важный момент, вот этот обработчик
>_integrate_forces
Доступен только на потомках RigidBody, и state его относится только к конкретной ноде. Это означает, что обработчик состояния не может быть наследником какого-то класса кроме RigidBody, и если мы хотим добавить состояние, требующее работу с _integrate_forces, мы обязаны привязать скрипт к RigidBody, объявить в нём этот обработчик и вызывать из него обработчик состояния... Что всё усложняет на порядки, особенно если у нас все остальные состояния идут через совершенно другие ноды и к физике отношения не имеют.
Как это сделать универсально и гибко - непонятно.
Типа паттерны всякие, компонентно ориентированный подход... Например.
Я просто только вкатываюсь в пограмирование и пока еще многого не знаю.
В документации, в туториалах на ютубе, в демо-проектах. Но лучше всего - у себя вчерашнего, уже набившего шишки и понявшего как лучше. Опыт и рост это в основном личный путь.
Я видел в контроллерах персонажей в ассетлибе например,
https://github.com/expressobits/character-controller
А вообще язык скриптовый, в первых играх не заморачивайся с архитектурой, можно быстро прототипировать разные штуки.
>архитектуру игры пилить
Вот с этим можно ознакомиться:
https://gameprogrammingpatterns.com/contents.html
>>2969
>пока не понимаю что значат все эти func и var.
Это не архитектура, лол, у тебя самой базы нет.
Есть такая обучающая игрушка:
https://gdquest.github.io/learn-gdscript/
Ну и документацию тоже читай.
https://docs.godotengine.org/en/stable/getting_started/step_by_step/index.html
А это актуально для годота? Я смогу потом написать убивцу Death Stranding, став кодзимагением? М? МММ?
>Это не архитектура, лол, у тебя самой базы нет.
Ээээххх. Как же...
>Есть такая обучающая игрушка:
Пасиб, позырю.
>Ну и документацию тоже читай.
Я вот от про слышал, что документация - это душнильная параша для лохов.
>Я первый раз в кодинг пытаюсь, еще пока не понимаю что значат все эти func и var.
Тебе тогда рано в паттерны. Вложенные циклы и с ифами тебе будут мозговой процессор переполнять, до понимания паттернов там как до китая.
Я сразу хочу научиться програсмировать правильно и годно.
Начал вот пилить астероид шутанчик, но пока еще не оче понимаю что я делаю не правильно.
>написать убивцу Death Stranding
Дед Стренд помер 15 тредов назад: >>882182 →
Документацией не брезгуй, она тут хорошая.
>>2975
>что я делаю не правильно
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html
>я не знаю англиского
Как ты игоры делоть собрался без английского? Самые подробные и качественные материалы - на английском, зачастую совсем без перевода.
На русский перевод есть/был, но он не завершён:
https://docs.godotengine.org/ru/4.x/tutorials/scripting/gdscript/static_typing.html
Но трансляторы типа deepl и прочие нейронки уже достаточно хорошо переводят, понимают контекст.
Сразу не будет. Правильно и годно не бывает нигде и никогда.
>Как ты игоры делоть собрался без английского?
Ну у меня уровень - лет ми спик фром май харт. Такого хватит?
Просто я где-то на 99.9% понимаю техническуб документацию, но по всей видимости самое главное не могу понять и туплю оче много, часто из-за этого фейлю самые изичные залупки. Ээх.
Особенно забавляет пикрил: сложный визуальный редактор, а в коде потешный match на строках.
Ну и как сделать конечный автомат без match и if?
>Так чо по архитектуре смотреть
Не знаю, ищи сам, вот какое-то видео:
https://youtu.be/7NXgrd6wbXI
>Я вот от про слышал, что документация - это душнильная параша для лохов.
Это тебе ультрахуйню сказали. Плюнь тому человеку в ебало.
> Ну и как сделать конечный автомат без match и if?
Я это делаю через коннекты и сигналы. Каждый стейт - файл-класс, в который входим одним способом и выходим несколькими возможными сигналами. В родителе подсоединяешь сигналы к следующим стейтам.
Например стейт StateFollow - внутри 2 сигнала, target_reached и target_lost. Делаю StateFollow.connect(target_reached, StateAttack) и StateFollow.connect(target_lost, StateIdle), все, теперь из следования ты переключаешься либо в атаку, либо в айдл, ни одного ифа/матча.
>>2992
Учи английский. Технический английский простой. Изначальные авторы годота испаноязычные челы, кто-то вообще из бразильских-португальских джунглей, а годот запилили и комьюнити англоязычное вокруг. Они смогли выучить, а ты нет? Кмон, брух.
>Плюнь тому человеку в ебало.
Ну не могу я анончику в ебало плюнуть чисто физически
Мне совесть не позволяет, ну как ты все не поймешь
>>3000
>Учи английский. Технический английский простой.
Спасибо, что посометовал.
>Изначальные авторы годота испаноязычные челы, кто-то вообще из бразильских-португальских джунглей
Типа испанский еще учить? Ну хватит уже. Пожалуйста.
>Типа испанский еще учить?
Нет. Комьюнити, как я сказал, англоязычное. Я к тому что изначальным разрабам тоже пришлось учить английский чтобы прийти к тому, к чему они пришли.
>Каждый стейт - файл-класс
Ну вот я создал, например:
state_walk.gd
state_run.gd
state_jump.gd
state_fall.gd
Потом ещё хотел "вприсядку" добавить, но уже с предыдущими файлами обосрался от количества непонятных переходов в своём коде и всё снёс.
А у меня таких стейтов, по идее, десятки должны получиться, из каждого в каждый несколько путей.
Т.е., например, прыгнуть можно и в ходьбе, и в беге; из прыжка можно падать, ходить и бежать; можно ходить и бегать вприсядку, и можно прыгать из ходьбы и бега вприсядку; можно сделать куворок из ходьбы и бега и из ходьбы и бега вприсядку, куворок может быть сразу после прыжка или сразу перед прыжком, или в полёте над землёй, или... Ещё тысячи вариантов. Как я буду между каждым файлом бегать и проверять все условия, кто куда вошёл и откуда вышел? Сложна, нужно что-то проще. Типа массива флагов:
[✅] быстро
[✅] движется
[❌] в воздухе
[✅] вприсядку
[✅] катясь колобком
[❌] с оружием в руках
[❌] пытаясь подпрыгнуть
[✅] блокирует входящий урон
И т.д. Тут сразу видно, что происходит, и не нужно создавать стопицот отдельных классов. Но тогда получается обмазывание множеством match/if...
>Как я буду между каждым файлом бегать и проверять все условия, кто куда вошёл и откуда вышел?
Если тебе нужны длинные цепочки стейтов то ты хранишь историю переходов и смотришь на нее. Проверяешь эту историю в стейте, если она не подходит - ливаешь из стейта, передаешь контроль следующему кандидату. Но вообще тут я хз, длинные цепочки я не делал.
Ваще изи делается. Если ты не знаешь, как такую простейшую механику реализовать, то странно, как ты вообще браузер запустить смог и зайти в этот трежд. Мда уш.
>быстро
>движется
>в воздухе
>вприсядку
>катясь колобком
>с оружием в руках
>пытаясь подпрыгнуть
>блокирует входящий урон
Вот это уже 256 возможных состояний получается. Допустим, некоторые из них не имеют смысла, но всё равно большое количество разных состояний. Я читал про иерархические автоматы, но какая тут иерархия, если все действия примерно равны?
Для NPC такое решается через utility system...
https://en.wikipedia.org/wiki/Utility_system
Хммм, а если задействовать это для игрока? Игрок прожимает клавиши, а моделька реагирует на это по расчётной полезности... К примеру, игрок зажал:
- W чтобы двигаться вперёд;
- Ctrl для приседания;
- пробел для прыжка.
Но моделька уже находится в полёте и может только дрыгать ножками => по формуле выводит, что сейчас продолжаем беспомощно дрыгать ножками. Никаких десятков состояний с переходами тут уже не нужно.
>>3007
>такую простейшую механику реализовать
Так это не механика, это как раз архитектура. От неё зависит гибкость дальнейшей разработки.
Прости пожалуйста. Меня взрослые подучили.
Вот прям спокойно, не торопясь, по пунктам...
>Вот это уже 256 возможных состояний получается
Если делать ветвлением - то да.
Поэтому существует компонентный подход:
Один компонент отвечает за движение
Другой за скорость
Третий за полёт
Четвёртый за присядку
Пятый за качение колобком
Шестой за оружие
Седьмой за прыжки
Возьмой за блокирование урона
Итого у тебя 8 компонентов, каждый внутри себя имеет 2 простых состояния. И одно кольцо, чтобы править всеми - персонаж объединяет компоненты внутри себя. У персонажа в конечном итоге будет 256 состояний, да. Но явным образом описать надо всего 16. Это компонентный подход.
>>2985
Ты не вкурил. На самом деле у тебя на пикрилейтедах ДВЕ стейт-машины: одна отвечает за анимации и встроена в движок, другая отвечает за перемещение и написана туториалоблогером для нубов, чтобы они познавали силу стейт-машины, при этом оставаясь в рамках доступных им знаний. Я полностью поддерживаю такой подход, потому что это усложнение на один пункт. К ранее изученной базе прибавляется только машина состояний и ничего более.
Вот усложнение на два шага. Здесь мы осваиваем машину состояний и использование типа Callable. А для кого-то, возможно, сразу три шага, потому что тут ещё и словарь используется на манер луа-таблицы.
# описываем, что делают состояния, здесь
func idle(delta):
блабла
func walk(delta):
блобло
func jump(delta):
блэблэ
# словарь, в котором перечисляются все стейты
var states = {
idle = idle, # здесь слева именуется поле словаря, а справа ссылка на объявленную и описанную выше функцию
walk = walk, # то есть, это как бы states.walk = walk
jump = jump, # и даже то же самое, что states["walk"] = walk
}
func _in_StateMachinePlayer_updated(state, delta):
if states.has(state): # эту проверку можно убрать, если ты стопроцентно уверен, что эта функция не будет вызвана с неправильным стейтом
states[state].call(delta)
>Вот это уже 256 возможных состояний получается
Если делать ветвлением - то да.
Поэтому существует компонентный подход:
Один компонент отвечает за движение
Другой за скорость
Третий за полёт
Четвёртый за присядку
Пятый за качение колобком
Шестой за оружие
Седьмой за прыжки
Возьмой за блокирование урона
Итого у тебя 8 компонентов, каждый внутри себя имеет 2 простых состояния. И одно кольцо, чтобы править всеми - персонаж объединяет компоненты внутри себя. У персонажа в конечном итоге будет 256 состояний, да. Но явным образом описать надо всего 16. Это компонентный подход.
>>2985
Ты не вкурил. На самом деле у тебя на пикрилейтедах ДВЕ стейт-машины: одна отвечает за анимации и встроена в движок, другая отвечает за перемещение и написана туториалоблогером для нубов, чтобы они познавали силу стейт-машины, при этом оставаясь в рамках доступных им знаний. Я полностью поддерживаю такой подход, потому что это усложнение на один пункт. К ранее изученной базе прибавляется только машина состояний и ничего более.
Вот усложнение на два шага. Здесь мы осваиваем машину состояний и использование типа Callable. А для кого-то, возможно, сразу три шага, потому что тут ещё и словарь используется на манер луа-таблицы.
# описываем, что делают состояния, здесь
func idle(delta):
блабла
func walk(delta):
блобло
func jump(delta):
блэблэ
# словарь, в котором перечисляются все стейты
var states = {
idle = idle, # здесь слева именуется поле словаря, а справа ссылка на объявленную и описанную выше функцию
walk = walk, # то есть, это как бы states.walk = walk
jump = jump, # и даже то же самое, что states["walk"] = walk
}
func _in_StateMachinePlayer_updated(state, delta):
if states.has(state): # эту проверку можно убрать, если ты стопроцентно уверен, что эта функция не будет вызвана с неправильным стейтом
states[state].call(delta)
Нууу чеел. Я сейчас занят изучением англимского и испанского языка...
> обосрался от количества непонятных переходов в своём коде и всё снёс
Не мучайся и возьми готовое. https://godotengine.org/asset-library/asset/1778
https://www.youtube.com/watch?v=E9h9VnbPGuw
1. Мало готовых 3D ассетов для флипанья.
2. Не исправляет ошибки дизайнера за него.
Вот и всё, в остальном замечательный движ.
>8 компонентов
Ну так это понятно. Что с ними делать непонятно. Компонентный подход не решает задачу, только изменяет организацию кода (1 файл => 9 файлов).
>на пикрилейтедах ДВЕ стейт-машины: одна отвечает за анимации и встроена в движок
Не, там велосипедный аддон:
https://github.com/imjp94/gd-YAFSM
>func walk(delta):
А если стейту нужен PhysicsDirectBodyState3D?
>>3027
>готовое
Там всё как у всех, пикрил. Где интегрейт? Верно, бери исходники и костылируй в них интегрейт... Без костылей и лапши не получается. А весь смысол конечных автоматов - упорядочить код так, чтобы в нём не осталось места для лапши. Не получается.
>>3028
Прикольно, конечно. Молодец.
>has_method
Да не, нормально всё, если ты не делаешь это тыщу раз каждый кадр. Утиная типизация:
>if animal.has_method("quack"): animal.quack() # утка
Для ускорения можно использовать StringName:
>const QUACK = &"quack"
>if animal.has_method(QUACK): animal.quack()
В остальном затраты как у обычных вызовов.
Не путайте этот подход с сигналами. Сигналы - это когда тебе заранее всё известно и ты связываешь несколько объектов проводами. Утиная типизация нужна, когда к тебе пришло хрен знает что, но ты должен с ним сделать что-то конкретное.
Есть такая проблема, почти 6 лет не решена:
https://github.com/godotengine/godot/issues/22838
has_method не видит static func...
> has_method не видит static func
Он его и не должен видеть.
Статик-функции это костыль всех "ООП-языков". Сам принцип ООП-языка, "всё есть объект, всё есть метод" - вреден и костылен. Потому что когда нужна просто функция, язык не позволяет без задней мысли объявить императивный модуль с простофункциями, нет, будь добр объявить класс, который тебе нахуй не нужен, а в нём объяви статический метод, который ты будешь использовать как функцию.
10 лет меня это бесит, угнетает, аштрисёт!
Я заебался пиксели рисовать и вторую игру в лоуполи 3д делаю - особых проблем не испытываю. Ассеты и там и там свои.
>язык не позволяет без задней мысли объявить императивный модуль
На Паскале вот можно, а это ООП язык:
>Paradigms: Imperative, structured, object-oriented, functional, component-based, event-driven, generic
>объявить класс, который тебе нахуй не нужен
Но ведь смысл статических методов - не когда тебе класс вообще не нужен, а когда тебе нужно связать метод с конкретным классом, но использовать его вне контекста конкретного экземпляра класса...
>Статик-функции это костыль
>когда нужна просто функция
Костыль - это анонимные функции, которые ты объявляешь где попало, потому что тебе лень стрелочки на клавиатуре нажимать лишний раз.
>"всё есть объект, всё есть метод" - вреден
Почему? Ведь так оно и есть. Этот принцип отрицает существование метафизических сущностей, которые ухудшают читаемость кода (лапшичный монстр). Т.е. вместо обмазывания метафизикой, ты говоришь твёрдо и чётко - всё должно быть материальным объектом, а не больной фантазией дизайнера. И называешь эти объекты читаемыми именами, и обращаешься к ним по имени, ибо существуют. А обмазываясь анонимной лапшой из случайных функций ты только ухудшаешь читаемость кода.
Лучше ООП может быть только язык, в котором сущности не просто объекты, а субъекты, и создание программы заключается в налаживании отношений между ними, но эта парадигма пока не взлетела.
Меня больше бесит неспособность GDScript сделать наследника одного из встроенных классов: Array, Dictionary и т.п. не существуют в потомках Object, следовательно, из них нельзя сделать свой вариант. Пришлось сделать ArrayUtils со static методами - вот это уже костыль, но не из-за ООП, а из-за GDScript.
> На Паскале вот можно, а это ООП язык:
Паскаль - мультипарадигменный. О чём прямо говорит твой же гринтекст, парадигмы во мн.ч. и через запятую перечислены.
К сожалению, паскаля в годоте нет.
> смысл статических методов
> когда тебе нужно связать метод с конкретным классом
Единственная конкретность там в том, что у тебя имя метода состоит из класс.имя() какая ещё связь-то?
Поэтому смысл статических методов в ООП-языках, как я и сказал выше, в том, чтобы через пень-колоду эмулировать мультипарадигму, а именно модульность того же паскаля. Причём в том же паскале началась та же самая дрисня, зумеры забыли, что есть просто функции, просто процедуры, и сделали статик-процедуры в ФПК, и класс-процедуры в дельфи. Что это, я не понимаю. Ебашить велосипеды поверх велосипедов, лишь бы не как диды?
> Костыль - это анонимные функции
Но мы сейчас не про них.
> Почему? Ведь так оно и есть.
В упомянутом тобой паскале так не есть. Там можно сделать программу без единого класса вообще. Без ООП вообще. Исключительно на императивных модулях.
> Лучше ООП может быть только язык
ООП не язык, ООП - парадигма. А классы это лишь одна из реализаций этой парадигмы. Существуют и другие реализации, например, на прототипах (жс), или на типажах (раст). Но в классическом паскале ООП был на типах, просто типах. Классы пришли позднее, как зумерская мода выебываться не как диды. Описываем тип. Описываем реализацию типа. Создаём экземпляры. Работаем.
> Пришлось сделать ArrayUtils со static методами - вот это уже костыль
Но мы сейчас не про них.
>паскаля в годоте нет
При желании добавить можно.
>какая ещё связь-то?
В GDScript нет статических полей, к сожалению, но если бы были, то можно было сделать что-то такое:
>static func Enemy.spawn():
>_ if Enemy.spawn_count > 0:
>_ _ Enemy.spawn_count -= 1
>_ _ return Enemy.new()
>_ return null
Сейчас тебе обязательно нужен экземпляр класса, чтобы провернуть подобное, или использовать баг в реализации констант, но его могли уже пофиксить.
С другой стороны, да, такой прикол лучше не делать, лучше сделать отдельный EnemySpawner, экземпляр которого имеет собственный счётчик, который удаляется вместе с экземпляром. Видишь, в чём проблема таких функций? Они засоряют глобальное пространство в памяти, что трудно контролировать.
>func EnemySpawner.spawn():
>_ if spawn_count > 0:
>_ _ spawn_count -= 1
>_ _ return Enemy.new()
>_ queue_free()
>_ return null
И вот мы решили сразу несколько проблем.
>Там можно сделать программу без единого класса вообще. Без ООП вообще. Исключительно на императивных модулях.
Да, можно, но ООП подразумевает дополнительный уровень защиты от (архитектурных) ошибок... Думаю, поэтому языки отказались от "бездомных" функций.
>Но в классическом паскале ООП был на типах, просто типах. Классы пришли позднее
Я так и не понял, в чём разница между Object и Class кроме того, что Object передаётся целиком так же как Record, а Class всегда по ссылке. В остальном - синтаксис через точку что там, что здесь, особой разницы со стороны внешнего наблюдателя нет.
Вообще, для меня ООП - это синтаксис через точку, всё остальное - незначительные детали внутренней реализации, которые меня волновать не должны:
>ссылка на кого = Категория.кто-то новый (какой)
>что сделал = кто.что сделает (с чем сделает)
И так далее. Вот в этом преимущество ООП - тебе не нужны бессвязные функции, потому что их некому выполнять, если они совсем-совсем ничейные:
>что сделал = что сделает (с чем сделает)
Кто это сделал? Непонятно. Приходится костылить:
>что сделал = что сделает (кто, с чем сделает)
>что сделал = кто_что сделает (с чем сделает)
Но это по сути то же самое, что и через точку.
>паскаля в годоте нет
При желании добавить можно.
>какая ещё связь-то?
В GDScript нет статических полей, к сожалению, но если бы были, то можно было сделать что-то такое:
>static func Enemy.spawn():
>_ if Enemy.spawn_count > 0:
>_ _ Enemy.spawn_count -= 1
>_ _ return Enemy.new()
>_ return null
Сейчас тебе обязательно нужен экземпляр класса, чтобы провернуть подобное, или использовать баг в реализации констант, но его могли уже пофиксить.
С другой стороны, да, такой прикол лучше не делать, лучше сделать отдельный EnemySpawner, экземпляр которого имеет собственный счётчик, который удаляется вместе с экземпляром. Видишь, в чём проблема таких функций? Они засоряют глобальное пространство в памяти, что трудно контролировать.
>func EnemySpawner.spawn():
>_ if spawn_count > 0:
>_ _ spawn_count -= 1
>_ _ return Enemy.new()
>_ queue_free()
>_ return null
И вот мы решили сразу несколько проблем.
>Там можно сделать программу без единого класса вообще. Без ООП вообще. Исключительно на императивных модулях.
Да, можно, но ООП подразумевает дополнительный уровень защиты от (архитектурных) ошибок... Думаю, поэтому языки отказались от "бездомных" функций.
>Но в классическом паскале ООП был на типах, просто типах. Классы пришли позднее
Я так и не понял, в чём разница между Object и Class кроме того, что Object передаётся целиком так же как Record, а Class всегда по ссылке. В остальном - синтаксис через точку что там, что здесь, особой разницы со стороны внешнего наблюдателя нет.
Вообще, для меня ООП - это синтаксис через точку, всё остальное - незначительные детали внутренней реализации, которые меня волновать не должны:
>ссылка на кого = Категория.кто-то новый (какой)
>что сделал = кто.что сделает (с чем сделает)
И так далее. Вот в этом преимущество ООП - тебе не нужны бессвязные функции, потому что их некому выполнять, если они совсем-совсем ничейные:
>что сделал = что сделает (с чем сделает)
Кто это сделал? Непонятно. Приходится костылить:
>что сделал = что сделает (кто, с чем сделает)
>что сделал = кто_что сделает (с чем сделает)
Но это по сути то же самое, что и через точку.
К взаимодействию с Interactable объектами добавил возможность переключаться на привязанную к этому Interactable камеру, как в видео с постером.
Пока гулял по городу, наклевались зачатки основного сюжета. Правда религиозного, православного характера. Наверно сказались натыканные за каждом поворотом церкви и регулярный колокольный звон.
OBS почему-то начал записывать игру из Debug-режима с каким-то дерганным FPS, хз что случилось. Играется гладко.
Весьма недурно для 2005 года.
Так в годоти есть встроенный муви мейкер жи. Выдает на выходе ровный фпс, но не любит анимированные текстуры.
> наклевались зачатки основного сюжета. Правда религиозного, православного характера
Главное, чтоб не получился клон индики.
О, уже добавили? Когда успели?
https://godotengine.org/article/godot-4-1-is-here/#gdscript
А ты мог бы просто кинуть ссылку на документацию:
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#static-variables
Просто запомнил то длинное обсуждение на гитхабе, много спорили надо/не надо...
Там есть два метода равноэлегантых, выбирай какой тебе удобнее:
1) свойство фрейма анимации, задаёшь сколько у тебя равных фреймов по горизонтали и вертикали, спрайт разрезается внутри по заданной тобой сетке, и показывает только один фрейм. Индекс ты можешь менять сам когда захочешь.
2) свойство региона. Задаёшь ручками регион спрайта, которых хочешь выводить. И всё.
Спасибо! То, что надо!
Какой способ производительнее?
> Какой способ производительнее?
Вниз по дереву - обращаешься через $; вверх по дереву - обращаешься через сигналы, которые подключает нода сверху ноде снизу.
>>3159
> как лучше всего организовать обмен данными между сценами?
Через шины (гуглим).
В случае с деревом шина уже есть, - это сам корень дерева. Но для пущего удобства в настройках проекта можно добавить отдельную сцену в автозагрузки, она сделается прямым потомком корневого узла и будет видна всем остальным узлам, как синглтон.
И ещё.
Щас прибегут диванные безыгорники и начнут кудахтать про синглтон-антипаттерн. Не слушай их и не бойся синглтонов. В том же анриле, например, вся архитектура построена на синглтонах и никто не жалуется.
> как много я еще не знаю
Читай официальные доки (ссылки в шапке).
Переводи автопереводчиком, если не умеешь в инглиш. Доки подробные и качественные. В треде не всегда быстро ответят, вот я щас попью кофе и сваливаю ИРЛ.
>начнут кудахтать про синглтон-антипаттерн
Но ведь сами движки используют синглтоны. Вообще, все эти рекомендации из энтерпрайза не относятся к геймдеву. Более того, они даже вредны, если им следовать.
Интересный контент
https://gameprogrammingpatterns.com/contents.html
>Зачем нужен emit signal
https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html
Вкратце: сигнал - это событие. Ты можешь сделать несколько мест в коде, которые реагируют на одно и то же событие, а соединить их через редактор.
К примеру, у тебя есть генератор звука и генератор частиц взрыва, ты можешь подключить их к событию нажатия кнопки Button.pressed и тогда по нажатию кнопки будет производиться звук и генерироваться частицы. Теперь ты решил - что-то тут не так, и перекинул соединения с кнопки на Timer.timeout, чтобы те же события происходили по происшествию времени. Код при этом никак менять не нужно, меняется только описание сцены (.tscn).
Такое соединение игровых сущностей становится наиболее выгодным, когда тебе нужно часто переиспользовать одну и ту же сцену в разных местах. Вот у нас есть Button в движке, но она не подходит для размещения на стенах в 3D играх, верно? Ты делаешь свою собственную сцену Button3D, которая объявляет свой сигнал signal pressed, и которую можно поместить в 3D мире, чтобы игрок мог с ней взаимодействовать в пространстве (press E to...). Теперь тебе достаточно закинуть эту Button3D в любое место сцены и подсоединить её сигнал к методам какого-либо другого объекта, например, гаражной двери, лампочки, радио и т.д. При этом ты можешь закинуть просто кнопку, ни с чем её не соединяя - и она по-прежнему будет работать, хоть её нажатие и не влияет ни на что (нет обработчиков).
>к ноде можно обратиться напрямую через $?
Так ты связываешь код с к конкретной сценой, в случае с кнопкой у тебя будет $lamp.enable = true, но что, если теперь тебе не лампа нужна, а радиоприёмник или дверь? Ты же не будешь создавать тысячу скриптов типа button_lamp, button_door, button_radio и т.д., в каждый из которых отличается от остальных только строчкой с $.
Конечно, можно написать так:
>@export var node: Node
>node.do_something()
Но во-первых, если мы хотим соблюдать строгую типизацию, возникают трудности с тем, что можно положить в эту переменную, а во-вторых, если ты забудешь положить туда ноду или нода по какой-то причине исчезнет из сцены, твой скрипт сломается. Конечно, можно добавить проверку if node: node.do..., но это не решает всех проблем, т.к. инвалидная ссылка не всегда null, и единственный надёжный способ проверки - через WeakRef...
>Какой способ производительнее?
Тут вопрос не в производительности, а в удобстве и гибкости разработки. Но сигналы, по идее, быстрее обращения через $, потому что:
- $нода - это сокращение self.get_node("нода")
- строка "нода" создаёт новый объект NodePath
- get_node() как-то ищет ноду в дереве нод
- только потом вызывается метод ноды.
С сигналами, если у тебя что-то привязано к сигналу, оно сразу выполняется, и поскольку это один из самых важных концептов движка, внутри оно наверняка очень сильно оптимизировано (сигналы буквально на всех нодах).
Ты можешь ускорить обращение через @export ноды или через @onready, заранее получив ссылку на ноду, но это не решает тех проблем, описанных выше.
>>3159
>организовать обмен данными между сценами
Что ты имеешь в виду? Если ты используешь для смены сцены встроенную функцию SceneTree.change_scene, то я не рекомендую так делать - лучше заменять часть дерева целой сцены, так у тебя будет больше контроля. Если всё же хочешь заменять сцены этой функцией, то тебе придётся добавлять ноды в "автозагрузку" и передавать данные через эти ноды - они никак не затрагиваются "сменой сцены".
Если ты имеешь в виду передачу данных вроде передачи предмета из инвентаря игрока на пол или в верстак, то тут уже всё зависит от того, как у тебя игра устроена. Чего-то универсального тут не посоветуешь.
>>3171
>сами движки используют синглтоны
Потому что у тебя не может быть два экземпляра Engine, два экземпляра OS. А вот для экземпляра Player, два экземпляра WorldMap и т.д. - запросто. Новички обманываются синглтонами и потом не могут понять, почему движок не даёт им создать второго Player без кучи фатальных ошибок в коде.
В большинстве игр синглтоны не нужны. Синглтон нужен только если тебе вот прям обязательно нужно выбить в граните "сцена God может быть лишь одна и обращаться к ней нужно только с большой буквы". Естественно, что это очень вредный антипаттерн.
Этого не слушай, он уверовал в Синглтон и теперь проповедует о его могуществе ньюфагам: >>3162
>Не слушай их и не бойся синглтонов.
Ага, обязательно обмазывай весь код кучей лишних Имён, которые потом хрен вырежешь из кода, когда они неизбежно пукнут и обмякнут кучей ошибок.
Особенно смешно смотреть на то, как новички объявляют синглтон Global и завязывают на него всю игру, по сути высирая тонну бесполезной лапши, которую они даже сами не смогут использовать для другой своей игры, т.к. всё слишком запутано в этом божественном объекте, на который молятся все остальные скрипты игры.
Но если ты любишь трудности, тогда можешь хоть намагниченной иголкой биты в жёстком диске переворачивать, программируя игру в машинных кодах - бояться тут нечего, это просто форма БДСМ.
>В том же анриле
>никто не жалуется.
Это потому что:
- ААА студии сами могут переделать движок;
- нищих индюков никто слушать не будет, лол;
- синглтоны движка != скриптолапша твоей игры.
>Зачем нужен emit signal
https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html
Вкратце: сигнал - это событие. Ты можешь сделать несколько мест в коде, которые реагируют на одно и то же событие, а соединить их через редактор.
К примеру, у тебя есть генератор звука и генератор частиц взрыва, ты можешь подключить их к событию нажатия кнопки Button.pressed и тогда по нажатию кнопки будет производиться звук и генерироваться частицы. Теперь ты решил - что-то тут не так, и перекинул соединения с кнопки на Timer.timeout, чтобы те же события происходили по происшествию времени. Код при этом никак менять не нужно, меняется только описание сцены (.tscn).
Такое соединение игровых сущностей становится наиболее выгодным, когда тебе нужно часто переиспользовать одну и ту же сцену в разных местах. Вот у нас есть Button в движке, но она не подходит для размещения на стенах в 3D играх, верно? Ты делаешь свою собственную сцену Button3D, которая объявляет свой сигнал signal pressed, и которую можно поместить в 3D мире, чтобы игрок мог с ней взаимодействовать в пространстве (press E to...). Теперь тебе достаточно закинуть эту Button3D в любое место сцены и подсоединить её сигнал к методам какого-либо другого объекта, например, гаражной двери, лампочки, радио и т.д. При этом ты можешь закинуть просто кнопку, ни с чем её не соединяя - и она по-прежнему будет работать, хоть её нажатие и не влияет ни на что (нет обработчиков).
>к ноде можно обратиться напрямую через $?
Так ты связываешь код с к конкретной сценой, в случае с кнопкой у тебя будет $lamp.enable = true, но что, если теперь тебе не лампа нужна, а радиоприёмник или дверь? Ты же не будешь создавать тысячу скриптов типа button_lamp, button_door, button_radio и т.д., в каждый из которых отличается от остальных только строчкой с $.
Конечно, можно написать так:
>@export var node: Node
>node.do_something()
Но во-первых, если мы хотим соблюдать строгую типизацию, возникают трудности с тем, что можно положить в эту переменную, а во-вторых, если ты забудешь положить туда ноду или нода по какой-то причине исчезнет из сцены, твой скрипт сломается. Конечно, можно добавить проверку if node: node.do..., но это не решает всех проблем, т.к. инвалидная ссылка не всегда null, и единственный надёжный способ проверки - через WeakRef...
>Какой способ производительнее?
Тут вопрос не в производительности, а в удобстве и гибкости разработки. Но сигналы, по идее, быстрее обращения через $, потому что:
- $нода - это сокращение self.get_node("нода")
- строка "нода" создаёт новый объект NodePath
- get_node() как-то ищет ноду в дереве нод
- только потом вызывается метод ноды.
С сигналами, если у тебя что-то привязано к сигналу, оно сразу выполняется, и поскольку это один из самых важных концептов движка, внутри оно наверняка очень сильно оптимизировано (сигналы буквально на всех нодах).
Ты можешь ускорить обращение через @export ноды или через @onready, заранее получив ссылку на ноду, но это не решает тех проблем, описанных выше.
>>3159
>организовать обмен данными между сценами
Что ты имеешь в виду? Если ты используешь для смены сцены встроенную функцию SceneTree.change_scene, то я не рекомендую так делать - лучше заменять часть дерева целой сцены, так у тебя будет больше контроля. Если всё же хочешь заменять сцены этой функцией, то тебе придётся добавлять ноды в "автозагрузку" и передавать данные через эти ноды - они никак не затрагиваются "сменой сцены".
Если ты имеешь в виду передачу данных вроде передачи предмета из инвентаря игрока на пол или в верстак, то тут уже всё зависит от того, как у тебя игра устроена. Чего-то универсального тут не посоветуешь.
>>3171
>сами движки используют синглтоны
Потому что у тебя не может быть два экземпляра Engine, два экземпляра OS. А вот для экземпляра Player, два экземпляра WorldMap и т.д. - запросто. Новички обманываются синглтонами и потом не могут понять, почему движок не даёт им создать второго Player без кучи фатальных ошибок в коде.
В большинстве игр синглтоны не нужны. Синглтон нужен только если тебе вот прям обязательно нужно выбить в граните "сцена God может быть лишь одна и обращаться к ней нужно только с большой буквы". Естественно, что это очень вредный антипаттерн.
Этого не слушай, он уверовал в Синглтон и теперь проповедует о его могуществе ньюфагам: >>3162
>Не слушай их и не бойся синглтонов.
Ага, обязательно обмазывай весь код кучей лишних Имён, которые потом хрен вырежешь из кода, когда они неизбежно пукнут и обмякнут кучей ошибок.
Особенно смешно смотреть на то, как новички объявляют синглтон Global и завязывают на него всю игру, по сути высирая тонну бесполезной лапши, которую они даже сами не смогут использовать для другой своей игры, т.к. всё слишком запутано в этом божественном объекте, на который молятся все остальные скрипты игры.
Но если ты любишь трудности, тогда можешь хоть намагниченной иголкой биты в жёстком диске переворачивать, программируя игру в машинных кодах - бояться тут нечего, это просто форма БДСМ.
>В том же анриле
>никто не жалуется.
Это потому что:
- ААА студии сами могут переделать движок;
- нищих индюков никто слушать не будет, лол;
- синглтоны движка != скриптолапша твоей игры.
>перекинул соединения с кнопки на Timer.timeout
>Код при этом никак менять не нужно
Чёт не подумал сразу. На самом деле, у сигналов с разными аргументами должны быть разные обработчики... По крайней мере, если ты хочешь статическую типизацию... Совсем без изменений в коде можно перекинуть только сигналы с одинаковыми аргументами (особенно их количеством).
>is_instance_valid
Раньше с ней проблемы какие-то были.
Алсо, мне не нравится такая длинная запись...
Где ты там ECS увидел? ECS совсем про другое.
Уже сам нашел, надо было тип hint_color source_color поствить
Теперь не дает назначить COLOR и пишет что это константа
Надо было ALBEDO юзать оказывается.
Классная документация, кайфую. Стена текста больше чем этот тред и простого примера как прокинуть цвет и покрасить им пиксели нет.
>Классная документация, кайфую. Стена текста больше чем этот тред и простого примера как прокинуть цвет и покрасить им пиксели нет.
Документация хорошая, просто она не для тебя.
Ищи туториалы для самых маленьких.
Алсо, судя по твоим вопросам рано тебе в шейдеры.
Абсолютно норм. На то они и "звездные объекты". Только долбаеб будет делать синглтоном 100500 незначительных объектов. Шина тоже звездный объект.
Если быть точнее то без глобальных переменных ни одна сложная программа не обойдется. У каждой сложной программы по крайней мере есть Composition Root https://medium.com/@cfryerdev/dependency-injection-composition-root-418a1bb19130
Как-то хуево пояснил.
1) Даже если у тебя код модульный и все круто, в программе нет глобальной области видимости. У тебя есть модуль с состоянием. Ты этот модуль импортирует в 100500 других модулей. Состояние глобальное.
2) Ты не можешь программировать без глобального состояния. Ты не можешь с помошью ивентов в шине синхронизировать 100500 состояний если тебе именно требуется одно глобальное состояние
3( Ты должен организовать какой-то протокол мутирования этого состояния юзерами этого состяния.
>звездный объект
Конкретнее давай, не выдумывай новые термины. Ты таким образом божественный объект зовёшь?
>100500 незначительных объектов
Да, лучше 1 god object, который всё про всех лучше всех знает и всё на свете умеет без посторонней помощи. Зачем тебе вообще ООП, зачем тебе ноды, ресурсы и вообще какой-то там движок, если ты можешь всю игру в один скрипт уместить?
>>3220
>без глобальных переменных ни одна сложная программа не обойдется
БЕЗ ВОДЫ ТЕБЕ НЕ ВЫЖИТЬ
@
ВЫПИЛ 10 ЛИТРОВ ЗА ЧАС И УМЕР
@
НО ГОВОРИЛИ ЖЕ ЧТО БЕЗ ВОДЫ НЕ ВЫЖИТЬ
>>3227 >>3228
Понятия не имею, о чём вы теперь спорите, но я подорвался на всех этих глобальных сущностях несколько раз и больше не собираюсь.
Если что-то можно изолировать - это необходимо изолировать. В этом один из фундаментальных принципов ООП - инкапсуляция. Если у вас код хоть немного запачкан ссылками на что угодно "где-то там", то это нарушение инкапсуляции и ваш код уже начал разъезжаться в непонятную хрень.
И чем дальше - тем только хуже.
Конечно, всё относительно. API движка мы вообще не рассматриваем в этом споре - не надо про Input и прочее, ведь движок вы не каждый день меняете.
Это я все один писал.
>не выдумывай новые термины. Ты таким образом божественный объект зовёшь?
Глобальный стейт.
>Да, лучше 1 god object, который всё про всех лучше всех знает и всё на свете умеет без посторонней помощи.
Не он обо всех знает, а все про него знают. Это две больших разницы.
Я сказал что без глобального стейта программы не пишутся. Так что нет альтернативы синглтоны (или что-то другое что этот глобальный стейт хранит) или события.
>В этом один из фундаментальных принципов ООП - инкапсуляция.
Инкапсуляция тут не причем если тебе нужно врямя суток в игре сделать, и тобы все обекты игры на это время суток реагировали
Я с телеги принёс
480x360, 4:10
Эй, ОП, сходи на скуфуслуги, выпиши себе альтушку!
>без глобального стейта программы не пишутся
Наличие у программы глобального состояния не значит ни что об этом состоянии должны знать все компоненты программы, ни что это состояние должны мочь модифицировать любые компоненты программы. Если у тебя где-то в глобально доступном месте есть галочка "игрок проиграл", её могут видеть и изменять любые части игры - это хорошо? Допустим, что это не плохо - но зачем так делать? Ты планируешь читать/изменять это состояние из случайной строчки кода в случайном файле? Нет? Тогда зачем она глобально всем доступна? Запакуй её куда-нибудь подальше и выдавай строго по разрешению, чтоб никто не мог тайком её дёргать. Даже если ты работаешь один - накодишь что-то в плохом настроении, а через неделю не разберёшься, что ты накодил.
>если тебе нужно время суток в игре сделать
Делаю систему времени и размещаю её в игровом мире, который не является глобальной сущностью.
>и чтобы все объекты игры на это время суток реагировали
Зачем всем объектам игры реагировать на время суток? У тебя в любой игре будет масса объектов, которым время суток вообще никак не нужно - а оно у тебя отовсюду доступно. Ещё меньше будет объектов которые могут как-то повлиять на течение времени - а оно у тебя кем угодно изменяется.
Если у тебя время суток доступно откуда угодно, однажды ты можешь решить на скорую руку изменить время из какого-нибудь мутного участка кода. В этот момент тебе будет казаться, что это оправданное решение и ничего плохого из этого не будет - игра ведь продолжает работать, ничего не сломалось. Пока не сломалось. Но ты уже запутал клубок и дальше он будет только затягиваться, если ты не решишь заняться рефакторингом. Потому что ты обязательно забудешь, где у тебя время реально читается и модифицируется, а где только доступно.
А ещё ты можешь захотеть сделать в игре, скажем, телевизор с фильмами - и фильмы эти "снимать" прямо в игровом мире. Вот только в игре сейчас ночь, а по телевизору фильм в полдень - ты не можешь просто разместить камеру в реальном игровом мире, тебе нужна копия. Если твой игровой мир может существовать сам по себе, обладая собственной, независимой системой времени, ты легко сделаешь независимую модель мира для телевизора - у которой будет своё время. Если же ты сделал систему времени синглтоном и связал с ним кучу других файлов, ты либо вообще не сможешь сделать задуманную фичу, либо убьёшь кучу времени на рефакторинг, спотыкаясь на непонятных ошибках, о причинах которых ты наверняка давно забыл (потому что дёргал синглтон из рандомных мест в коде).
На пикриле у системы времени строго определённое место в дереве сцены и доступ к ней регулируется. Если ты не используешь хрень вроде get_parent().get_parent() или get_node("/"), а корректно объявляешь @export в нодах, легко понять, кто получает доступ к системе времени. Тут не будет внезапных строк вида "WorldTime.time" где-то в середине 1000-строчного скрипта, в заголовке которого (и инспекторе) нет ни слова о системе времени. Ты можешь заменить систему времени на альтернативную или вообще заткнуть пустой заглушкой, чтоб исключить её из геймплея. Можешь создать несколько миров с разными системами времени, в которых будут полностью независимые ИИ, живущие по разным графикам. И если ты перетащишь свою систему ИИ в новый проект, тебе не обязательно срочно объявлять систему времени или переносить вместе с системой ИИ старую систему времени - она сможет работать и без неё (скажем, твои NPC могут жить вне времени, если данных об актуальном времени почему-то нет).
Нет, я не говорю, что все должны делать именно так. Но я на грабли синглтонов наступил несколько раз и результат мне не понравился. Это только в самом начале кажется удобно, пока о будущих проблемах ничего не знаешь.
>без глобального стейта программы не пишутся
Наличие у программы глобального состояния не значит ни что об этом состоянии должны знать все компоненты программы, ни что это состояние должны мочь модифицировать любые компоненты программы. Если у тебя где-то в глобально доступном месте есть галочка "игрок проиграл", её могут видеть и изменять любые части игры - это хорошо? Допустим, что это не плохо - но зачем так делать? Ты планируешь читать/изменять это состояние из случайной строчки кода в случайном файле? Нет? Тогда зачем она глобально всем доступна? Запакуй её куда-нибудь подальше и выдавай строго по разрешению, чтоб никто не мог тайком её дёргать. Даже если ты работаешь один - накодишь что-то в плохом настроении, а через неделю не разберёшься, что ты накодил.
>если тебе нужно время суток в игре сделать
Делаю систему времени и размещаю её в игровом мире, который не является глобальной сущностью.
>и чтобы все объекты игры на это время суток реагировали
Зачем всем объектам игры реагировать на время суток? У тебя в любой игре будет масса объектов, которым время суток вообще никак не нужно - а оно у тебя отовсюду доступно. Ещё меньше будет объектов которые могут как-то повлиять на течение времени - а оно у тебя кем угодно изменяется.
Если у тебя время суток доступно откуда угодно, однажды ты можешь решить на скорую руку изменить время из какого-нибудь мутного участка кода. В этот момент тебе будет казаться, что это оправданное решение и ничего плохого из этого не будет - игра ведь продолжает работать, ничего не сломалось. Пока не сломалось. Но ты уже запутал клубок и дальше он будет только затягиваться, если ты не решишь заняться рефакторингом. Потому что ты обязательно забудешь, где у тебя время реально читается и модифицируется, а где только доступно.
А ещё ты можешь захотеть сделать в игре, скажем, телевизор с фильмами - и фильмы эти "снимать" прямо в игровом мире. Вот только в игре сейчас ночь, а по телевизору фильм в полдень - ты не можешь просто разместить камеру в реальном игровом мире, тебе нужна копия. Если твой игровой мир может существовать сам по себе, обладая собственной, независимой системой времени, ты легко сделаешь независимую модель мира для телевизора - у которой будет своё время. Если же ты сделал систему времени синглтоном и связал с ним кучу других файлов, ты либо вообще не сможешь сделать задуманную фичу, либо убьёшь кучу времени на рефакторинг, спотыкаясь на непонятных ошибках, о причинах которых ты наверняка давно забыл (потому что дёргал синглтон из рандомных мест в коде).
На пикриле у системы времени строго определённое место в дереве сцены и доступ к ней регулируется. Если ты не используешь хрень вроде get_parent().get_parent() или get_node("/"), а корректно объявляешь @export в нодах, легко понять, кто получает доступ к системе времени. Тут не будет внезапных строк вида "WorldTime.time" где-то в середине 1000-строчного скрипта, в заголовке которого (и инспекторе) нет ни слова о системе времени. Ты можешь заменить систему времени на альтернативную или вообще заткнуть пустой заглушкой, чтоб исключить её из геймплея. Можешь создать несколько миров с разными системами времени, в которых будут полностью независимые ИИ, живущие по разным графикам. И если ты перетащишь свою систему ИИ в новый проект, тебе не обязательно срочно объявлять систему времени или переносить вместе с системой ИИ старую систему времени - она сможет работать и без неё (скажем, твои NPC могут жить вне времени, если данных об актуальном времени почему-то нет).
Нет, я не говорю, что все должны делать именно так. Но я на грабли синглтонов наступил несколько раз и результат мне не понравился. Это только в самом начале кажется удобно, пока о будущих проблемах ничего не знаешь.
Во-первых, ты безыгорный шиз, который воюет с синглтонами.
Во-вторых, почему шина на второй картинке не синглтон?
В-третьих, что означают стрелочки?
>ты безыгорный
Есть прототипы игр, я в них играю.
>воюет с синглтонами
Потому что жопа сгорела с них.
>на второй картинке не синглтон
По-быстрому накидал же, долго не думал.
>что означают стрелочки
Ну, типа, кто кем владеет/управляет:
А -> Б
А командует Б как захочет (дёргает методы и поля).
Б может только просить А (излучает сигналы).
"Call down, signal up", забыл что ли?
1024x768, 0:54
Внезапно обнаружил что glTF версия моделей на скетчфабе уже имеет ao/metallic/roughness текстуры сплавленными в одну orm-текстуру. Вот бы времени сэкономил если бы удосужился посмотреть раньше.
Нашел в найстроках захвата экрана OBS параметр скорости захвата и поставил "fastest", запись снова стала гладкой. Странная фигня.
Выглядит-то лампово, но где геймплей?
Хорошо, ты продемонстрировал всем, что умеешь красиво флипать ассеты в ВСЖ-стиль. Молодец. Теперь возвращайся к блокингу и пили уже геймплей. Иначе велика вероятность, что уже напиленные тобой квартиры придётся долго и нудно переделывать.
Я в ахуе. Им говоришь, что игру делать надо, а не демку красивую с тенями и глобальной иллюминацией. Им видосы показываешь с блокингом от именитых студий (блокинг сцена из анчартеда, например). Нет, не слушают нихуя, продолжают лепить постпродакшен на стадии предпродакшена.
И да, я безыгорник, напоминаю, я диван, у меня нет имени, у меня нет авторитета.
Я не он, но будем откровенны, своей игрой тут вряд кто-нибудь озолотится. Делонье игрочьтки - для местных больше хобби, чем способ заработка, так что надо делать то - что больше интересно.
Заработок тут не при чём. Я бы поиграл в сх-лайк от анона, но с таким подходом, он наиграется в декорацию сценок с брождением по ним в дебаге и отыгрышем в голове. И всё. Ничего кроме видосов в треде мы не увидим.
Я не правильно выразился, не заработок. Я больше имел ввиду, что большинству важнее делать с удовольствием, чем сделать в итоге.
>он наиграется в декорацию сценок с брождением по ним в дебаге и отыгрышем в голове
Как будто что-то плохое.
>Ничего кроме видосов в треде мы не увидим.
Ничеси, в треде будут даже видосы.
Архитектура на пике в начале главы.
В его реализации, и тэги и компоненты - наследники энтити.
Где-то дальше об этом пишется, можешь считать что допустимые компоненты - это такие энтити напрямую прикрепленные к миру.
https://www.flecs.dev/flecs/md_docs_2Manual.html#component-handles
Понял, спасибо, квикстарт внезапно оказался быстрым, а не подробным
Вот да.
Уважаемые, как сделать Camera2D текущей? Раньше был чекбокс Current, которого у меня почему-то нет.
Первый пик это из интернетов (чекбокс есть), второй пик это мой годот 4.2.2
current больше нет, есть enabled, там немного другая логика.
Читай документацию.
https://docs.godotengine.org/en/stable/classes/class_camera2d.html
>bool enabled = true
>Controls whether the camera can be active or not. If true, the Camera2D will become the main camera when it enters the scene tree and there is no active camera currently (see Viewport.get_camera_2d).
>When the camera is currently active and enabled is set to false, the next enabled Camera2D in the scene tree will become active.
>bool is_current ( )
>Returns true if this Camera2D is the active camera (see Viewport.get_camera_2d).
>void make_current ( )
>Forces this Camera2D to become the current active one. enabled must be true.
Перевод deepl.com для самых маленьких:
>bool enabled = true
>Управляет тем, может ли камера быть активной или нет. Если значение true, то Camera2D станет основной камерой, когда она войдет в дерево сцены и в данный момент нет активной камеры (см. Viewport.get_camera_2d).
>Если камера активна в данный момент, а значение enabled равно false, то активной станет следующая включенная Camera2D в дереве сцены.
>bool is_current ( )
>Возвращает true, если эта Camera2D является активной камерой (см. Viewport.get_camera_2d).
>void make_current ( )
>Принуждает эту Camera2D стать текущей активной камерой. enabled должно быть true.
Слушай, ещё помощь нужна, поясни пожалуйста, как компонентам часть значений менять, я вижу только set. Неужели надо создавать рид онли переменные, брать из них всё, кроме того, что я хочу изменить и потом при помощи set заменять старый компонент?
А, нашёл сам. GetMut возвращает изменяемый. Ну такое, могли бы такие очевидно нужные вещи на поверхности показывать...
Смотрю всякие видеоуроки и читаю, пишут, что экспорт спрайт листа в годоте, это обычно создание сцены, добавление AnimatedSprite2d, там создание всяких idle, run, attack и т.п. анимаций через импорт спрайт-листа и выбор фреймов, скрипты. И потом добавление уже в нужную сцену.
А что делать, если мобов много? Создавать для каждого сцену и настраивать в ручную?
Если у тебя там реально сотни разных мобов, пиши скрипт для автоматического импорта и настройки. Скрипты можно выполнять прямо в редакторе. Все операции в GUI редактора можно делать из кода.
https://docs.godotengine.org/en/stable/tutorials/plugins/running_code_in_the_editor.html
Хранить мобов лучше отдельными сценами, если потребуется что-то исправить вручную или создать новый вариант имеющегося моба.
Подумай над тем, что возможно в этом случае их стоит разделить на отдельные компоненты.
Да не, тут вопрос не в отдельных компонентах а в нежелании создавать лишний раз переменные. Хотя из моего эксперимента с системами - они сами могут по менять содержимое без лишних приседаний и GetMut. Так-то у меня есть уже игра-в-разработке, но мне что-то не нравится как библиотека Arch работает, вот и решил сменить шило на мыло.
Понимаю, что ты молодой шутливый, но я сортировкой ассетов занимаюсь свободными вечерами, сажусь под какой нибудь сериальчик или анимце.
А так, поищи в ассетах по import или animation или wizard.
Вот этот, например, импортирует из aseprite (там есть возможность называть промежутки кадров каким то словом).
https://godotengine.org/asset-library/asset/1415
Или вот другой
https://godotengine.org/asset-library/asset/1880
Может есть и для чего-то другого.
Как анон выше сказал, можешь написать свой, под свою схему названий файлов.
>Ну это же на английском, друг.
Господи, дауничи ебаные, вы до сих пор не в курсе что уже давно можно переводить звуковую дорожку ютюба (да хоть порнхаба, блять!) расширением для браузера? Откудаж вы берётесь? Вы в бункере живёте?
> расширением для браузера
Оно не работает. Для хлебушков (типа меня) проще яндекс.браузер поставить и в нём всё искаропки без пердолинга работает.
У людей большая инерционность мышления.
Я вот только недавно нашел этому применение в обратную сторону (рус->англ)
Я с четверкой еще не работал, знаю только что за миграцию проджект менеджер Юрка Сизов отвечал.
Толсто. Переименовали как раз неудачные названия, тянущиеся с легаси.
Потому что ты кинул проект с файлом godot.project. Годот в этом случае на всякий случай отключает папку, вдруг у тебя туда реально другой проект случайно скопировался.
И даже если я ставлю ассет не вручную, а из годота через assetlib, я его не вижу в окне FileSystem после установки
Ну перезапусти попробуй. Там закешировалось наверняка.
Чем вызван вопрос? Что тебе мешает?
Если мобы отличаются только косметически, т.е. условным цветом кожи - это одна сцена с опциями.
Если мобы отличаются радикально, т.е. имеют абсолютно разные способности - это разные сцены.
Если мобы отличаются, но имеют много общего между собой, т.е. их можно выстроить в некую иерархию как реальных животных - это сцены с наследованием, т.е. имеют предка и наследников.
Можно пойти путём компонентов и собирать мобов из множества кусочков прямо на ходу. Но тебе будет банально удобнее тестировать, имея набор заранее собранных сцен с наборами компонентов, чем если ты будешь их в коде соединять в дерево.
В целом - экспериментируй и смотри сам, что тебе больше нравится или лучше идёт твоим задумкам.
>Почему с ним такой пиздос?
Приведи примеры конкретных названий, тогда будем разбираться. Могу найти обсуждения на гитхабе, где переименования обсуждали (с голосованием).
Алсо, переименовать давно хотели, но ждали 4.0, чтоб соблюдать правила https://semver.org/
Обычно да, делаю в духе MVVC, когда есть сцены под всех мобов которые сами занимаются своими анимациями, а эта сцена уже вставляется в какую-то общую сцену персонажа, который имеет управление игроком или поведение ии и переключает анимации соответствующе.
>отвалится на какой-нибудь китайской мобиле
https://docs.godotengine.org/en/stable/classes/class_videostreamtheora.html
>The Theora codec is decoded on the CPU.
— должна работать на любом процессоре, но тратит ресурсы из-за отсутствия хардварного ускорения.
А тебе какие видео нужно проигрывать?
>decoded on the CPU
О, найс, проебал это в документации. Спасибо.
>А тебе какие видео нужно проигрывать?
Делаю экстренную помощь-подсказки для самых тугодумов. Решил что нет ничего нагляднее чем 2-4 секунды видео.
Почему жсонину не прочитать?
А хрен его знает. Может, проще написать андроид плагин для такого?
В 3 есть какая-то недокументированная функция OS.native_video_play. Но с ней тоже непонятно.
Ну там все написано
У типа int нет поля error.
Это значит, что result - int.
parse() возвращает не объект пару (error, result)
Он возвращает код ошибки, не помню какой, ERR_чтото, либо OK
Проверяй не result.error, а сам result != OK.
Если OK, то данные не в result.result, а в json.data.
>подсказки для самых тугодумов
>2-4 секунды видео
Лучше делать скриптами из игровых ресурсов:
- актуальное отображение, даже если изменятся иконки, текстуры, биндинги клавиш и т.д.;
- максимальное разрешение без артефактов, при том практически не добавляет лишнего веса игре;
- можно сделать интерактивным и пошаговым, чтоб игрок сам подсвеченные тобой кнопки нажимал в комфортном ему темпе, успевая читать надписи;
- легче встроить в игровой процесс/мир - у игрока не будет переключения ментального контекста.
Имхо, видео-подсказки - прошлый век. Как и список портянок со скриншотами-иллюстрациями. Ты игру делаешь или википедию про игру? Обучай игрока интерактивно, иначе не поймёт или заскучает.
Актуальный пример кода есть в документации.
Жмёшь ctrl+клик по JSON в коде и читаешь:
https://docs.godotengine.org/en/stable/classes/class_json.html
Для JSON рекомендую https://hjson.github.io/
Сильно упрощает редактирование и поиск ошибок.
Если не хочешь делать ролик на движке, то;
Видео это просто быстро меняющиеся картинки.
Видеофайл просто использует хиьрое сжатие, поэтому зпнимает мало места, но тормозит.
Ты можешь показать просто слайдшоу из 30 пнг в секунду. Возможно они даже сожмутся в apk нормально.
Ты гений, епта. Здоровья матушке.
extends Node
func _ready():
load_combinations("res://src/combinations.json")
func load_combinations(file_path):
var file = FileAccess.open(file_path, FileAccess.READ)
if file:
var json_text = file.get_as_text()
print("JSON Text:")
print(json_text)
file.close()
var json = JSON.new()
var error = json.parse(json_text)
if error != OK:
print("Error parsing JSON: ", error)
else:
print("Combinations loaded successfully:")
print(json.data) # Accessing parsed data from the JSON instance
else:
print("Combinations file not found")
Спасибо, я что-то путаюсь в годотошной доке
>слайдшоу из 30 пнг в секунду. Возможно они даже сожмутся в apk нормально.
PNG не сожмутся, потому что они уже используют максимально эффективное сжатие без потерь. Дальнейшее сжатие возможно только если у тебя почти одинаковые PNG файлы, с большими повторяющимися блоками, что в случае геймплейного видео маловероятно.
Рекомендую не изобретать велосипед и сделать как во всех приличных мобильных играх сделано - игра блокирует все возможные пути кроме верного, игрок запоминает это на уровне мышечной памяти.
>>3475
Алсо, если геймплей такой сложный, что ты хочешь показывать летсплей, стоит ли оно вообще того? Не лучше ли будет снизить планку сложности? Игрок не станет умнее от того, что решит твой ребус.
>Алсо, если геймплей такой сложный, что ты хочешь показывать летсплей, стоит ли оно вообще того? Не лучше ли будет снизить планку сложности?
Геймплей не сложный, я просто разочаровался в способностях игроков, особенно мобильных. Мои предыдущие игры показали что механики, которые тебе и мне кажутся интуитивными, для других окажутся невыполнимыми. Текст такие игроки не читают, думать ленятся, а за ручку всю игру держать не станешь.
Вот хороший видос на эту тему: https://www.youtube.com/watch?v=ax7f3JZJHSw
^ и опять же, этот видос про взрослого человека из развитой страны, тогда как среди мобильных геймеров полно детей из задниц мира с ограниченным игровым опытом, компов они не видели, английский не знают, зато могут на изи влепить тебе 1 балл в гугл плее.
Ахаха, когда знаешь половину ассетов, потому что сам их тоже двигаешь и расставляешь.
И тоже коммиблочная романтика. Как же без этого, дааа. Где-то там, в одном из этих коммиблоков, ходит пеппа в костюме годетты.
Как посмотреть? Видеоскачиватели выдают ошибку.
>>3534
>не любит коммиблочную романтику (ВСЖ)
Что это вообще за мем?
Мне вот нравится атмосфера условного Гигахруща, но однотипные игры уровня "вот комната, в ней есть ковёр, диван, шкаф, телевизор" я не понимаю. У меня ИРЛ дома точно такая же обстановка, какой смысл делать симулятор ходьбы виртуальный музей про мою квартиру в десятках игр?
> Что это вообще за мем?
Происходит от знаменитого высказывания "забыл в какой стране живёшь?" сократилось до ВСЖ. Суть ты уже сам описал:
> "вот комната, в ней есть ковёр, диван, шкаф, телевизор"
К сожалению, любимый тобой гигахрущ - это тоже ВСЖ, причём самый апогей.
>Текст такие игроки не читают, думать ленятся, а за ручку всю игру держать не станешь.
ПРОСТО блокируешь всё управление кроме одной единственной кнопки, которую нужно нажать, или единственного элемента, который нужно сдвинуть.
Мобильные игры так и учат:
1. Нажми сюда, чтобы открыть инвентарь.
2. Свайпом объедини два предмета в новый.
3. Нажми сюда, чтобы надеть предмет на себя.
4. Нажми сюда, чтобы повысить уровень предмета.
5. Нажми сюда, чтобы закрыть инвентарь.
6. Нажми сюда, чтобы использовать предмет.
7. Посмотри сюда, чтобы увидеть эффект предмета.
8. Ты восхитительный игрок, вот тебе лутбокс.
9. Нажми сюда, чтобы открыть лутбокс...
Потом ты можешь делать что захочешь, но ты уже знаешь основные элементы управления и задачи.
>этот видос про взрослого человека
Это видос про человека с явным топографическим кретинизмом (ваще не ориентируется на местности), отсутствием любопытства (не пытается нажать все возможные кнопки на геймпаде - НА ГЕЙМПАДЕ, анон, там буквально 3.5 кнопки - эти устройства специально для детей, не приученных к взрослой клавомыши) с полным отсутствием способностей к обучению (даже осознав, что мышку НЕОБХОДИМО двигать, она продолжает ходить боком как краб).
Таким людям сложные игры противопоказаны. Их предел развлечений - мять в руках мягкие игрушки.
Алсо, в видосе виден тупой геймдизайн ААА игр: налепливают кучу реалистичных декораций, но механики игры противоречат этим декорациям. Например, там, где игра требует бежать по строго определённому пути, наказывая игрока невидимой килзоной вместо ясно видных и понятных барьеров. Проблема не в игроке, а в дизайнерах и сценаристе.
Или тот же дум - заставляет играть единственным возможным способом, наказывая игрока за любое отклонение от задумки дизайнера: стрелять в лоб с дробовика вместо использования огнестрела как огнестрела, нажимать кнопку Е вместо очевидного использования игровых механик (бочки). Опять же, виноват тут только геймдизайнер, а не игрок.
>Почему я не могу сделать так?
>Потому что потому)))) и ваще игры сложна делать)
Нет, потому что геймдизайнер дурачок и влошил все средства в реалистичные декорации вместо базовых игровых механик и их взаимодействия друг с другом.
Так и представляю:
>Тестировщик: бочки не наносят урон врагам...
>Дизайнер: у нас нет времени фиксить это.
>Тестировщик: игрок может пройти не тем путём.
>Дизайнер: аааыыы... ну поставим килзону, лол.
>Тестировщик: а сюда почему нельзя прыгнуть?
>Дизайнер: так задумано, иди по стрелочке!!!
>Тестировщик: залез в дом и ничего не случилось.
>Дизайнер: ну что за люди, иди по стрелочке...
Современные игры такие современные. Скорее бы сверхинтеллекты AGI порешали весь ААА геймдев, лишив этих дурачков контроля над дизайном игр.
>могут на изи влепить тебе 1 балл в гугл плее
Оценки в Гугле давно потеряли смысл, их лепят от балды все, кому не лень. Ребёнок тебе влепит 1 балл не потому, что ему что-то не понравилось, а потому, что он может нажать кнопку голосования. Тот, кому не понравилось, скорее просто удалит и забудет.
>Текст такие игроки не читают, думать ленятся, а за ручку всю игру держать не станешь.
ПРОСТО блокируешь всё управление кроме одной единственной кнопки, которую нужно нажать, или единственного элемента, который нужно сдвинуть.
Мобильные игры так и учат:
1. Нажми сюда, чтобы открыть инвентарь.
2. Свайпом объедини два предмета в новый.
3. Нажми сюда, чтобы надеть предмет на себя.
4. Нажми сюда, чтобы повысить уровень предмета.
5. Нажми сюда, чтобы закрыть инвентарь.
6. Нажми сюда, чтобы использовать предмет.
7. Посмотри сюда, чтобы увидеть эффект предмета.
8. Ты восхитительный игрок, вот тебе лутбокс.
9. Нажми сюда, чтобы открыть лутбокс...
Потом ты можешь делать что захочешь, но ты уже знаешь основные элементы управления и задачи.
>этот видос про взрослого человека
Это видос про человека с явным топографическим кретинизмом (ваще не ориентируется на местности), отсутствием любопытства (не пытается нажать все возможные кнопки на геймпаде - НА ГЕЙМПАДЕ, анон, там буквально 3.5 кнопки - эти устройства специально для детей, не приученных к взрослой клавомыши) с полным отсутствием способностей к обучению (даже осознав, что мышку НЕОБХОДИМО двигать, она продолжает ходить боком как краб).
Таким людям сложные игры противопоказаны. Их предел развлечений - мять в руках мягкие игрушки.
Алсо, в видосе виден тупой геймдизайн ААА игр: налепливают кучу реалистичных декораций, но механики игры противоречат этим декорациям. Например, там, где игра требует бежать по строго определённому пути, наказывая игрока невидимой килзоной вместо ясно видных и понятных барьеров. Проблема не в игроке, а в дизайнерах и сценаристе.
Или тот же дум - заставляет играть единственным возможным способом, наказывая игрока за любое отклонение от задумки дизайнера: стрелять в лоб с дробовика вместо использования огнестрела как огнестрела, нажимать кнопку Е вместо очевидного использования игровых механик (бочки). Опять же, виноват тут только геймдизайнер, а не игрок.
>Почему я не могу сделать так?
>Потому что потому)))) и ваще игры сложна делать)
Нет, потому что геймдизайнер дурачок и влошил все средства в реалистичные декорации вместо базовых игровых механик и их взаимодействия друг с другом.
Так и представляю:
>Тестировщик: бочки не наносят урон врагам...
>Дизайнер: у нас нет времени фиксить это.
>Тестировщик: игрок может пройти не тем путём.
>Дизайнер: аааыыы... ну поставим килзону, лол.
>Тестировщик: а сюда почему нельзя прыгнуть?
>Дизайнер: так задумано, иди по стрелочке!!!
>Тестировщик: залез в дом и ничего не случилось.
>Дизайнер: ну что за люди, иди по стрелочке...
Современные игры такие современные. Скорее бы сверхинтеллекты AGI порешали весь ААА геймдев, лишив этих дурачков контроля над дизайном игр.
>могут на изи влепить тебе 1 балл в гугл плее
Оценки в Гугле давно потеряли смысл, их лепят от балды все, кому не лень. Ребёнок тебе влепит 1 балл не потому, что ему что-то не понравилось, а потому, что он может нажать кнопку голосования. Тот, кому не понравилось, скорее просто удалит и забудет.
Вопрос - у меня есть ряд однотипных объектов (спрайтов) внутри ноды2д.
На все эти спрайты должен действовать один и тот же скрипт - х.gd
Могу ли я закинуть спрайты в какой-нибудь "контейнер" и назначить скрипт на него? (Чтобы спрайты наследовали скрипт от него)
Или мне все еще нужно назначить этот скрипт на каждый спрайт?
Если выделить их, Attach Script просто не появляется. По одному прокликивать?
Ты можешь получать в скрипте в цикле список детей объекта и делать с ними что хочешь например
Чо пацы, погнали за гаражи! Я у бати две сиги стырил!
очередная бродилка без геймплея, виртуальный музей ВСЖ-детства, которую в общем-то и не доделают
Ты скорее всего смотрел видос без перевода, со своим техническим английским на троечку. Потому что весть твой длиннопост подробно и по пунктам опрокинут в видосе.
Разумно, спс.
Вопрос посложнее - в годоте можно поменять логику наименования дублей?
Например, если я дублирую Спрайт, я получаю Спрайт2. А я хочу получать Спрайт_2
> Attach Script просто не появляется. По одному прокликивать?
У них всё еще есть инспектор, и там всё еще есть поле "скрипт", в которое можно сразу всем скрипт назначить. Но ты верно догадался, что такие вещи лучше делать в одном вышестоящем скрипте.
Хорошо понимаю на слух + там субтитры на русском.
>подробно и по пунктам опрокинут в видосе
Да он просто понтуется тем, что женат, вот и всё.
Он в конце сказал "не советую так делать, пожалуйста, объясняйте новичкам азы игр", что перечёркивает все аргументы в его видео (проблема решена).
>К сожалению, любимый тобой гигахрущ - это тоже ВСЖ, причём самый апогей.
Я представляю себе Гигахрущ как пикрил, но в масштабах целой планеты или всей вселенной:
- хаотичная застройка на крышах соседей;
- лютый срач, который просто некуда девать;
- тяжёлая промышленность в одном доме со школами и развлекательными учреждениями;
- внутри легко заблудиться, однако выходить из этого тесного лабиринта жильцам не нужно, у них всё своё;
- натуральный киберпанк, каким он должен быть, без лишнего блеска, неона и избыточного пространства.
А в играх "ВСЖ" всё слишком чистое и просторное, как будто зашёл в музей, где экспонаты аккуратно расставили, демонстрируя жизнь древних людей.
Если дублируешь через код, то там же задавай и имя. Если менять логику - то пересобирать движок под себя
Читай https://ru.wikipedia.org/wiki/Проблема_XY
Зачем тебе это всё нужно? Ты что-то не то делаешь.
>должен действовать один и тот же скрипт - х.gd
Если я правильно понял твою проблему:
1. Создай сцену, у которой корень - Sprite2D.
2. Сохрани её как-нибудь вроде "element.tscn".
3. Дай ей один общий скрипт "element.gd".
4. Добавляя элементы в какую-то другую сцену, меняй им картинку элемента и другие параметры.
ИЛИ
4. Унаследуй от element.tscn несколько новых сцен, настрой их как следует, сохрани fire.tscn, water.tscn и т.д., и уже эти сцены-потомки используй в сцене.
Использовать "контейнер" не советую, если эти твои элементы должны быть независимыми сущностями. Контейнер имеет смысл для функций, которые нужно производить над большим количеством сущностей независимо от их индивидуальных особенностей.
Т.е. тут вопрос в том, что ты реально хочешь сделать.
>Если выделить их, Attach Script не появляется
Потому что это противоречит воркфлоу движка. Ты должен создавать новые сцены и использовать их, а не возиться с отдельными нодами в одной сцене.
Когда понимаешь эту концепцию, становится легче.
>получаю Спрайт2. А я хочу получать Спрайт_2
Зачем тебе это? Номер ни на что не влияет. Лучше переименуй во что-то осмысленное, чтобы цифры вообще не было в названии, иначе запутаешься.
Почитай документацию об основных концепциях.
Читай https://ru.wikipedia.org/wiki/Проблема_XY
Зачем тебе это всё нужно? Ты что-то не то делаешь.
>должен действовать один и тот же скрипт - х.gd
Если я правильно понял твою проблему:
1. Создай сцену, у которой корень - Sprite2D.
2. Сохрани её как-нибудь вроде "element.tscn".
3. Дай ей один общий скрипт "element.gd".
4. Добавляя элементы в какую-то другую сцену, меняй им картинку элемента и другие параметры.
ИЛИ
4. Унаследуй от element.tscn несколько новых сцен, настрой их как следует, сохрани fire.tscn, water.tscn и т.д., и уже эти сцены-потомки используй в сцене.
Использовать "контейнер" не советую, если эти твои элементы должны быть независимыми сущностями. Контейнер имеет смысл для функций, которые нужно производить над большим количеством сущностей независимо от их индивидуальных особенностей.
Т.е. тут вопрос в том, что ты реально хочешь сделать.
>Если выделить их, Attach Script не появляется
Потому что это противоречит воркфлоу движка. Ты должен создавать новые сцены и использовать их, а не возиться с отдельными нодами в одной сцене.
Когда понимаешь эту концепцию, становится легче.
>получаю Спрайт2. А я хочу получать Спрайт_2
Зачем тебе это? Номер ни на что не влияет. Лучше переименуй во что-то осмысленное, чтобы цифры вообще не было в названии, иначе запутаешься.
Почитай документацию об основных концепциях.
>У меня бы там был шкаф с инструментам
Лол, у меня тоже. Была фальшстена с дверью и внутри много полок да самого верха.
>одинокая бабулька
Думаю, в этом случае там был бы советский столик со скатертью и фотографиями/иконками и возможно цветами, ну или комод хотя они не так были распространены.
А, ещё у моей бабушки на таком столе стояло большое радио с часами. Но правда для этого рядом должна быть радиоточка, а она обычно на кухне вроде как.
>Думаю, в этом случае там был бы советский столик со скатертью и фотографиями/иконками и возможно цветами, ну или комод хотя они не так были распространены.
Вспомнил - комод косметичка с зеркалом. Пасиба.
>объясняйте новичкам азы игр
Что контрится его же примером "у игрока включается туннельное зрение, и он НЕ ВИДИТ ВАШИХ ОБЪЯСНЕНИЙ И БЬЕТСЯ ЛБОМ В СТЕНУ". Алсо, если уж ААА игры не осилили нормальное объяснение, а для ААА игр критично расширить аудиторию - отчасти поэтому туда добавляют сильных женщин, прячут кровь чтобы снизить возрастной рейтинг, льют желтую краску и прочее подобное - то странно ожидать что обскурная инди, слепленная двачером в одно ебало, справится с этим лучше.
Поставь туда слоновью ногу.
Не треко ли?
Так речь не о туториале.
Видишь, как кто-то в игры не играл - хватаешь за руку и начинаешь ему объяснить, что он не так играет в игры и вообще нуб полный. Он слушает и начинает осознавать суть геймерства. Становится геймером и больше не нуждается в туториалах.
В этом основной посыл видео, если отбросить затронутые проблемы с геймдизайнерами.
Э, сам такой.
>закутке у входной двери
>хозяином квартиры была одинокая бабулька
Навали туда всякого хлама, чтобы сложно было разобрать, что есть что. Пакеты, мешки, какие-то тряпки, ящики всех цветов и размеров, банки.
И обязательно нужно ободрать потолок, пол и стены, насрать по всем углам и нарисовать старые потёки. Обжить помещения, чтоб чувствовалась душа.
А то у тебя как будто палата в больнице. Нет, даже в больницах не бывает таких стерильных помещений.
Вдохновляйся реальной жизнью.
Слишком много времени уйдет. Было бы здорово добавить естества в виде потертостей и следов, но слишком долго. Я и так уже затрахался квартиру обставлять.
В Питере есть такое. Идешь по улице архитектура, дорогие бутики, дефелируют модные тяночки. Окно с разбитым стеклом занавешенное грязной половой тряпкой смотрит на тротуар с прохожими и проезжающими мимо трамваями.
Я тебя уверяю, если бы ты сделал эту игру сам, у тебя вышло бы точно такое же. А разгадка проста: хлам и срач сделать намного сложнее, чем "чистые, аккуратные" кубы с текстурами.
> уже затрахался квартиру обставлять
А зачем тебе годот? Квартиры обставлять гораздо удобнее в SweetHome3D - там и режим брождения от первого лица есть.
Хуле там сложного, давай прямо итт сделоем вместе. Щас погодь, я дела доделаю. Набрасывай пока ноды в кучку.
>потертостей и следов, но слишком долго.
Я сам не юзал пока, но вроде 3D декали есть.
https://docs.godotengine.org/en/stable/classes/class_decal.html
>Я и так уже затрахался квартиру обставлять.
Лолшто? Ты ж только коробки по углам расставил и всё.
Вроде есть плагин для более удобной привязки, например:
https://godotengine.org/asset-library/asset/2943
https://youtu.be/cG4yzGOc6SI
К табам у нас ещё не доёбывались. Ctrl+R нажми, \t заменить всё, если ты не игру делаешь, а чужие плагины разглядываешь.
Какая нахуй разница, автор ты или нет, лол? Ты одобряешь подобное, а значит сам не соблюдаешь хороший стиль (либо склонен его не соблюдать). Не удивлюсь, если ты еще босоножки с носками носишь.
> Ты одобряешь подобное
Какое подобное?
Код работает? Работает. Интерфейс в инспектор вынесен? Вынесен. Ты просто работаешь с меню, и не глядишь в код. Попустись уже.
>Код работает? Работает.
Если ты косплеишь дерево, то не надо. С самого начала понятно, что ты скорее всего не умеешь в хороший стиль (и я об этом уже писал в прошлом посте, а ты все пытаешься доказать очевидное)
>Ctrl+R нажми, \t заменить всё
Ты просто не понял, о чём речь.
>чужие плагины разглядываешь
А если там вирус или тормоза?
>пытается выдать "писать уродливый и неконсистентный код" за "тебе просто не нравица"
Иди что ли книжки почитай по прогроммизму, раз не учился нигде.
Не, пчел, это ты тут пытаешься выдать вылизывание кода по десятому кругу за некую продуктивность, за финальный продукт, который можно пощупать и поиграть. Ты как те наивные ньюфаги с идеями на миллион. Сами по себе их идеи не стоят ничего, как ничего не стоит и твой чистый код без законченного продукта.
> вылизывание кода по десятому
Снова пытаешься подменить понятия. Дальше не читал, сорян. Удачи тебе в обучении!
>вылизывание кода по десятому кругу за некую продуктивность, за финальный продукт
Скажи честно: ты обсуждаемый код смотрел или просто бомбанул и срёшься?
https://github.com/diklor/advanced_radial_menu/blob/main/addons/advanced_radial_menu/radial_menu_class.gd
1. Ты взял этот скриптик с гитхаба и не глядя вставил в игру.
2. Изменил параметры через инспектор по своему вкусу.
3. Релизнул игру/апдейт с этим меню (у тебя есть игроки).
4. Игроки (лично уважаемые тобой люди) поиграли и сказали:
>говно какое-то, неудобно, сделай так-то и так, будет лучше
5. Ты открываешь проект, лезешь в инспектор к этому скрипту.
6. Меняешь параметры, но не можешь добиться желаемого.
7. Решаешь всё-таки посмотреть скрипт и доработать его.
8. А там говно уровня "и так сожрут, бесплатное же".
Твои действия?
>а если напишут плохое!
Вот когда напишут тогда и приходи. Спойлер - не напишут, потому что игры нет, и скорее всего не будет. Через год-полтора возни и байтоебства интерес иссякнет, появится новая идея, а текущая пополнит собой архив. И так по кругу у каждого второго гейдева.
Тогда как рядом сидят всякие Тоби Фоксы и на километровых портянках иф-елсов ебашут хиты с фанбазами размером со среднюю страну.
Не забудь про велосипед "Аист".
Пикрил кстати то что заработало мое говно за время с момента релиза, 6 мая вроде дропнул. Немного обидно, да и похуй, сам виноват ибо мимо мейн аудитории яндекса умышленно стрелял.
Короч в планах кликер за неделю, а дальше сидим думаем че делать дальше.
Высираться итт оч редко буду, пакедава.
Маладца, это уже больше чем у половины гд. Продолжай работать. Алсо ты не думай что 50.52р это все, что твоя игра в состоянии заработать. Площадок в интернете много - выкладывай и на другие. Я свои поделки в перерывах от работы раскидываю повсюду. Да, даже если не сможешь обойти санкции и монетизироваться на западной площадке - все равно выкладывай. И лепи ссылки на свои соцсеточки/бложеки/аккаунты.
Пока не доделал, но этот код должен помочь.
Для кругового меню нужно, как минимум:
1. Кнопки (любой Control, но лучше Button).
2. Определить позиции всех кнопок по формуле.
3. Округлить позицию курсора до позиции кнопки.
Всё остальное дорабатывается по желанию и вкусу.
Можно без кнопок (только _draw), но кнопки удобнее.
>муза покинула
>ждал вдхновления
>буду кликер делать
Вдохновляйся. :3
http://store.steampowered.com/app/383080/
> Тогда как рядом сидят всякие Тоби Фоксы и на километровых портянках иф-елсов ебашут хиты с фанбазами размером со среднюю страну.
База!
Не, это отличный код. А то, что он выглядит как хуйня и что его сложно поддерживать - это вкусовщина. За чистотой кода зачем вообще в 2к25 следить, вы шизы что ли.
Мы, пролетарии клавиатуры, в университетах ваших не обучались, чтоб еще о какой-то красоте думать.
@
ВОТ ТАК, ВОТ ТАК, ГОТОВО, НЕПЛОХО ПОЛУЧИЛОСЬ
@
ТАК, А ТЕПЕРЬ ДОБАВИМ КРАСИВУЮ ОБВОДОЧКУ
@
А КРУТО ПОЛУЧИЛОСЬ, С АНИМАЦИЯМИ ВАЩЕ НИШТЯК
@
ВСМЫСЛЕ _DRAW РИСУЕТ ПОВЕРХ СТАНДАРТНОЙ КНОПКИ?
@
ТАК, ПАДАЖЖИ, ЩАС РАЗБЕРЁМСЯ, ЕСЛИ РИСОВАТЬ...
@
А ЕЩЁ НУЖНО ПОВЕРНУТЬ НАДПИСИ ПОД УГЛОМ?..
@
ДА ЛАН, НАКИДАЮ LABEL, TEXTURERECT, ВОТ ЭТО ВСЁ
@
А НЕ, ПОГОДИ, ЧЁТ СЛИШКОМ МНОГО ЛИШНИХ НОД
@
ОЙ ВСЁ, ЩАС НАРИСУЮ ВСЁ МЕНЮ САМ В _DRAW
@
АГА, РАЗОБРАЛСЯ, ВРОДЕ НЕСЛОЖНО ВРАЩАТЬ ЭТО
@
В СМЫСЛЕ НЕ МОГУ ПРОСТО ЗАГНАТЬ ТЕКСТ В RECT2?
@
ТАК-ТО ВРОДЕ НОРМ, НО НАСЛАИВАЕТСЯ СЛИШКОМ
@
ОООООЙ ВСЁ, КАКАЯ-ТО ХРЕНЬ, ПОГУГЛЮ РЕФЕРЕНСЫ
@
А ЧЁ, В СМЫСЛЕ, В БЛЕНДЕРЕ ПРЯМОУГОЛЬНЫЕ КНОПКИ?
@
В НАТУРЕ! ТАК ЛУЧШЕ ПОЛУЧИТСЯ, ЧИТАБЕЛЬНО ЖЕ
@
ДА И ШОРТКАТЫ У СТАНДАРТНЫХ КНОПОК ТОЖЕ ЕСТЬ
@
ТАК-ТАК-ТАК, Я БЫЛ ПРАВ, ВОЗВРАЩАЕМСЯ К BUTTON
@
АААААА, Я ЧТО, ЗРЯ КРАСИВУЮ ОБВОДОЧКУ ДЕЛОЛ?
@
НУ ВСЁ, ЩАС БУДУ ВСЁ ПЕРЕДЕЛЫВАТЬ ЗАНОВО
@
ВОТ ТАК, ВОТ ТАК, ГОТОВО, НЕПЛОХО ПОЛУЧИЛОСЬ
@
ТАК, А ТЕПЕРЬ ДОБАВИМ КРАСИВУЮ ОБВОДОЧКУ
@
А КРУТО ПОЛУЧИЛОСЬ, С АНИМАЦИЯМИ ВАЩЕ НИШТЯК
@
ВСМЫСЛЕ _DRAW РИСУЕТ ПОВЕРХ СТАНДАРТНОЙ КНОПКИ?
@
ТАК, ПАДАЖЖИ, ЩАС РАЗБЕРЁМСЯ, ЕСЛИ РИСОВАТЬ...
@
А ЕЩЁ НУЖНО ПОВЕРНУТЬ НАДПИСИ ПОД УГЛОМ?..
@
ДА ЛАН, НАКИДАЮ LABEL, TEXTURERECT, ВОТ ЭТО ВСЁ
@
А НЕ, ПОГОДИ, ЧЁТ СЛИШКОМ МНОГО ЛИШНИХ НОД
@
ОЙ ВСЁ, ЩАС НАРИСУЮ ВСЁ МЕНЮ САМ В _DRAW
@
АГА, РАЗОБРАЛСЯ, ВРОДЕ НЕСЛОЖНО ВРАЩАТЬ ЭТО
@
В СМЫСЛЕ НЕ МОГУ ПРОСТО ЗАГНАТЬ ТЕКСТ В RECT2?
@
ТАК-ТО ВРОДЕ НОРМ, НО НАСЛАИВАЕТСЯ СЛИШКОМ
@
ОООООЙ ВСЁ, КАКАЯ-ТО ХРЕНЬ, ПОГУГЛЮ РЕФЕРЕНСЫ
@
А ЧЁ, В СМЫСЛЕ, В БЛЕНДЕРЕ ПРЯМОУГОЛЬНЫЕ КНОПКИ?
@
В НАТУРЕ! ТАК ЛУЧШЕ ПОЛУЧИТСЯ, ЧИТАБЕЛЬНО ЖЕ
@
ДА И ШОРТКАТЫ У СТАНДАРТНЫХ КНОПОК ТОЖЕ ЕСТЬ
@
ТАК-ТАК-ТАК, Я БЫЛ ПРАВ, ВОЗВРАЩАЕМСЯ К BUTTON
@
АААААА, Я ЧТО, ЗРЯ КРАСИВУЮ ОБВОДОЧКУ ДЕЛОЛ?
@
НУ ВСЁ, ЩАС БУДУ ВСЁ ПЕРЕДЕЛЫВАТЬ ЗАНОВО
https://www.youtube.com/watch?v=TtziEJZtWXc
В радиальном меню главное - тригонометрия. А что там в секторы засунуть - это мелочи. Ты с тригонометрией разобрался?
Нужно было с самого начала определиться, что именно мне нужно...
>А что там в секторы засунуть - это мелочи.
Не мелочи, это как раз база того, будет игрок им пользоваться или нет. Игроку похер как у тебя реализована тригонометрия внутри
> на одном древнем ноуте запускаю - 4 фпс, на другом, почти таком же древнем и хуевом - 40 фпс
Ненене, давай спеки в студию. Древний древнему рознь. Для тебя они одинаковы, а на деле там в одном штеуд атом и штеуд графика, а на втором амд со встроенным радеоном. Вот и разница.
>почему в Godot источники света кастующие тени так сильно сажают FPS?
>Что можно предпринять, чтобы избежать просадок и получить нормальную картинку?
Источники света и тени по умолчанию динамически обновляются каждый кадр, чтобы учитывать актуальное состояние сцены. Читай документацию - там всё подробно описано, как переключить источники света в статический режим. В большинстве случаев динамические источники света тебе не нужны, если ты просто размещаешь лампочку и не двигаешь её.
Источник света относительно дешёвый, а вот тень - это отдельный рендеринг почти всей видимой игроку сцены с позиции источника света, чтобы нарисовать силуэт объектов, который потом будет наложен на основную картинку как тень. Расчёт не точный, но можно прикинуть, что 1 источник света - это 1/2 от FPS без источников света, 3 источника света - это 1/4 от FPS без источников и т.д. Во-первых, избавляйся от лишних источников света, которые не играют роли, во-вторых, выключай рендеринг теней для источников света, которым тени не нужны, в-третьих, выключай отбрасывание теней у мелких объектов и прочего мусора, которым тени не нужны. Можно попробовать создать один невидимый большой объект (куб), который бросает одну огромную тень вместо тысячи мелких предметов - так рендеринг теней будет меньше нагружать видеокарту.
Также производительность зависит от качества теней. Если хочешь гладкие и чёткие тени, текстуру нужно увеличить, но падает производительность. Если хочешь быстро, уменьшаешь размер текстуры, но получаешь размытые артефакты. Если тебе нужно тени на большом расстоянии от камеры, тогда тебе нужна текстура теней большего размера или будут артефакты. Если у тебя только мелкие комнаты, ты можешь сократить расстояние и получишь красивые тени со сравнительно высокой производительностью.
Также некоторые эффекты учитывают источники света, об этом подробно в документации по этим эффектам написано, поиграв настройками можно добиться приемлемого качества с не слишком сильной потерей производительности. Или вообще убрать эффект, если он тебе не нужен в конкретном месте.
И не забудь добавить в настройки игры опции для качества теней и других эффектов. Лично я во всех играх стараюсь отключить тени или снизить их качество на минимум, потому что они всё равно мешают геймплею, делая картинку тёмной и грязной, порой скрывая важные объекты. Кому нравится - у того и компьютер мощнее, пусть ставит тени на "ультра", будешь разбираться только если на 4090 у тебя меньше 60 фпс.
>почему в Godot источники света кастующие тени так сильно сажают FPS?
>Что можно предпринять, чтобы избежать просадок и получить нормальную картинку?
Источники света и тени по умолчанию динамически обновляются каждый кадр, чтобы учитывать актуальное состояние сцены. Читай документацию - там всё подробно описано, как переключить источники света в статический режим. В большинстве случаев динамические источники света тебе не нужны, если ты просто размещаешь лампочку и не двигаешь её.
Источник света относительно дешёвый, а вот тень - это отдельный рендеринг почти всей видимой игроку сцены с позиции источника света, чтобы нарисовать силуэт объектов, который потом будет наложен на основную картинку как тень. Расчёт не точный, но можно прикинуть, что 1 источник света - это 1/2 от FPS без источников света, 3 источника света - это 1/4 от FPS без источников и т.д. Во-первых, избавляйся от лишних источников света, которые не играют роли, во-вторых, выключай рендеринг теней для источников света, которым тени не нужны, в-третьих, выключай отбрасывание теней у мелких объектов и прочего мусора, которым тени не нужны. Можно попробовать создать один невидимый большой объект (куб), который бросает одну огромную тень вместо тысячи мелких предметов - так рендеринг теней будет меньше нагружать видеокарту.
Также производительность зависит от качества теней. Если хочешь гладкие и чёткие тени, текстуру нужно увеличить, но падает производительность. Если хочешь быстро, уменьшаешь размер текстуры, но получаешь размытые артефакты. Если тебе нужно тени на большом расстоянии от камеры, тогда тебе нужна текстура теней большего размера или будут артефакты. Если у тебя только мелкие комнаты, ты можешь сократить расстояние и получишь красивые тени со сравнительно высокой производительностью.
Также некоторые эффекты учитывают источники света, об этом подробно в документации по этим эффектам написано, поиграв настройками можно добиться приемлемого качества с не слишком сильной потерей производительности. Или вообще убрать эффект, если он тебе не нужен в конкретном месте.
И не забудь добавить в настройки игры опции для качества теней и других эффектов. Лично я во всех играх стараюсь отключить тени или снизить их качество на минимум, потому что они всё равно мешают геймплею, делая картинку тёмной и грязной, порой скрывая важные объекты. Кому нравится - у того и компьютер мощнее, пусть ставит тени на "ультра", будешь разбираться только если на 4090 у тебя меньше 60 фпс.
Чёт они замедлились.
Godot 4.3 уже полгода делают, а беты всё ещё нет.
Вроде обещали быстрее доставлять после релиза 4.0.
>В большинстве случаев динамические источники света тебе не нужны, если ты просто размещаешь лампочку и не двигаешь её.
А что если вокруг этой лампочки движется игрок? Я хочу чтобы моделька игрока освещалась. Пусть без отбрасываемых теней.
Плохо штоль? Хорошо. Ждём дальше.
Шейдер на ассемблере за пару вечеров пишется, а вы не можете на таком уровне абстракции это решить, ну и программисты пошли
Ай не пизди. Он Казима, он шейдеры иголкой на перфокартах выковыривает.
1280x720, 0:41
Запости свой проект на реддит, сразу в топ выйдешь.
https://www.reddit.com/r/godot/comments/1d40enz/
>А что если вокруг этой лампочки движется игрок?
Там какая-то сложная система запекания... Я особо не разбирался в этом пока.
>Я хочу чтобы моделька игрока освещалась. Пусть без отбрасываемых теней.
Тени (те, что падают от предмета на другие предметы) можно одной галочкой отключить без проблем. Запекание источников света имеет смысл, когда у тебя целая гирлянда разноцветных лампочек и нужно чтобы эти цветные пятна красиво отображались на окружающей гирлянду статичной геометрии. Или что-то в этом роде.
Ты лучше проверь, действительно ли проблема в источниках света или в чём-то другом.
>>3981
GLSL в машинный код видеокарты компилируется. Наверное, он прям этот машинный код и пишет под свою видеокарту, вручную, без GLSL. Зато игра не будет компилировать шейдеры. Оптимизации уровня ECS...
>>4009
Это так не работает, братишка.
Если бы мне были нужны спрайты для игры, я бы сразу спрайтщитами кочал с множества ресурсов, типа LPC-генератора. Вот например, беременная горгулья с лопатой (што?) сделано за 5 минут, пока пост писал. Полная раскадровка всех основных анимаций. И что мне твоя мазня по сравнению с генераторами? И сколько лет ты будешь мне раскадровку пилить? И сколько мозгов выебешь? А в генераторе перс уже готов.
А игры тонет всё равно.
А вот возьму и неиронично добавлю в свою игру. Показать что я делаю с этими картинками пока не могу, но знай, я ими воспользуюсь!
у нейронок такая же проблема как у скачать без смс. Того что надо никогда не будет. Поэтому только 3D -> анимации -> рендеринг 2D
Глянул - эта штука из шаблонов генерирует. Это даже не нейронка с промптом. Ты с этим далеко не уедешь без хуйдожника...
Если хочешь серьёзно научиться пиксель-арту, читай это:
http://archive.org/details/pixel-logic-a-guide-to-pixel-art-michael-azzi/
От себя (я сам плох в этом, но всё же) рекомендую:
1. Ограничиваться только базовыми цветами, без оттенков и полутонов. Берёшь несколько контрастных цветов, которые легко отличить друг от друга, и рисуешь только ими. Сейчас у тебя всё сливается в пятна из-за недостаточной разницы между цветами.
2. Персонажей лучше всего делать с обводкой - чёрной или очень тёмной. Без обводки мелкопиксельный персонаж плохо читается даже как отдельный статичный спрайт, а в игре он легко может слиться с фоном, даже если ты подбирал цвета под конкретный тайлсет фона. Тайлсеты фона, наоборот, чаще без обводки, чтобы не бросаться в глаза, но обводка может подсвечивать интерактивные предметы, твёрдые поверхности и т.п.
3. Если делаешь спрайт для игры, то необходимо знать, в каком стиле будет игра: размер пикселей (никто не будет делать сегодня пиксельную игру 1:1, всегда пиксели умножают на какое-то число, и это число должно быть одним на всю игру), палитра (даже если нет одной палитры на всю игру, всё равно есть разница между кислотными, мрачными, серыми, пастельными и другими группами оттенков, это задаёт атмосферу игры), положение камеры (сверху, сбоку, 3/4), что персонажа чаще всего окружает (буйная тропическая зелень, городская серость, постапокалиптическая ржавчина и т.д.) и т.д.
4. Лучше тренироваться не на спрайтах, а на иллюстрациях. Чтобы не задумываться пока об анимации, спрайт-шитах и т.д. Набить руку на отдельных рисунках.
5. Знания и опыт в академическом художестве помогут в пиксель-арте, особенно если хочешь подняться над унылыми тяп-ляп 2D платформерами от школьников.
6. Изучи специальные инструменты. Да, рисовать пиксель-арт можно и в пейнте, но специальные редакторы сегодня имеют массу вспомогательных инструментов.
>>4020
>LPC-генератор
Ты бы хоть ссылку дал на этот генератор, лол.
http://sanderfrenken.github.io/Universal-LPC-Spritesheet-Character-Generator/
>А в генераторе перс уже готов.
Ага, и он точно в таком же стиле, как и 99% игр на РПГ Мейкере, которые совершенно не отличаются друг от друга из-за одинаковых бесплатных тайлсетов и генераторов персонажей. Смешно смотреть на очередную инди-жРПГ в стиме, у которой скриншоты ничем не выделяются кроме аниме героини, которая тоже в стиле стандартного инди аниме и не выделяется на фоне остальных аниме героинь.
>>4028
>Того что надо никогда не будет.
Придёт AGI - порядок наведёт. Будет делать игру с нуля до релиза за час на кофеварке.
>Поэтому только 3D -> анимации -> рендеринг 2D
Такие игры легко отличить от труЪЪЪ ручного пиксель-арта. ИМХО, лучше уж делать стилизованную 3D игру, чем пытаться попасть в и без того переполненную нишу пиксель-арта со своими кривыми 3D рендерами.
>>4033
>Ты с этим далеко не уедешь без хуйдожника
99% игр на РПГ Мейкере как-то справляются.
Если хочешь серьёзно научиться пиксель-арту, читай это:
http://archive.org/details/pixel-logic-a-guide-to-pixel-art-michael-azzi/
От себя (я сам плох в этом, но всё же) рекомендую:
1. Ограничиваться только базовыми цветами, без оттенков и полутонов. Берёшь несколько контрастных цветов, которые легко отличить друг от друга, и рисуешь только ими. Сейчас у тебя всё сливается в пятна из-за недостаточной разницы между цветами.
2. Персонажей лучше всего делать с обводкой - чёрной или очень тёмной. Без обводки мелкопиксельный персонаж плохо читается даже как отдельный статичный спрайт, а в игре он легко может слиться с фоном, даже если ты подбирал цвета под конкретный тайлсет фона. Тайлсеты фона, наоборот, чаще без обводки, чтобы не бросаться в глаза, но обводка может подсвечивать интерактивные предметы, твёрдые поверхности и т.п.
3. Если делаешь спрайт для игры, то необходимо знать, в каком стиле будет игра: размер пикселей (никто не будет делать сегодня пиксельную игру 1:1, всегда пиксели умножают на какое-то число, и это число должно быть одним на всю игру), палитра (даже если нет одной палитры на всю игру, всё равно есть разница между кислотными, мрачными, серыми, пастельными и другими группами оттенков, это задаёт атмосферу игры), положение камеры (сверху, сбоку, 3/4), что персонажа чаще всего окружает (буйная тропическая зелень, городская серость, постапокалиптическая ржавчина и т.д.) и т.д.
4. Лучше тренироваться не на спрайтах, а на иллюстрациях. Чтобы не задумываться пока об анимации, спрайт-шитах и т.д. Набить руку на отдельных рисунках.
5. Знания и опыт в академическом художестве помогут в пиксель-арте, особенно если хочешь подняться над унылыми тяп-ляп 2D платформерами от школьников.
6. Изучи специальные инструменты. Да, рисовать пиксель-арт можно и в пейнте, но специальные редакторы сегодня имеют массу вспомогательных инструментов.
>>4020
>LPC-генератор
Ты бы хоть ссылку дал на этот генератор, лол.
http://sanderfrenken.github.io/Universal-LPC-Spritesheet-Character-Generator/
>А в генераторе перс уже готов.
Ага, и он точно в таком же стиле, как и 99% игр на РПГ Мейкере, которые совершенно не отличаются друг от друга из-за одинаковых бесплатных тайлсетов и генераторов персонажей. Смешно смотреть на очередную инди-жРПГ в стиме, у которой скриншоты ничем не выделяются кроме аниме героини, которая тоже в стиле стандартного инди аниме и не выделяется на фоне остальных аниме героинь.
>>4028
>Того что надо никогда не будет.
Придёт AGI - порядок наведёт. Будет делать игру с нуля до релиза за час на кофеварке.
>Поэтому только 3D -> анимации -> рендеринг 2D
Такие игры легко отличить от труЪЪЪ ручного пиксель-арта. ИМХО, лучше уж делать стилизованную 3D игру, чем пытаться попасть в и без того переполненную нишу пиксель-арта со своими кривыми 3D рендерами.
>>4033
>Ты с этим далеко не уедешь без хуйдожника
99% игр на РПГ Мейкере как-то справляются.
Как закончу хотя бы квартиру.
Я как-то выкладывал на реддит видео другой демки
https://youtu.be/wpZODOlzOCg
Это реворк демки одного нсфв художника. Реакция на реддит была в целом положительная, но пользы от этого было никакой. Даже художник не мотивировался вернуться к геймдеву, а жаль.
Базовый стол. У меня такой есть. Охуенно!
>видео другой демки
О, а я помню это видео, давно видел.
Думал, ты новенький, а ты уже смешарик.
>выкладывал на реддит
>пользы от этого было никакой
>художник не мотивировался вернуться
Куда конкретно ты это выкладывал, r/godot?
Нужно выкладывать прямо к твоей ЦА:
https://old.reddit.com/r/vore/
https://old.reddit.com/r/giantess/
https://old.reddit.com/r/succubus/
Ну и там поищи что-то в этом духе.
>vore/giantess/
Выкладывал в r/godot, но я потом акк удалил.
Вообще, поглащение и гиганты не мои фетиши, прст технически исполнил.
>>4080
>а ты уже смешарик
Первую демку делал на версии 3.4, потом ничем не занимался аж до конца прошлого года. Там другую демку сделал по поням (тоже реворк чужой работы). Эта вот с квартирой - третья, первая полностью своя... на чужих ассетах, плагат популярной франшизы.
Не густо.
Советы хороши.
А я нирикаменую пиксель арт как таковой. Это обман, наебка, ловушка. Он кажется обманчиво простым, но если делаешь что-то выше 12х12, то оно тебя сожрет. А потом сожрет второй раз, когда начнешь ебаться с пиксель-перфект в движке, с y-сортами и прочим геморроем. А уж анимировать его, ууу бля, сидишь как даун половину спрайта перерисовываешь, а потом понимаешь что он уехал не туда и слышь давай по-новой. Я уж лучше на primitive shapes and colors игры поделаю.
У lpc лицензия кривоватая
960x840, 0:22708 Кб, mp4,
1152x768, 0:13998 Кб, mp4,
720x720, 0:30825 Кб, mp4,
960x960, 0:29
>если делаешь что-то выше 12х12
Чем выше разрешение, тем ближе к обычному арту, а тут уже решает то, насколько ты хорош в обычном арте и его теоретической базе. Если знать теорию - у тебя будет меньше вопросов "что делать" и рисунки станут привлекательнее. Дальше всё сводится к механическому дрочу пикселей, в этом инструменты помогают. Теория - технические знания, бояться их не надо, но большинство новичков ленится читать и разбираться, потому и разочаровываются в себе - это как если бы начинающие программисты садились писать Hello World без чтения мануала по незнакомому им языку и потом плакали, что код - это не для них и больше они к нему не притронутся.
>анимировать его, ууу бля, сидишь как даун половину спрайта перерисовываешь, а потом понимаешь что он уехал не туда
У тебя неправильный порядок работы. Ты сначала полностью детализировал один спрайт, а потом пытаешься кадр за кадром анимировать его, верно? На практике лучше наоборот: сначала сделать всю анимацию цветными кляксами, не заботясь о пикселях, и только когда анимация будет удовлетворять, наращивать на неё все необходимые детали вроде одежды, волос, лица, предметов, и т.д. Сначала делаешь свою супер-пупер анимацию удара ногой с разворота с подробной физикой прыгающих сисек, а потом уже натягиваешь на неё свою бимбу в микрокини. Тогда у тебя не будет "ой, чёт криво прыгают". Пикрилы в своё время открыли мне глаза на анимацию.
Масло = дорого (особенно в пендостане, где нет ни молока, ни хуя)
Т.е. он кичится своим богатством, которое приобрел за счет своих инди-игор. Получается, это такая ирония, мол, он говорит - ха-ха, мне так трудно быть гейдевом, что приходится жрать черную икру ложками (если адаптировать эту историю для граждан Российской Федерации).
> ни молока
Разве? Там же сильно с середины прошлого века производители молока продавливали молоко в массы
Вообще не до этого бро. Сплошные игры живого действия, времени остается только на самописный sdl микродвиг.
>instance_set_transform: Condition "!v.is_finite()" is true
Ты забыл указать строчку кода в исходниках (она всегда указывается дебаггером при таких ошибках), так что придётся играть в форумного экстрасенса.
Эта ошибка генерируется, например, здесь:
https://github.com/godotengine/godot/blob/705b7a0b0bd535c95e4e8fb439f3d84b3fb4f427/servers/rendering/renderer_scene_cull.cpp#L935
Суть проблемы: один из компонентов матрицы NaN или бесконечность, поэтому матрицу не удаётся применить.
Нужно смотреть, какие значения у тебя в матрице мешей, которые закреплены за телом, которое ты пытаешься двигать. Если используешь MultiMeshInstance3D, то нужно смотреть, какие данные находятся в его буфере - там иногда могут быть ошибки, которые, похоже, пока не удалось исправить:
https://github.com/godotengine/godot/issues/75485
>Как вообще пофиксить подобное
Удалить меши и пересоздать их заново. Особенно если у тебя MultiMeshInstance3D.
>вероятность того, что эта ошибка вылезает где-то кроме move_and_slide() стремится к нулю
С чего такая уверенность? Этот метод двигает физическое тело. Если подозреваешь, что проблема именно в нём, а не в графике, тогда удали все MeshInstance3D и оставь только CharacterBody3D с его CollisionShape3D. Включи отображение коллизий, чтобы видеть персонажа на экране без мешей, и тестируй.
Не нравится мне его подход к чарактер контроллеру.
Лучше абстрагировать инпут игрока от персонажа.
Пикрил (не нашёл более подходящую картинку).
>Ты забыл указать строчку кода в исходниках
E 0:00:38:0649 instance_set_transform: Condition "!v.is_finite()" is true.
<Исходный код C++>servers/rendering/renderer_scene_cull.cpp:922 @ instance_set_transform()
>С чего такая уверенность?
>Суть проблемы: один из компонентов матрицы NaN или бесконечность, поэтому матрицу не удаётся применить.
Ну мб я преувеличил. Я, по сути, почти совсем нюфаня. Я как раз делал везде где только можно проверки скоростей и величин, чтобы они были не нан и не бесконечность, и только после этого применял move_and_slide().
>а не в графике
Я вообще не в курсе, что это тоже влияет
>удали все MeshInstance3D и оставь только CharacterBody3D с его CollisionShape3D
Сделал. Та же хуйня.
>Нужно смотреть, какие значения у тебя в матрице мешей, которые закреплены за телом, которое ты пытаешься двигать.
Подскажи, плс, как это сделать, и как это поможет
>Аж трисет.
Не завидуй. У него 6.9К лайков, а у тебя сколько?
https://reddit.com/r/PixelArt/comments/17xgycv/
>Тупо обрисовка
По его словам в комментариях, рисовал без этого:
https://en.wikipedia.org/wiki/Rotoscoping
Но даже если этой техникой, то какая разница?
Главное, чтобы результат был хороший.
Дрочь на техники == дрочь на движкописание.
Делайте игры на ассемблере, а то не труъ.
><Исходный код C++>servers/rendering/renderer_scene_cull.cpp:922 @ instance_set_transform()
Да, это та самая строчка.
>>значения в матрице
>как это сделать
Либо через инспектор в сцене Remote в запущенном проекте, либо print(transform).
Попробуй сделать новую сцену со своим скриптом, чтобы там было минимум компонентов.
Попробуй вырезать или закомментировать весь лишний код, который тебе не обязателен.
В худшем случае просто сносишь вообще всё и начинаешь делать с нуля, но осознанно.
Алсо, мог бы хотя бы скриншот своего кода показать, скриншот дерева сцены и т.д.
Ты случайно не трогал масштаб CharacterBody? Сбрось его в исходное состояние.
[X: (-0.767623, 0, -0.640902), Y: (0, 1, 0), Z: (0.640902, 0, -0.767623), O: (-7.212014, -0.294964, 1.819657)]
[X: (-0.767623, 0, -0.640902), Y: (0, 1, 0), Z: (0.640902, 0, -0.767623), O: (-7.25317, -0.294962, 1.784231)]
[X: (-0.763492, 0, -0.645818), Y: (0, 1, 0), Z: (0.645818, 0, -0.763492), O: (-7.25317, -0.294962, 1.784231)]
[X: (-0.763492, 0, -0.645818), Y: (0, 1, 0), Z: (0.645818, 0, -0.763492), O: (-7.293885, -0.294962, 1.749318)]
[X: (-0.760393, 0, -0.649464), Y: (0, 1, 0), Z: (0.649464, 0, -0.760393), O: (-7.293885, -0.294962, 1.749318)]
[X: (-0.760393, 0, -0.649464), Y: (0, 1, 0), Z: (0.649464, 0, -0.760393), O: (-7.334162, -0.294962, 1.714919)]
Я хз, как это поможет.
>Ты случайно не трогал масштаб CharacterBody? Сбрось его в исходное состояние.
Скейл, вроде, весь по 1
>Алсо, мог бы хотя бы скриншот своего кода показать, скриншот дерева сцены и т.д.
Да я даже проект позже могу приложить, вот только надо разобраться с баном от двоща, лол (не ебу, какого хуя прилетел)
Древо сцены - см. пик
Код кидать смысла нет - там ща лютый говнокод, который надо разгребать. Я как раз находился в процессе, когда обнаружил баг.
Вообще, ситуация осложняется тем, что изначально код не мой. Основу кода и древо сцены делал другой чел, и он там где-то, в теории, мог накосячить - он еще больший ньюфаг, чем я
У вас часто такое бывает, что редактируешь-редактируешь один скрипт (у него @tool и class_name), а когда пытаешься использовать его из другого скрипта, редактор почему-то не знает актуальное состояние скрипта и ругается на отсутствующие ошибки? Ничего не помогает, приходится перезагружать проект.
Пример: я объявил метод close() -> void, использовал его в другом скрипте, всё было нормально, а потом я решил, что мне нужно, чтоб этот метод возвращал какой-то результат. Я изменил скрипт, а потом попытался использовать возвращаемый результат - редактор ругается, что метод ничего не возвращает.
Нажимать "soft reload tool script" пробовал, не помогает. Также пробовал убирать метку @tool, это не влияет. Похожая проблема наблюдается при частом редактировании нескольких class_name скриптов (без @tool), редактор почему-то не может их вовремя обновить и выдаёт ошибки.
Проблема мелкая, но перезагружать весь редактор раздражает.
Что тебе CollisionShape3D говорит? Жёлтый значок - предупреждение о каком-то косяке, как правило - твоём, кликни и прочитай. Если там сообщение с пикрила - сбрось ему масштаб. Встроенный физический движок непредсказуемо косячит с масштабированием.
>изначально код не мой
>Основу кода и древо сцены делал еще больший ньюфаг, чем я
Не рекомендую так делать, если ты пытаешься нахватать чужого кода и заставить его работать, толком не разбираясь в основах движка и скриптинга на нём. Лучше самостоятельно научиться с нуля, чтобы потом видеть ошибки в чужом коде/сценах, чем разбираться без опыта в чужом коде и научиться чужим ошибкам. Впрочем, во всяких туториалах и даже платных курсах часто учат говнокоду...
Алсо, рекомендую привыкать разделять сцену на отдельные самостоятельные сущности, которые сохраняются в отдельные tscn-файлы и затем используются в композиции других сцен:
- Player - главный кандидат на такое выделение, он же должен забрать к себе Camera3D (исключение, если это камера локации, фиксированная на месте и следящая за игроком как ИРЛ камера).
- Часто используемые звуки лучше сгруппировать в одну сцену, типа "плеер звуков", исключение - если это локальные звуки вроде открывания ящика (они принадлежат сцене ящика).
- Препятствия разложить по отдельным сценам, особенно если они часто повторяются, вроде конусов на дороге, барьеров и т.д. Иначе задолбаешься расставлять/двигать их по сцене.
Тогда для тестирования Player было бы достаточно закинуть его на пустую площадку, уже с камерой и всем необходимым для его работы.
>0xc0000005
По-человечески это называется STATUS_ACCESS_VIOLATION.
>что я могу сделать?
1. Проверить, где ты в своём коде обращаешься туда, куда обращаться тебе запрещает ОС: скорее всего, ожидаемый тобой по ссылке объект был уже уничтожен, а ты пытаешься к нему обратиться - ОС запрещает это, чтобы программы не могли залезть в чужую память, и поэтому крашит без разбора всех, кто так делает.
2. Перейти на GDScript, на нём такого нет (дебаггер сразу указывает туда, где ты обратился куда не следует, вместо краша с ошибкой ОС, и чётко говорит, в чём проблема).
>не узнаю, это ошибка ещё не выскочила, или действительно проблемный фрагмент закомментировал
Чтоб такого не было, применяют TDD:
https://en.wikipedia.org/wiki/Test-driven_development
Всё дело в том, что ошибка вылезает не в моей логике, а будто после того как один Process закончился, а следующий ещё не начался.
> ошибка вылезает не в моей логике
Если ты обнаружил баг движка, то можешь сделать новый проект, по шагам воспроизвести баг, убедиться, что ты обнаружил баг движка, и зарепортить на гитхаб ищью.
Не бывает "как правильно", бывает - как удобно тебе.
>ошибка вылезает не в моей логике
Если ты в этом так уверен, то иди на гитхаб и создавай issue. Желательно к описанию проблемы приложить минимальный проект, в котором гарантированно воспроизводится эта проблема. Там почитаешь, что нужно для правильного оформления (версия движка, версия ОС, что делал и т.д.).
Но я всё же думаю что проблема в твоём коде - что-то где-то некстати удаляешь.
Сам движок тут ничем не поможет, твой код (или ошибка в движке) приводит его в состояние, в котором ОС принудительно завершает процесс. Можно отследить, на каком конкретно этапе происходит остановка, если использовать внешний дебаггер, но он, наверное, будет выдавать кучу ассемблерных кодов, и ты в этом, скорее всего, ничего не разберёшь.
А, вот ещё. Если делаешь регулярные бекапы или заливаешь код в систему контроля версий, тогда попробуй открыть предыдущий бекап и проверь, есть ли там эта ошибка. Потом сравни, что ты успел налепить в коде до появления ошибки. Так сузишь область поиска проблемы. Мне пару раз помогало, когда я наговнокодил кучу всего и сам в этом запутался.
На будущее рекомендую тестировать проект после минимальных изменений. Чем меньше изменений между тестами, тем меньше мест, в которых придётся искать ошибку - чаще всего ошибка возникает из-за свежего кода.
Я считаю более выгодным создавать абстрактного персонажа, который никем конкретным не управляется, но имеет состояния и переходы между ними, может ходить, бегать, прыгать и т.д. Создав такого персонажа, ты сможешь не только с клавиатуры его контролировать, но и через код, т.е. создать бота, который игромеханически будет равен игроку - в плане того, что он точно так же бегает, прыгает и делает все остальные действия.
Соответственно, тебе нужен скрипт, реагирующий на внешние команды, и отдельный скрипт, генерирующий эти команды от ввода с клавиатуры или от мозгов неигрового персонажа. Двух зайцев одним выстрелом, да? В туториалах об этом не говорят и чарактер контроллеры, которые я видел, прибиты гвоздями к вводу с клавиатуры...
>косяк вылезает в месте, которое я не могу отследить
Ещё раз, разбираемся:
1. Изначально твой проект был без ошибки (как минимум пустой).
2. Ты добавил код - он работал всё ещё без ошибки.
3. Ты добавил больше кода - начала выпадать ошибка.
4. Убрал добавленный код - ошибка перестала выпадать.
5. Изучаешь, что ты делаешь в коде, и понимаешь, откуда ошибка.
Я в таких случаях стараюсь исполнить код в голове или в Блокноте.
Ещё попробуй сбросить весь кэш проекта (.godot), вдруг это Godot что-то сам себе сломал.
Понимаешь, проблема в том, что это
> 3. Ты добавил больше кода - начала выпадать ошибка.
Это смена библиотеки ECS, я знаю, что если я откачусь на версию до смены, то там этой ошибки не будет. У меня слишком много кода, чтобы выполнять его в голове и анализировать классическими методами.
>>4327
Попробую, но надежды мало
>Это смена библиотеки ECS, я знаю, что если я откачусь на версию до смены, то там этой ошибки не будет.
Даже и не знаю, чем тебе помочь, если ты не можешь отказаться от багованной библиотеки, про которую ты уже знаешь, что она багованная. Попробуй написать разработчикам этой библиотеки.
>У меня слишком много кода, чтобы выполнять его в голове и анализировать классическими методами.
Что значит "слишком много кода"? Ты огромную портянку лапши накидал что ли, что у тебя оперативной памяти мозга не хватает? Единственно верный подход к разработке софта - это разделять код на мелкие самостоятельные части, тестировать их по отдельности, затем тестировать композицию из уже протестированных частей и т.д. Берёшь маленький кусок кода, изучаешь его - что он делает, с чем работает, на что влияет, что возвращает. Если с ним всё в порядке, закрываешь его и больше не трогаешь. В чём проблема? Естественно, код нужно изначально писать в таком виде, но никогда не поздно произвести рефакторинг.
Вот чего я не пойму, ты ведь новичок? Судя по тому, что ты не знал про ошибку доступа, вряд ли у тебя богатый опыт программирования. Но ты взял C# (объективно сложнее GDScript, хуже поддержка движком, меньше туториалов и годотеров, способных помочь в контексте движка), в добавок взял ECS (объективно сложнее отлаживать, чем классическое ООП, а его главное преимущество играет роль только на очень большом количестве одинаковых компонентов - десятки тысяч), навалил кучу какого-то кода, который сам не можешь проанализировать (нейронкой генерировал?), а теперь бодаешься с ошибкой, которую не можешь понять. Зачем ставить себе столько палок в колёса? Ты игру хочешь сделать или что? Или у тебя какое-то задание, которое ты взял, не подумав о последствиях? Если ты сам для себя это делаешь, проще бросить проект и начать с нуля, чем распутывать клубок неудачного кода, в котором ты сам не разбираешься. Всё равно большинство инди-проектов так и остаются недоделанными - это факт.
Извини, если что, не хочу обидеть.
>Это смена библиотеки ECS, я знаю, что если я откачусь на версию до смены, то там этой ошибки не будет.
Даже и не знаю, чем тебе помочь, если ты не можешь отказаться от багованной библиотеки, про которую ты уже знаешь, что она багованная. Попробуй написать разработчикам этой библиотеки.
>У меня слишком много кода, чтобы выполнять его в голове и анализировать классическими методами.
Что значит "слишком много кода"? Ты огромную портянку лапши накидал что ли, что у тебя оперативной памяти мозга не хватает? Единственно верный подход к разработке софта - это разделять код на мелкие самостоятельные части, тестировать их по отдельности, затем тестировать композицию из уже протестированных частей и т.д. Берёшь маленький кусок кода, изучаешь его - что он делает, с чем работает, на что влияет, что возвращает. Если с ним всё в порядке, закрываешь его и больше не трогаешь. В чём проблема? Естественно, код нужно изначально писать в таком виде, но никогда не поздно произвести рефакторинг.
Вот чего я не пойму, ты ведь новичок? Судя по тому, что ты не знал про ошибку доступа, вряд ли у тебя богатый опыт программирования. Но ты взял C# (объективно сложнее GDScript, хуже поддержка движком, меньше туториалов и годотеров, способных помочь в контексте движка), в добавок взял ECS (объективно сложнее отлаживать, чем классическое ООП, а его главное преимущество играет роль только на очень большом количестве одинаковых компонентов - десятки тысяч), навалил кучу какого-то кода, который сам не можешь проанализировать (нейронкой генерировал?), а теперь бодаешься с ошибкой, которую не можешь понять. Зачем ставить себе столько палок в колёса? Ты игру хочешь сделать или что? Или у тебя какое-то задание, которое ты взял, не подумав о последствиях? Если ты сам для себя это делаешь, проще бросить проект и начать с нуля, чем распутывать клубок неудачного кода, в котором ты сам не разбираешься. Всё равно большинство инди-проектов так и остаются недоделанными - это факт.
Извини, если что, не хочу обидеть.
> Попробуй написать разработчикам этой библиотеки.
Я перешёл на более популярную библиотеку. Думаю она стабильнее.
> Вот чего я не пойму, ты ведь новичок?
> Судя по тому, что ты не знал про ошибку доступа,
> вряд ли у тебя богатый опыт программирования
> который сам не можешь проанализировать (нейронкой генерировал?)
> которую не можешь понять.
> Извини, если что, не хочу обидеть.
Не буду тратить время на расписывание, что я не дурак. Складывается впечатление что ты хочешь самоутвердиться за мой счёт. Вместо того, чтобы просто сказать "Анон, я не знаю метода как отловить ошибку доступа" ты начал предлагать мне сменить язык, принцип разработки и начал учить что такое ошибка доступа.
В планах пока что только отдохнуть ибо хуярил чтоб не спиздеть часов 20 подряд. А потом напиздить ассетов гуи.
Такие вот дела.
А ты чем щас занять анон?
>Думаю она стабильнее.
Но у тебя ошибка доступа, которую ты не можешь отловить. После смены библиотеки на "стабильную". В проекте, где у тебя уже куча кода, в котором ты не можешь просто так взять и разобраться. Сам себе приключение устроил.
>что я не дурак
Я не говорю, что ты дурак, но, судя по постам, ты допускаешь ошибки новичка, и я заранее предупреждаю об этом.
>Анон, я не знаю метода как отловить ошибку доступа
Я знаю, как её отловить, и уже писал - берёшь отладчик и смотришь, на какой инструкции процессора Godot крашится. Только это вряд ли чем-то может помочь, если ты не разбираешься в низкоуровневой отладке. Если у тебя стоит подходящий отладчик, Windows сама должна предложить открыть процесс в отладчике.
>начал предлагать мне сменить язык, принцип разработки
Потому что в GDScript реально легче работать. Если ты на C# с ECS только ради производительности, то это преждевременная оптимизация. Тем более что API Godot само по себе медленное, так что у тебя получается бутылочное горлышко между Godot и твоей библиотекой. Там много нюансов. На GDScript можно быстро сделать игру, а потом уже думать, что и зачем переносить на более производительный язык или в ECS. Да, сделать в первый раз всегда сложнее и дольше, чем перенести готовое куда-либо. Да и в целом, GDScript более чем достаточно для большинства задач, а код пишется легко и гибко. К табам и отступам привыкаешь очень быстро.
У тебя Microsoft Visual Studio Debugger есть? По идее, он должен помочь с поиском проблемного места.
Вон, создатели твоего любимого C# целую статью про отладку для чайников накатали:
https://learn.microsoft.com/en-us/visualstudio/debugger/debugging-absolute-beginners
>беты всё ещё нет
ВЫШЛА ВЫШЛА ВЫШЛА
https://godotengine.org/article/dev-snapshot-godot-4-3-beta-1/
Ещё немного подождать и сможем начать делать игры!
>Какой-то подлец залил мне диверсию
Это самоирония? Или проект на гитхабе? Или код - копипаста?
>спешишь делать что интересно
Что интересного в InputEvent.Unreference()?
Насколько я понимаю, InputEvent нельзя уничтожать, потому что он последовательно проходит по всему дереву. Т.е. уничтожив этот объект в одном месте ты вызываешь ошибку доступа где-то дальше по дереву, где его кто-то ждёт. Хотя как это к C# относится - не знаю, разве в C# принято удалять объекты вручную? Кажется, там GC автоматически всё удаляет.
Ну, главное, ты разобрался - рад за тебя.
https://docs.godotengine.org/en/stable/classes/class_refcounted.html#class-refcounted-method-unreference
>bool unreference ( )
>Decrements the internal reference counter. Use this only if you really know what you are doing.
>Returns true if the object should be freed after the decrement, false otherwise.
Т.е. получается, что ты уменьшил счётчик ссылок, и это вызвало преждевременное удаление объекта. По-прежнему непонятно, зачем это нужно было делать в данном конкретном случае. Возможно, эту функцию нужно использовать для разрешения циклических зависимостей, когда A и B ссылаются друг на друга и поэтому не могут быть освобождены штатным путём (читал что-то об этом в документации).
> самоирония
Это
> Что интересного в InputEvent.Unreference()
> Decrements the internal reference counter. Use this only if you really know what you are doing.
Оказалось я не знал что тогда делал. Думаю что я тогда хотел сделать так, чтобы если в одном инпуте обработал ивент, то больше его никто не мог использовать
> рад за тебя
Спасибо
>если в одном инпуте обработал ивент, то больше его никто не мог использовать
Для этого тебе нужно это, если ещё сам не нашёл:
https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-private-method-unhandled-input
https://docs.godotengine.org/en/stable/classes/class_viewport.html#class-viewport-method-set-input-as-handled
Ну зато теперь ты чуть больше знаешь о том, что ты делаешь.
>ECS
>главное преимущество играет роль только на очень большом количестве одинаковых компонентов - десятки тысяч
Я от про слышал, что ECS в гейдеве - это единственно правильное и оптимальное решение.
Изи в рефакторинге, изи в масштабировании и реюзабельности. Да и много логичней остальных подходов.
Я только мечтаю вкатиться в геймдев и многого не знаю еще. Но просто пока искал информацию о разных подходах, то нашел, что TCS - самый топ номер 1.
Не, это инфоцыгане были. Реальные про как раз сказали, что это оказалось ошибкой.
>нашел, что ECS - самый топ номер 1
Некоторые шизы будут тебе и про функциональные языки точно так же говорить, мол, иммутабельность - топ номер 1, всё должно состоять из функций, игра - это тоже одна иммутабельная функция, типа вызываешь game() и получаешь игру, если захотел нажать кнопку - выбросил старую игру и вычислил новую игру с нажатой кнопкой, и т.д. Это прекрасно работает в идеальном мире, но мы живём в реальности, а не в фантазии функциональщиков. Ты можешь, конечно, использовать .all(), .any(), .filter(), .map() и прочие полезные функции, популярные в функциональщине, но всю игру на одном этом не построишь.
>Изи в рефакторинге, изи в масштабировании и реюзабельности
При условии, что ты мыслишь в стиле ECS.
Допустим, ты хочешь, чтобы твой персонаж прыгал. Ты создаёшь систему "прыганье" и компонент "прыгатель". Добавляешь этот компонент к любой сущности, которая должна уметь прыгать. Эта система получит список всех сущностей с этим компонентом и будет их "прыгать" по мере необходимости.
В чём преимущество? Допустим, у тебя 100 тысяч прыгателей. Если ты пользуешься классическим ООП, в теории процессор будет метаться по разным участкам памяти, по отдельности прыгая каждого прыгателя, и так 100 тысяч раз. Если ты обмазал код ECS, тогда в теории процессор загрузит в свой кэш все компоненты "прыгатель" одним массивом и быстро пройдётся по этому массиву кодом из "прыганья", не обращаясь к чипам оперативной памяти, потому что все данные у него уже есть в кэше (обращение к RAM - долго, именно поэтому придумали кэш и с каждым годом его увеличивают в процессорах).
На практике хрен знает что будет, процессор не только с твоей игрой работает (игра - только гость в ОС, которая всем управляет), и вообще там все эти оптимизации сложнее, чем в фантазии геймдевелоперов. Часть оптимизаций оказались уязвимы к вирусам... Но наверняка придумают что-то ещё. Короче, не всё так однозначно в процессорах.
Зато тебе, как разработчику игры, приходится разделять код на тысячи якобы (по заявлениям любителей ECS) ничем не связанных сущностей ("прыгатель", "ходитель", "предметособиратель", "стрелятель", "умиратель", "подлечатель", "подмыватель", "пенетратель", "оратель" и прочее), которые в реальности очень тесно друг с другом связаны и ты не можешь думать о них по отдельности - ты думаешь об игроке, который бегает, прыгает, стреляет, умирает и орёт, а не о кучке полностью независимых систем и компонентов. Мышление человека - основа ООП, а не наоборот, человеку намного проще думать о цельных объектах, чем о кучке ничем не связанных компонентов и систем. А комбинировать компоненты можно и на ООП, никто тебя не заставляет пользоваться наследованием (на которое обычно ругаются, аргументируя в пользу ECS) - пользуйся преимущественно композицией и агрегацией, получишь точно такую же гибкость архитектуры проекта, что и в ECS, но зато объекты будут как в твоих мыслях.
Короче, ИМХО, ООП намного лучше подходит геймдеву, и страдает только в случае если тебе нужно сто тыщ юнитов с одним и тем же кодом, что бывает крайне редко и не факт что вообще получится. Древние стратегии в реальном времени создавали и без модного ECS на медленных процессорах с крайне ограниченным кэшем. Godot, между прочим, имеет под капотом множество оптимизаций по кэшу процессора в системах, где это действительно необходимо (эти системы тут называются "серверы"). Если тебе нужно оптимизировать сто тыщ сущностей по кэшу - ты берёшь и пишешь собственный модуль движка на C++, выставляешь API и дёргаешь по необходимости из GDScript. Да и вообще, Godot не то чтобы самый эффективный, пытаться максимально оптимизировать проект на нём - это как ставить двигатель от реактивного истребителя на Запорожец - технически возможно, но результат вряд ли обрадует. Обещают сфокусироваться на оптимизациях движка, начиная с версии 4.4, тогда как версия 4.3 только вышла в бету. Однако, для освоения базы геймдева Godot сегодня подходит лучше всех, ты просто качаешь движок, создаёшь проект и начинаешь играть в разработчика игр в своё удовольствие, развлечение гарантировано на сотни часов. Можно забыть обо всяких Скретчах, Гейм Мейкерах и т.д.
>нашел, что ECS - самый топ номер 1
Некоторые шизы будут тебе и про функциональные языки точно так же говорить, мол, иммутабельность - топ номер 1, всё должно состоять из функций, игра - это тоже одна иммутабельная функция, типа вызываешь game() и получаешь игру, если захотел нажать кнопку - выбросил старую игру и вычислил новую игру с нажатой кнопкой, и т.д. Это прекрасно работает в идеальном мире, но мы живём в реальности, а не в фантазии функциональщиков. Ты можешь, конечно, использовать .all(), .any(), .filter(), .map() и прочие полезные функции, популярные в функциональщине, но всю игру на одном этом не построишь.
>Изи в рефакторинге, изи в масштабировании и реюзабельности
При условии, что ты мыслишь в стиле ECS.
Допустим, ты хочешь, чтобы твой персонаж прыгал. Ты создаёшь систему "прыганье" и компонент "прыгатель". Добавляешь этот компонент к любой сущности, которая должна уметь прыгать. Эта система получит список всех сущностей с этим компонентом и будет их "прыгать" по мере необходимости.
В чём преимущество? Допустим, у тебя 100 тысяч прыгателей. Если ты пользуешься классическим ООП, в теории процессор будет метаться по разным участкам памяти, по отдельности прыгая каждого прыгателя, и так 100 тысяч раз. Если ты обмазал код ECS, тогда в теории процессор загрузит в свой кэш все компоненты "прыгатель" одним массивом и быстро пройдётся по этому массиву кодом из "прыганья", не обращаясь к чипам оперативной памяти, потому что все данные у него уже есть в кэше (обращение к RAM - долго, именно поэтому придумали кэш и с каждым годом его увеличивают в процессорах).
На практике хрен знает что будет, процессор не только с твоей игрой работает (игра - только гость в ОС, которая всем управляет), и вообще там все эти оптимизации сложнее, чем в фантазии геймдевелоперов. Часть оптимизаций оказались уязвимы к вирусам... Но наверняка придумают что-то ещё. Короче, не всё так однозначно в процессорах.
Зато тебе, как разработчику игры, приходится разделять код на тысячи якобы (по заявлениям любителей ECS) ничем не связанных сущностей ("прыгатель", "ходитель", "предметособиратель", "стрелятель", "умиратель", "подлечатель", "подмыватель", "пенетратель", "оратель" и прочее), которые в реальности очень тесно друг с другом связаны и ты не можешь думать о них по отдельности - ты думаешь об игроке, который бегает, прыгает, стреляет, умирает и орёт, а не о кучке полностью независимых систем и компонентов. Мышление человека - основа ООП, а не наоборот, человеку намного проще думать о цельных объектах, чем о кучке ничем не связанных компонентов и систем. А комбинировать компоненты можно и на ООП, никто тебя не заставляет пользоваться наследованием (на которое обычно ругаются, аргументируя в пользу ECS) - пользуйся преимущественно композицией и агрегацией, получишь точно такую же гибкость архитектуры проекта, что и в ECS, но зато объекты будут как в твоих мыслях.
Короче, ИМХО, ООП намного лучше подходит геймдеву, и страдает только в случае если тебе нужно сто тыщ юнитов с одним и тем же кодом, что бывает крайне редко и не факт что вообще получится. Древние стратегии в реальном времени создавали и без модного ECS на медленных процессорах с крайне ограниченным кэшем. Godot, между прочим, имеет под капотом множество оптимизаций по кэшу процессора в системах, где это действительно необходимо (эти системы тут называются "серверы"). Если тебе нужно оптимизировать сто тыщ сущностей по кэшу - ты берёшь и пишешь собственный модуль движка на C++, выставляешь API и дёргаешь по необходимости из GDScript. Да и вообще, Godot не то чтобы самый эффективный, пытаться максимально оптимизировать проект на нём - это как ставить двигатель от реактивного истребителя на Запорожец - технически возможно, но результат вряд ли обрадует. Обещают сфокусироваться на оптимизациях движка, начиная с версии 4.4, тогда как версия 4.3 только вышла в бету. Однако, для освоения базы геймдева Godot сегодня подходит лучше всех, ты просто качаешь движок, создаёшь проект и начинаешь играть в разработчика игр в своё удовольствие, развлечение гарантировано на сотни часов. Можно забыть обо всяких Скретчах, Гейм Мейкерах и т.д.
Ты не понимаешь сути ECS
Замечательно конечно. Но я не соображаю вообще о чем речь идет, а ты меня грузишь.
Я только пытаюсь вкатиться в игродевелопмент.
>Но я не соображаю вообще о чем речь идет, а ты меня грузишь.
>Я только пытаюсь вкатиться в игродевелопмент.
Англюсик знаешь ведь? Хорошо. Иди поиграй в это - онлайн, без смс и регистрации:
https://www.gdquest.com/news/2022/12/learn-gdscript-app/
>Our app is designed to be accessible to people with no programming experience. It provides a step-by-step guide to learning GDScript, starting with the absolute basics and gradually introducing more concepts.
О всяких ECS пока не думай вообще, начинай с самых основ (переменная, цикл, функция и т.д.).
>Англюсик знаешь ведь? Хорошо. Иди поиграй в это - онлайн, без смс и регистрации:
Минимальность только. Уровня хеллоу, зэариз э говнотред.
В системах просто описываешь поведение компонентов. В чем проблема?
Я так же не понимаю программирование. Просто позырил что-то и подумал, что так и должно быть.
Буквально база, фундамент. Расписал все даже лучше чем я бы смог.
Крыша совсем поехала?
База, но нужно не забывать упоминать, что ECS придумали для анчартеда на третьей плойке, в рамках оптимизации под трёшкоплойковский массив сопроцессоров. Там этот ECS давал просраться остальным игорам и выжимал из плойки весь потанцевал.
На архитектуре пека это зачем - вопрос открыт.
Есть метод get_tree().call_group("группа", "метод"). Он вызывает метод из аргумента для всех нод, состоящих в группе и присутствующих в дереве. Ноды могут состоять в любом количестве групп, вплоть до того, что ноды в течение игры могут исключаться из групп и включаться снова. Чем это не ЕЦС? Это больше чем ЕЦС. В группе могут быть непосредственные ноды-"делатели", а могут быть ноды-компоненты, прикреплённые к целевой ноде, и манипулирующие ею. В результате всё равно собирается массив и обрабатывается как в ЕЦС.
Надо будет потестировать этот вариант.
КОТОРЫЙ РАЗ СЛУЧАЙНЫМ КЛИКОМ ПО [ Х ] ЗАКРЫЛ В Е С Ь ПРОЕКТ
@
ВСПОМНИЛ, ЧТО ВРОДЕ БЫЛА КАКАЯ-ТО ОПЦИЯ В НАСТРОЙКАХ
@
ПОИСКАЛ
@
НЕ НАШЁЛ
@
ПОГУГЛИЛ
@
>This seems a neverending wheel. Some people requested confirm quit, so it was added, then people said modern apps do not have this, so this was removed, and now people ask for confirm quit again...
>Есть метод get_tree().call_group("группа", "метод").
Есть пара проблем:
https://docs.godotengine.org/en/stable/classes/class_scenetree.html#method-descriptions
>Calls method on each member of the given group. You can pass arguments to method by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped.
Т.е. ты должен реализовать этот метод везде, где хочешь его вызвать (это не метод вызывающей ноды, а метод вызываемой ноды, иначе этот аргумент был бы Callable, а не StringName). Не проблема, если в группе состоят дубликаты одной и той же сцены/ноды, но ты не можешь просто добавить рандомную ноду в группу, не реализовав в её скрипте соответствующий этой группе метод. Точнее можешь, но тогда попытка вызывать метод пропустит эту рандомную ноду без подходящего метода.
>Note: call_group will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members.
Т.е. метод выполняется у всех нод в группе, и ты не можешь как-то легко взять и разделить этот процесс на несколько потоков или шагов (не создавая новые группы для каждого потока/шага). Нормально, если нужно всего лишь поставить галочку на сотне нод, но десятки тысяч ты так не обработаешь за один кадр. Впрочем, наверное, можно реализовать параллелизм, если забраться в исходники движка... но это может вызвать проблемы с методами, которые обращаются к каким-то внешним данным.
>Ноды могут состоять в любом количестве групп, вплоть до того, что ноды в течение игры могут исключаться из групп и включаться снова. Чем это не ЕЦС? Это больше чем ЕЦС.
Группы - это всего лишь теги. Аналог компонентов из ECS - это метаданные:
https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-set-meta
>Adds or changes the entry name inside the object's metadata. The metadata value can be any Variant, although some types cannot be serialized correctly.
Потому что компоненты хранят в себе какие-то данные, а не просто тег. Система проходит не по массиву тегов, а по массиву конкретных данных, которые, по идее, должны всем массивом загружаться в кэш процессора.
Т.е. бесполезно вызывать метод на нодах. Пример системы в ECS:
>for entry in data_array: entry.x += 1
Этот код загрузился в процессор, процессор увидел "data_array" и скачал весь массив из RAM, пробежался по этому массиву, добавляя +1 для поля x в каждом компоненте, а в конце вернул изменённый массив в RAM. При этом массив должен состоять только из данных, без ссылок (pointer), иначе весь профит теряется при попытке процессора перейти по ссылке, которая указывает в рандомное место в RAM. Конечно, современные процессоры пытаются предугадать переходы по ссылкам и запросить данные заранее, но уязвимости в этом алгоритме вроде как заставили отключить эту фичу (или другую похожую... не помню).
Собственно, без этой фичи (загрузка данных одним блоком) смысла и преимуществ у ECS нет.
Т.е. если ты делаешь так:
>for object in object_array: object.x += 1 # переход по ссылке object в поисках x в RAM
Или, тем более, так:
>for object in object_array: object.do_work() # переход по ссылке object в поисках do_work()
Это не ECS и преимуществ у этого никаких нет.
>Есть метод get_tree().call_group("группа", "метод").
Есть пара проблем:
https://docs.godotengine.org/en/stable/classes/class_scenetree.html#method-descriptions
>Calls method on each member of the given group. You can pass arguments to method by specifying them at the end of the method call. If a node doesn't have the given method or the argument list does not match (either in count or in types), it will be skipped.
Т.е. ты должен реализовать этот метод везде, где хочешь его вызвать (это не метод вызывающей ноды, а метод вызываемой ноды, иначе этот аргумент был бы Callable, а не StringName). Не проблема, если в группе состоят дубликаты одной и той же сцены/ноды, но ты не можешь просто добавить рандомную ноду в группу, не реализовав в её скрипте соответствующий этой группе метод. Точнее можешь, но тогда попытка вызывать метод пропустит эту рандомную ноду без подходящего метода.
>Note: call_group will call methods immediately on all members at once, which can cause stuttering if an expensive method is called on lots of members.
Т.е. метод выполняется у всех нод в группе, и ты не можешь как-то легко взять и разделить этот процесс на несколько потоков или шагов (не создавая новые группы для каждого потока/шага). Нормально, если нужно всего лишь поставить галочку на сотне нод, но десятки тысяч ты так не обработаешь за один кадр. Впрочем, наверное, можно реализовать параллелизм, если забраться в исходники движка... но это может вызвать проблемы с методами, которые обращаются к каким-то внешним данным.
>Ноды могут состоять в любом количестве групп, вплоть до того, что ноды в течение игры могут исключаться из групп и включаться снова. Чем это не ЕЦС? Это больше чем ЕЦС.
Группы - это всего лишь теги. Аналог компонентов из ECS - это метаданные:
https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-set-meta
>Adds or changes the entry name inside the object's metadata. The metadata value can be any Variant, although some types cannot be serialized correctly.
Потому что компоненты хранят в себе какие-то данные, а не просто тег. Система проходит не по массиву тегов, а по массиву конкретных данных, которые, по идее, должны всем массивом загружаться в кэш процессора.
Т.е. бесполезно вызывать метод на нодах. Пример системы в ECS:
>for entry in data_array: entry.x += 1
Этот код загрузился в процессор, процессор увидел "data_array" и скачал весь массив из RAM, пробежался по этому массиву, добавляя +1 для поля x в каждом компоненте, а в конце вернул изменённый массив в RAM. При этом массив должен состоять только из данных, без ссылок (pointer), иначе весь профит теряется при попытке процессора перейти по ссылке, которая указывает в рандомное место в RAM. Конечно, современные процессоры пытаются предугадать переходы по ссылкам и запросить данные заранее, но уязвимости в этом алгоритме вроде как заставили отключить эту фичу (или другую похожую... не помню).
Собственно, без этой фичи (загрузка данных одним блоком) смысла и преимуществ у ECS нет.
Т.е. если ты делаешь так:
>for object in object_array: object.x += 1 # переход по ссылке object в поисках x в RAM
Или, тем более, так:
>for object in object_array: object.do_work() # переход по ссылке object в поисках do_work()
Это не ECS и преимуществ у этого никаких нет.
Я не могу понять в какой момент ECS от примитивных данных на стеке (интов, флотов) переходит к сложным данным в куче (стрингов, мешей)?
Когда мне рассказывают про ECS то как и ты в этом посте приводят пример как проц пробегает по массиву, состоящему из структа с интами, я полагаю из твоего же кода, но игра это же не структы с интами, и ты не сможешь избегать указателей всё время.
Второй пункт ECS состоит в том чтобы не бегать по таблицам виртуальных методов
https://ru.wikipedia.org/wiki/Таблица_виртуальных_методов
Считается что системы уменьшают промахи кеша процессора, типа за раз обходится массив компонентов вызывая один и тот же код системы. А сам компоненты уже плоские структуры данных без методов
>переходит к сложным данным в куче (стрингов, мешей)
>но игра это же не структы с интами, и ты не сможешь избегать указателей всё время.
Вот-вот, и я о том же. ECS только в фантазии даёт твоей игре буст в 100500% скорости по сравнению с "постоянно прыгающим по ссылкам" ООП, а на практике ощутимая разница будет только в узком круге задач, и то не факт.
Зато проблемы архитектуры проекта вылезут, как только начнёшь делать что-то сложнее Hello World, потому что запутаешься в куче неявных связей между "никак (явно) не связанными" компонентами и системами.
Тут где-то был тред Katabasis - по-моему, ОП там признался, что пожалел о своём выборе ECS (на Unity).
Это надо гуглить насколько оправданы такие выводы. Если бенчмарки.
С другой стороны основная фича ECS это замена наследования композицией. Чтобы каждая игровая сущность могла происвольную функциональность иметь.
Эта функциональность разбивается на компоненты. Каждая сущность связывается со своим набором компонент.
И тут представление копонент в виде плоских данных сильно упрощает разработку логики.
Если ты знаком с концепцией стейта, которая в вебразработке используется, например для библиотеки Redux или Vuex - должно быть понятно. Это что то похожее
Набор компонентов - это стейт сущностей. Системы переводят стейт из одного состояния в другое в функциональном стиле.
Для плюсов например максимально прозрачно это делается в популярной библиотеке EnTT
Если есть бенчмарки.
>>>>4685
> С другой стороны основная фича ECS это замена наследования композицией.
Не проблема для годота. К любой ноде можно прикрепить любую ноду, составив тем самым композицию. При этом, основной набор нод основан на наследовании. В итоге движок нас никак не ограничивает. Хочешь наследование - наследуйся. Хочешь композицию, цепляй ноды-компоненты к чарактербоди.
Но я не могу понять другое, как там от примитивных данных на стеке переходят к прогрузке ресурсов в игру, которые как ни крути, в стек не влезут?
Не понял почему примитивных данных
К примеру у тебя классический компонет
stкuct TransformConmponent {
Vector3f position;
Vector3f velocity;
}
система
stкuct TransformSystem {
void update(Registry ®istry, Time &deltaTime) {
...
for (auto elem: components) {
elem.position += elem.velocity * deltaTime;
}
}
}
Потому что им не нужно выделять память в куче.
Надо было добавить настройку "хотите ли вы видеть подтверждение".
бтв скретч заебись. Там часто взрослые дядьки программисты любят своим скиллом литерелли детишек унизить
иди нахуйээээээээээ
E 0:00:01:0491 player.gd:88 @ _physics_process(): Condition "det == 0" is true.
<Исходный код C++>core/math/basis.cpp:47 @ invert()
<Трассировка стека>player.gd:88 @ _physics_process()
Кот:
https://pastebin.com/ZEQA5pM5
Все, разобрался, я сам дурак - масштаб нечаянно выставил в (0.1, 0, 0)
Нах качать из репов если есть аппимейдж? Вообще никогда даже не пытался сам скачивать, всё и так удобно и ебли с зависимостями меньше.