Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Что выбрать PacketID или ObjectID?

Что выбрать PacketID или ObjectID?

Поделиться
gamedeveloper01Пользовательwww10 фев. 201716:10#0
Я понимаю что на этом форуме нет нормальных сетевиков, но я всё таки подыму эту тему.

Короче сейчас я использую классическую схему с PacketID (еще по другому OpCodes) и обработчиками пакетов. Но меня манит другой подход, более объектно ориентированный. Вместо 16 бит PacketID использовать связку из ObjectID (11 bit) + RPCID (5 bit), можно и другое распределение бит, если где то не хватает. Чтобы оперировать не сообщениями, а сразу объектами и их RPC. Можно конечно каждому PacketID формально прилепить свой объект, храня на него ссылку в обработчике пакета, но это как то слишком примитивно и не ООП.

В общем хочу сделать что то похожее на UE4, где есть экторы, и у экторов есть RPC. Только ObjectID не будут генерироваться автоматически а будут задаваться статически в коде, как и PacketID. Прелесть в том, что для RPCID можно использовать значения от 0, то есть для каждого объекта свой набор RPC со своими локальными идентификаторами, а не глобальный список идентификаторов PacketID.

Если сервер и клиент - это один проект, как в UE4, то ObjectID можно генерировать автоматически (increment), как и RPCID.

ObjectID это не InstanceID. InstanceID можно передавать при необходимости после ObjectID + RPCID.

Вместо обработчиков пакетов, когда для каждого пакета обычно создается свой класс с обработкой, в случае с ObjectID это не потребуется, нужно будет использовать делегаты, то есть брать ссылку на функцию (RPC) и регистрировать её вместе с ObjectID и RPCID, если делать это с PacketID то это скорее минус, но в случае с ObjectID использование делегатов скорее плюс, потому что эти делегаты (RPC) итак имеют привязку к ObjectID в котором они находятся.

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

Пример:
Для логина можно сделать объект Login или LoginManager (ObjectID = 1), и добавить ему парочку RPC (LoginRequest (RPCID=0), LoginAccepted (RPCID=1) ну и так далее). Потом допустим заходим в Lobby (ObjectID = 2), добавляем парочку RPC (SearchGame (RPCID=0), GameFound (RPCID=1)...), делаем FriendList (ObjectID = 3) добавляем парочку RPC (AddFriend, RemoveFriend, FriendLogon, FriendLogoff...).

Если бы использовались PacketID то пришлось бы все RPC смешивать в одну кучу.

Короче смысл думаю понятен.

Поэтому я уже практически полностью решил отказаться от классического примитивного PacketID (OpCode), наверное, вряд ли.

NOTE: В движках обычно свой встроенный ObjectID и RPC (Unity, UE4), но у меня как бы сетевая библиотека, а не движек, а в библиотеках обычно лепят PacketID, тот же Photon например.

NOTE2: также могут возникнуть сложности, ведь нужно выделять объекты и распределять RPC по объектам, вместо того, чтобы просто сделать единый список всех действий, потребует определенных усилий.

Проблема1: сразу на ум приходит проблема, что PacketID на самом деле более простой и более гибкий подход, к тому же централизованный, все сетевые сообщения можно объединить в один протокол, а не распихивать обработчики по разным объектам.

Проблема2: какие то непонятки с обработчиками, во первых RPC придется делать статическими, если мы не хотим для каждого соединения устанавливать обработчики заново. Во вторых, допустим у нас есть FriendList, он должен быть у каждого игрока свой, но обработчики должны быть общие-статические, но для ObjectID придется регистрировать указатель на FriendList? В случае с PacketID мы просто получаем ссылку на соединение и оттуда берем все необходимые данные игрока, тогда мы либо делаем все обработчики вида Handler(connection, reader), либо Handler(object=friendList, reader), чтобы получить обработчик сразу с объектом, то нужно заново зарегистрировать все статические обработчики для соединения указав для них нужный object, либо использовать обработчик с соединением, но тогда какой смысл от ObjectID. Идеальный вариант, когда RPC встроен в движек, и не нужно делать обработчики статическими, делаешь обычные функции, добавляешь атрибут RPC, и всей маршрутизацией и регистрацией занимается движек. В случае с PacketID всё просто, создаётся один протокол, один раз регистрируются все обработчики вида Handler(connection, reader) и всё.

Проблема3: для простых серверов и простых задач не требуются объекты, или попросту нужен только один объект, что мало отличается от обычного PacketID. Либо делать поддержку и PacketID и ObjectID.

Итог: не рискну, законсервирую данный вопрос до лучших времен.

Правка: 10 фев. 2017 17:55

AmaBobПостоялецwww10 фев. 201720:17#1
gamedeveloper01
> Я понимаю что на этом форуме нет нормальных сетевиков, но я всё таки подыму эту
> тему.
Данунафиг. Нет же нормальных сетевеков на этом форуме.
Demiurg-HGПостоялецwww10 фев. 201722:04#2
gamedeveloper01
> В общем хочу сделать что то похожее на UE4
UE4 заточен на удовлетворение хотелок всех подряд.

Делай обычную snapshot-based систему с дельта-компрессией, дешево, надежно, практично, стабильно.
+Бесплатные save и replay.

Если хочешь сделать поддержку протоколов разных версий — добавь версию в заголовок снапшота.

Demiurg-HGПостоялецwww10 фев. 201722:06#3
gamedeveloper01
> (AddFriend, RemoveFriend, FriendLogon, FriendLogoff...).
Это же всякие Steam API из коробки умеют?

> Для логина можно сделать объект Login или LoginManager
Обычно при коннекте клиент шлет user info, а сервер решает — давать или не давать.

XsПользовательwww11 фев. 201710:59#4
Поддерживать, рефакторить и жить с кодом построенным как хендлеры для опкодов куда проще чем с rpc привязанным к ооп. Нужно будет либо тулзы для рефакторинга писать и тестами покрывать лишние кейсы, либо обсираться через шаг если проект более менее долгий. Как ни странно, но традиционный ооп в играх часто противоречит здравому смыслу, особенно когда это касается сетевого взаимодействия. Серверную БЛ например куда проще писать и поддерживать если она стейтлесс (а часто и по перфу лучше) чем если это страшные ооп деревья где вперемешку данные и поведение. Растут зависимости, связанность, а в геймдеве где бл меняется кардинально и постоянно это очень больно бьет. Когда мне нужно было рпц я оборачивал рпц в опкод.
Sh.Tac.Постоялецwww11 фев. 201715:27#5
Demiurg-HG
> обычную snapshot-based систему с дельта-компрессией
а это всё и всегда нужно посылать, по трафику бывает выгоднее частями и не каждый раз, и тут могла бы пригодиться некоторая система кодирования объектов и полей чтобы сервер больше не посылал то что не изменилось
gamedeveloper01Пользовательwww11 фев. 201717:13#6
Xs
> Поддерживать, рефакторить и жить с кодом построенным как хендлеры для опкодов
> куда проще чем с rpc привязанным к ооп. Нужно будет либо тулзы для рефакторинга
> писать и тестами покрывать лишние кейсы,
Я тоже об этом подумал

/ Форум / Программирование игр / Сеть

2001—2017 © GameDev.ru — Разработка игр