Game Center Поиск совпадения программно
Я просто не могу понять, как это работает. То, что я пытаюсь сделать, это позволить двум игрокам играть в игру, если третий игрок присоединяется к нему, он может немедленно присоединиться к игре, если четвертый и последний игрок присоединяется, он также может мгновенно присоединиться к игре. Они также могут выйти из игры в любое время по любой причине, если это произойдет, должно быть место, открытое для другого человека или для того же человека, чтобы восстановить соединение. Это идея.
Теперь я получил следующее. Я аутентифицирую местного игрока по понятным причинам. Затем я ищу совпадение так:
if (matchRequest) [matchRequest release];
matchRequest = [[GKMatchRequest alloc] init];
matchRequest.minPlayers = 2;
matchRequest.maxPlayers = 4;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:matchRequest withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error) {
// An error occured
} else {
if (matchCurrent) [matchCurrent release];
matchCurrent = [match retain];
matchCurrent.delegate = self;
}
}];
Если я выполню эту часть на трех разных устройствах, два из них найдут друг друга, а третье все еще ищет. Поэтому я решил, что после поиска соответствия для запроса будет найдено минимальное количество игроков, которое будет выполнено один раз. Так что мне нужен был метод, который использовал matchCurrent, который я сохранил, чтобы добавить больше игроков. К счастью, этот метод существовал, но как он будет работать? Когда вы называете это в этом случае? Я решил поместить его под кнопку, чтобы вручную выполнить его, когда совпадение найдено.
Я обнаружил, что когда я нажал его на первом устройстве, наконец, третье устройство могло найти совпадение, в котором находились первое и второе устройства. Фактически, второе и третье устройства содержали идентификаторы игроков каждого задействованного устройства. Что хорошо. Но есть две проблемы.
- Какое устройство на самом деле должно вызывать метод addPlayersToMatch? И как вы можете ограничить это одним устройством, выполняющим этот метод? Плюс, когда ты должен это назвать?
Почему на устройстве, вызывающем этот метод, не обновляются идентификаторы игроков?
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:matchCurrent matchRequest:matchRequest completionHandler:^(NSError *error) { //matchCurrent.playerIDs is not updated?! }];
На самом деле они обновляются. Когда я вижу, что идентификаторы playerID появляются на втором и третьем устройстве, я вручную обновляю matchCurrent.playerIDs на устройстве one, и внезапно он распознает игрока. Однако даже "didChangeState" для игрока не вызывается, когда новый игрок обнаружен на первом устройстве.
4 ответа
Вы используете Apple iOS Game Center GKMatchmaker класс. Я предполагаю, что вы используете одноранговое соединение, а не хостинг.
Класс GKMatch предоставляет вам массив playerIDs.
@property(nonatomic, readonly) NSArray *playerIDs
Это упорядоченный список, поэтому вы можете использовать его для выбора первого вызова игрока addPlayersToMatch.
Ниже приведена некоторая документация.
Какое устройство на самом деле должно вызывать метод addPlayersToMatch? И как вы можете ограничить это одним устройством, выполняющим этот метод?
Вы можете решить эту проблему, если бы устройства "рисовали соломинки". Каждое устройство генерирует случайное число, а затем отправляет его другим. Устройство с наибольшим номером является лидером, и именно оно должно вызывать addPlayersToMatch. Если два устройства выбирают один и тот же номер, выбросьте цифры и начните все сначала.
Я бы посоветовал вам периодически (возможно, раз в секунду или два) опрашивать статус других игроков, чтобы вы могли определить, присоединился ли кто-либо или ушел по какой-либо причине. Если архитектура iphone, которую вы используете, уже предоставляет функцию, которая обрабатывает это событие.
Похоже, вы захотите найти дополнительную документацию и / или пример кода для многопользовательской среды, которую вы используете.
Я делаю это с Unity через GameCenterMultiplayerBinding Prime31 . Я не совсем уверен, как это соотносится с GameKit (документы скудны и не содержат этих деталей), но названия очень наводят на размышления.
Чтобы иметь возможность подбирать от 2 до 4 игроков в матче, я делаю:
findMatchProgrammaticallyWithFilters(
minPlayers: 2,
maxPlayers: 4,
playerGroup: GetCurrentPlayerGroup(),
playerAttributes: 0);
Я предполагаю, что это соответствует findMatchForRequest:withCompletionHandler.
После этого я звоню:
Что, безусловно, соответствует finishMatchmakingForMatch. Я обнаружил, что вызов findMatchForRequest или addPlayersToMatch завершился ошибкой с сообщением «Запрошенная операция была отменена или отключена пользователем», если я не позвонил первым.
addPlayersToCurrentMatchWithUpdatedMatchRequest(
minPlayers: 2,
maxPlayers: 4,
playerGroup: GetCurrentPlayerGroup(),
playerAttributes: 0,
playersToInvite: null);
addPlayersToMatch:matchRequest:completionHandler
После этого я звоню:
finishMatchmakingForMatch();
Если у меня есть место для других игроков, я зацикливаюсь и снова звоню.
Я ожидал этого, так как мне нужно позвонить
finishMatchmakingForMatch
когда я закончу сватовство, стреляю
findMatchProgrammatically
будет продолжать искать, пока не найдет maxPlayers, но это не так. Сдается после первого матча. Итак, нам нужно позвонить
addPlayersToMatch
.