Вопрос по реализации таймеров в геймдеве.

Возьмем какую-нибудь мультиплеерную (это важно) "ферму" или травиан-like стратегию. В ней игроки строят/изучают. Каким образом это реализовано на сервере?

Ниже просто мои размышления.

Допустим, мы делаем табличку с заданиями. Когда игрок нажимает "построить сортир", туда, в табличку, записываем время начала строительства и время его окончания. Так же у нас работает cron, в котором скрипт раз в N времени достает все задачи, проверяет время - и если оно истекло, то удаляет задание из таблички, а в другую делает запись о появившемся "сортире".

Всё это по идее неплохо работает в сингле или на крайне ограниченном количестве игроков. А если их хотя бы пара тысяч и каждый постоянно что-то строит/изучает?

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

Можно пойти другим путем и на каждое задание спавнить тред, в котором будет реализован таймер ожидания. Избавляемся от проблем с периодичностью запуска планировщика, но упираемся в ресурсы. 2-10к тредов с таймерами непонятно во что выльются и скорее всего только рестарт такого монстра будет занимать недопустимое время. Опять тупик.

В общем, хотелось бы увидеть ответ по реализации.

66
17 комментариев

Комментарий недоступен

6
Ответить

и раз в N времени скорее всего раз в секуну сверяем не наступила ли дата, эта операция сравнения таких можно хоть пару сотен миллионовВам как минимум необходимо эти данные достать из базы, а это уже не "миллионы раз в секунду", особенно если база на отдельном сервере. Плюс если все эти проверки идут в одном треде (да даже в нескольких), то затянувшееся обновление одной записи затормозит обновление всех остальных.

Ответить

Это же игра от Алавар про постройку отелей на скриншоте? 

4
Ответить

Да, «Построй-ка» называется

3
Ответить

Не знаю. Просто картинка из интернета)

1
Ответить

Всё проще: записываем в таблицу время начала строительства, и пока никто не обратился к игровому состоянию этого игрока больше ничего не делаем. Если потребовалось получить эту информацию (игрок создал сессию или произошло мультиплеерное событие) - читаем текущее состояние и актуализируем его, т.е. все завершённые здания становятся достроенными и в режиме fast-forward вычисляется их влияние на состояние игры с момента постройки до текущего момента (т.е., например, если построена шахта то добавляются все ресурсы которые она должна была произвести с момента постройки). Никаких таймеров, тредов и крона (представляйте что они сделают с сервером с миллионом игроков, 75% которых не заходили уже полгода?). Максимум отдельная очередь сообщений для push-нотификаций.

4
Ответить

Можно пойти другим путем и на каждое задание спавнить тред, в котором будет реализован таймер ожидания. Избавляемся от проблем с периодичностью запуска планировщика, но упираемся в ресурсы. 2-10к тредов с таймерами непонятно во что выльются и скорее всего только рестарт такого монстра будет занимать недопустимое времяХреновая идея.

А так подхода два - либо дергаем по таймеру, как ты описал (индексы помогут сделать это быстро, 2к игроков не проблема). Либо проверяем даты как только игрок что-то делает. Например, зашел в игру - проверились даты окончания, успешные здания "построились" в тот же момент. Либо решил напасть на игрока - и как только запускается атака, проверяем и обновляем статус зданий

1
Ответить