Доброго времени суток! В голову пришла мысль создать игру на Java, так как играть одному неинтересно - игра будет многопользовательска. Движок выбран Jmonkey на базе jogl. В голову приходит клиент серверная архитектура с небольшими поправками - из того что я нашел в интернете: 1. Клиент посылает сообщения на сервер. 2. Сервер их принимает и оповещает остальных игроков - изменение координат, нажатие клавиш, etc. Тут у нас сходу появляется несколько проблем: 1. У всех разная скорость соединения нужно как то делать поправку на пинг, даже не знаю как можно сделать корректировку. 2. Непрерывный флуд, пользователи асинхронно посылают сообщения на сервер и при каждом сообщении нужно оповещать всех остальных игроков. Решение: 1) посылать сообщения не каждый раз при нажатии, а по таймауту. 2) На сервере составлять очереди сообщений и высвобождать их одновременно, так же по таймауту. 3. Игрок нажал кнопку ходить и начал двигаться в определенном направлении у себя на клиенте, но сообщение еще не поступило на сервер и к другим игрокам тут у нас происходит рассинхронизация, пока сервер не будет оповещен и другие игроки не получат его новые действия и координаты с поправками. Если кто то сталкивался с такими проблемами в играх или в подобных приложениях. Подскажите направление решения задачи, какие еще проблемы могут встретится в подобной архитектуре. Спасибо.
Чтобы ускориться видимо нужен вебсокет. А вот сам принцип синхронизации персонажей это интересный вопрос. Если это не пошаговая игра, а риалтайм нельзя равняться по последнему. Пока персонажи не взаимодействуют, можно пренебречь задержками. Ну отрисуется фигурка не совсем по месту - фигня. Но как только происходит какое-то действие между двумя акторами, надо их приводить к общему состоянию, пусть даже ценой залипания на какое-то мгновение. Я так думаю.
Я думаю подобные вопросы нужно задавать на соответствующем форуме. Тут нет сильных игроделов-практиков, а тема неодназначная и сложная. Не имея реального опыта решения этих задач, ничего хорошего не посоветуешь.
Дело то в алгоритеме, а сидят тут люди разные. Я посчитал, что если мы имеем 100 игроков в локации, то за единицу времени нужно будет отправить (100-1)*100 = 9900 сообщений - те самые over 9000. Смотря какое взаимодействие, если один игрок в другого выкинул фаербол - создается объект фаербол и он летит за вторым игроком как отдельный объект. Если нужно сделать допустим бартер между игроками то оба игрока должны стоять и задержка в полсекунды - нормально. А вот если вов или ланэйдж и рубятся с фпс 25 100 на 100 игроков то тут уже тяжелее. Буду делать простой месседжер с сервером на Java и Websocket для теста производительности. Попробую разные варианты - какой быстрее.
Ну если включить диванного аналитега то: почему так? непонял. мы на сервере моделируем весь игровой процесс. за единицу времени расчитали все изменения, собрали это в пакет и разослали этот "diff" всем 100 игрокам. и получили ответ с действиями каждого игрока. т.е. получается 100 сообщений таду и 100 обратно. далее все повторяется. далее. если в игре есть физика, то траекторию того же самого фаербола, можно расчитать и на клиенте(зная скорость, радиус поражения и т.д.), а вот попал он в итоге или нет уже зависит успел ли противник убежать или нет. но передавать координаты самого фаербола, вроде как и ненужно, клиент сам это отрисует, важно лишь событие попадания фаербола во врага.
https://toster.ru/q/306868 паралельная тема. over 9000 это мем. В общем паковать все изменения об игроках в пакеты по типу для юзера 1 user1[user1-data,user2-data] для юзера 2 user2[user1-data,user2-data] Только не понятно как их собирать и рассылать, накапливать в очереди и рассылать всем одновременно по таймеру, например каждые 0,5 секунд? Небольшой тест http://www.gabrielgambetta.com/fpm_live.html Добавлено спустя 1 минуту 18 секунд: Ответы от комьюнити разработчиков движка: Код (Text): Networking is a fairly difficult topic to start with. I wouldn't recommend it. also please note that many games get networking hoplessly wrong. See the different forums for your fav game to see the problems apon problems with the network side of life. So start with a game. Add networking later. I'll wait. Now you have a single player game working fairly well we can start thinking about networking. There are libs and stuff to make the "marshaling" of messages or objects easier or harder. But we typically now come to the first important design question. Peer to Peer or server based. These days many people are just going server. But for smaller games like RTS etc peer to peer can still work well. Bad connections do run badly and mostly we humans have got very good and adjusting ourself to things like lag. There is not much you can do about it. The speed of light is just too slow. (260ms ping for around the world is about as good as it gets, and in fiber it is a little slower). Next is TCP or UDP, if your using a lib (you probably should) that will do this for you and you don't need to worry about it. Mostly you should ALWAYS START WITH TCP. No UDP is not faster, and it is not "better". there is one very narrow exception to that rule. A game where you can send the entire game state in a single packet and you send such packets at a fixed rate. Quake 3 and Unreal do this. Outside that use TCP. Seriously. Do you know what the 2 generals problem is? What flow control is? Congestion collapse? Packet fragmentation? Then you don't know enough about networks to tell me UDP is better and you don't know what TCP really does. Now if your using a lib or TCP we finally get to your questions more or less. As stated before the simplest solution is to just send the full game state every game tick to all clients. this only works for small games. But when it does work it is a really simple system that is fairly easy to implement. Users send actions to the server. Server at the end of a game tick, processes all actions. Sends out new game state. Rinse and repeat. More complicated systems are much harder to implement. But that is a good place to start. Esp if you havn't done networking before. Код (Text): Also it depends on what type of game you are making. You'll see very different solutions in say an RTS when compared with a FPS. https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking This goes into Sources latency solutions pretty in depth. Again though you gotta adapt.. PvE or PvP can be a major difference maker. PvE allows you to take a lot of liberties in how you handle things :smiley: EDIT: Just saw you say rpg. Planning on one server or multiple? Either way try to keep it simple this time round :wink: That way you might end up with a finished product Код (Text): Well You can only try to hide, it is always there (see Valva/Quake3 style networking for more infos on ping compensation) -> Also keep in mind that their tricks only barely work with physic engines 2.) Send the updates at a fixed rate instead, see Quake3 networking 3:) Complex, see Quake3 networking. Depdening on what game you have you might need a completly different solution. -> Eg RTS have no problem with slightly delayed reactions -> MMO's usually can ignore the slight desync, as all hits ect. are done serverside automatic, and it does not really matter if you are 0.5meters off. -> FPS now this is where it gets tricky, it depends on the type of fps -> -> World of tanks can ignore slight dealys quite fine, as noone expects atank to react very fast -> -> Quake 3 can replay parts as it has no physic, and retroactivly calculate what happesn -> -> Coop games can ignore potential cheating stuff, and just play happy world networking In practice I currenlty have a ok feeling, by only interpolating rotation client side, but do the actual moving serverside. -> Rotation delays are percieved way stronger Also note there are some mmo networkign middlewares, at least worth a look. https://hub.jmonkeyengine.org/t/server-architecture-not-for-fun/35520/7 http://javatalks.ru/topics/question/49049 http://www.gamedev.ru/code/forum/?id=212674#m6
runcore, Верно, а как быть с синхронизацией и тиками. 1)Я игрок1 бегу за игроком 2 -> он посылает пакеты бежать в одну сторону, я за ним. Потом проходит n времени я бегу за ним, а они у себя на клиенте развернулся и до меня этот пакет долетел "медленно". Как избежать таких "рывков". 2)Я зажал клавишу бежать, насколько часто нужно посылать пакеты серверу. 3)Серверу накапливать пакеты в очереди и доставлять по таймауту всем сразу большим пакетом обо всех игрока [player1,player2] 4)Или брать 1 пакет одного игрока и доставлять всем? 5) Как быть с локациями, смена локации
Обычно в некоторых MMO и сетевых экшенах сервер просчитывает позицию объекта "наперед" в случае небольшой задержки пакета, поэтому остальные игроки задержек коротких замечать не будут.
на 100% наверное не избежать. но можно попытаться их сгладить, для игрока. нет смысла ждать отклика от самого медленного. сервер все изменения в игре рассылает клиентам. с определенной частотой. получил/неполучил/получил поздно - это не проблема сервера. если задержка, и клиент получил несколько пакетов, то берем только самый свежий, старые уже неактуальны. если клиент неполучил вовремя инфу - то он продолжает думать что противник ведет себя так как должен себя вести на основании того что о нем известно. но с каждым квантом времени степень этой экстраполяции траекторий должна очевидно уменьшаться и сходить на нет. Частота обмена данными должна быть заведомо выше, чем та что физиологически способен сгенерировать человек...
1.Обычно в некоторых MMO и сетевых экшенах сервер просчитывает позицию объекта "наперед" в случае небольшой задержки пакета, поэтому остальные игроки задержек коротких замечать не будут. 2. Опять же в разных играх по разному решается. Некоторые в целях экономии могут ждать нажатия другой клавиши или действия отпускания клавиши, иные шлют пакеты постоянно с четкой заданной регулярностью. 3. Не всем игрокам вообще, а всем игрокам в зоне видимости. 4. О всех игроках всем другим игрокам в зоне видимости (если происходила какая-либо активность объекта игрока). 5. Если концепция единого игрового мира, то постепенная подгрузка контента, как это реализовано, к примеру в Unity, где игровой локацией может быть принята текущая зона видимости клиента. Как правильно замечено в цитатах, на многие вопросы можно получить ответ сделав простую сингл-игру. Где точно также будет решаться вопрос частичной загрузки игрового мира в целях экономии ресурсов.
Проблема одна - разный пинг, остальных проблем нет. Нет такой проблемы "флуд", ты же не графику тащишь по каналам - сколько там этих игровых сообщений? Наберется ли хоть 1 мбит/сек? Короткий пинг дает преимущество перед игроками с длинным пингом. То же самое с FPS, с этим трудно что-то сделать. Можно использовать облачную архитектуру сервера, чтобы максимально уровнять это время. Алсо большинство игроков не заметит разницы в пинге 50 и 80 мс, обычно проблемным считается пинг свыше 100 мс.
Zuldek вот это кстати отличная идея единый игровой мир и постепенная подгрузка. Как считаете такой вариант: у меня есть уровень с физикой - реки горы дома. Я создаю сетку - грубо говоря массив, в нем помечаю непроходимые места типа гор, телепорты - при наступлении на которые будет происходить перенос игрока. В этот массив помещаются игроки им дается радиус видимости тоесть, точка в которой находится игрок и + 3 квадратика видимости. Если в этот радиус видимости падает объект на карте - то он появляется. Если в этот радиус попадают игроки или монстры, то начинается взаимный обмен пакетов. Или может быть есть какой то лучший алгоритм? Добавлено спустя 1 минуту 32 секунды: Кто то знает разницу в отправке tcp и udp пакетов в клиент серверной архитектуре онлайн игр?
В принципе на UDP ты можешь релизовать собственные подтверждения действиям там, где это нужно, а что игроку с плохим интернетом придется сделать 10 кликов вместо 9 - это ерунда. Зато не будет виснуть =)
Небольшая подборка на тему мультиплеер tcp/udp https://yadi.sk/d/ZFKNnLI0qXZAe Добавлено спустя 25 минут 23 секунды: Вообще рассматриваю архитектуру в целом но в jmonkey показали мне вот эту штуку https://javadoc.jmonkeyengine.org/com/jme3/network/package-frame.html Буду на днях тестировать клиент серверный чат на нагрузку по пакетам. (tcp/udp) io/nio разные форматы тики
В общем нужно софрмулировать лучшие идеи в pdf написать udp p2p + сервер чат. Выложу в гитхаб для тестов.
Многопользовательская онлайн игра – передача пакетов client-server,p2p,tcp/upd,графы Описание процесса и поставновка задачи: 1)каждый игрок совершает действие у себя на клиенте и должен оповестить об этом игроков монстров и игровые объекты в определенном радиусе. 2) Игрок должен видеть 3d объекты и монстров только в опреденном радиусе. 3) Сервер выполяя действия за мир и монстров и оповещает об этом всех игроков или игроков в опреденном радиусе от объекта. 4) игрок монстры и сервер выполняя действия формируют сообщения или пакеты 5) формат игрового сообщения или пакета псевдокод [player1,player2,server][time_stamp][client/server][geo_location][game_map_location][net_key][player_id][visible_radius]– [player1,player2,server]Где каждый элемент это серриализованный объект player[ actions[ [hit,player2,fireball],[run,vector],[rotate,radius] ], player[param1,param2], items[item1,item2], message[string,chat], gruops[clan,party], time[time_stamp] ] Если отправлять сообщения от клиентов на сервер и формировать большой пакет. Проблемы: 1) Синхронизация игроков 2) Клиент серверная синхронизация 3) Низкая скорость передачи tcp/upd, низка скорость передачи clien-server 5) Обо всех пакетах должен знать только сервер, 6) Игроки находятся на разном расстоянии географически – что снижает скорость передачи 7) Необходимо посылать пакеты только соседним объектам 8) Пакеты могут потеряться, пакеты можно подменить Варианты решения на уровне игры: 1) Двумерный массив [][] который соответсвует физической карте игрового мира 2) Добавление игровых объектов в этот массив 3) Добавление радиуса видимости для каждого объекта который может посылать пакеты 4) Объект посылает пакеты только объектам которые находятся в определенном радиусе от него 6) Формируются группы объектов 5) Один из объектов назначается главным 6) Каждый из группы объектов посылает каждому пакет 7) Создается эталонный пакет 8) Главный объект группы посылает всем эталонный пакет Решение на уровне сети и сервер: 1)Берется карта мира и создается двумерный массив, ячейка содержит в себе информацию о регионе[country][city] и обо всех клиентах находящихся в регионе 2)По этим точкам строится граф и просчитываются кратчайшие пути до каждой точки 3)В каждом регионе выбирается несколько клиентов с самой высокой скоростью 4)Один из клиентов становится сервером передачи данных для всех остальных в регионе 5)Сервера региона передают сообщения по цепочке и по кратчайшему пути между собой и до сервера 1)Клиенты посы лают сообщения по таймауту 2)На сервере создается поток который формирует очереди сообщений 3)На главном сервере так же создается очередь сообщений
Что, впрочем, совершенно не важно, если игра будет пошаговая, верно? Ну кроме пункта 8, но это решается. Эти проблемы только для сурового рилтайма актуальны, я правильно понимаю.
Реал тайм иначе неинтересно. В общем объект(клиент/сервер) просто посылает сообщения серверу и другим игрока. Вопрос в том как это оптимизировать: 1) ускорить передачу 2) отсечь ненужную информацию 3) правильно синхронизировать Добавлено спустя 8 минут 35 секунд: Интересный комментарий на хабре https://habrahabr.ru/post/280720/#comment_8836612 Добавлено спустя 41 минуту: Цитирую совет Погугли "гексагональная сетка" и "гексагональная система координат" Предлогают NIO + простой клиент сервер.