不能接收游戏中心的邀请

我正在尝试通过使用http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center上的教程来使用cocos2d为iOS开发实时多人游戏-tutorial部分-22

一切正常,包括与随机播放器自动匹配,但邀请朋友不起作用,因为其他设备无法收到邀请。

当我点击邀请朋友按钮,然后通过使用标准游戏中心界面选择一个朋友时,它说等待(永远),没有任何反应。 我的朋友无法收到游戏中心的邀请(没有通知)。

我可以邀请朋友使用附近的朋友功能(当这两个设备上启用此功能时),但是当附近的朋友被禁用时没有邀请通知。

我花了几个小时在Google上搜索,发现了类似的情况,但没有解决方案。

关于可能答案的一些早期反馈:

  • 我使用两个设备(一个iPhone和一个iPad),没有模拟器
  • iTunes连接上的所有设置都可以,包括多人游戏设置
  • 我通过使用不同的测试帐户验证了两台设备已连接到沙箱
  • 我已经在两台设备上检查了Game Center的通知设置
  • 我已经检查了所有代理/防火墙问题,并尝试了两种设备的WiFi和Cellular
  • 为两个设备/帐户启用游戏邀请
  • 我已经检查过捆绑ID,应用版本ID等...
  • 这两个设备都是IOS 6.x和App目标版本IOS IOS 5.0
  • 我没有关于游戏中心的其他问题(排行榜,随机比赛等......都很好)
  • 我在苹果文档中提到的尽可能对用户进行身份验证后尽快调用inviteHandler方法。
  • 这里是我的游戏中心帮手类头文件:

    #import <Foundation/Foundation.h>
    #import <GameKit/GameKit.h>
    @protocol GCHelperDelegate
    - (void)matchStarted;
    - (void)matchEnded;
    - (void)match:(GKMatch *)match didReceiveData:(NSData *)data
    fromPlayer:(NSString *)playerID;
    - (void)inviteReceived;
    @end
    
    @interface GCHelper : NSObject <GKMatchmakerViewControllerDelegate, GKMatchDelegate>{
    BOOL gameCenterAvailable;
    BOOL userAuthenticated;
    
    UIViewController *presentingViewController;
    GKMatch *match;
    BOOL matchStarted;
    id <GCHelperDelegate> delegate;
    
    NSMutableDictionary *playersDict;
    
    GKInvite *pendingInvite;
    NSArray *pendingPlayersToInvite;
    NSMutableArray *unsentScores;
    }
    
    @property (retain) GKInvite *pendingInvite;
    @property (retain) NSArray *pendingPlayersToInvite;
    
    @property (assign, readonly) BOOL gameCenterAvailable;
    
    @property (retain) NSMutableDictionary *playersDict;
    
    @property (retain) UIViewController *presentingViewController;
    @property (retain) GKMatch *match;
    @property (assign) id <GCHelperDelegate> delegate;
    
    - (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers
                 viewController:(UIViewController *)viewController
                       delegate:(id<GCHelperDelegate>)theDelegate;
    
    - (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent;
    
    + (GCHelper *)sharedInstance;
    - (void)authenticateLocalUser;
    
    @end
    

    这里是游戏中心助手类的实现

    #import "GCHelper.h"
    
    @implementation GCHelper
    
    @synthesize gameCenterAvailable;
    
    @synthesize presentingViewController;
    @synthesize match;
    @synthesize delegate;
    @synthesize playersDict;
    @synthesize pendingInvite;
    @synthesize pendingPlayersToInvite;
    
    #pragma mark Initialization
    
    static GCHelper *sharedHelper = nil;
    + (GCHelper *) sharedInstance {
        if (!sharedHelper) {
            sharedHelper = [[GCHelper alloc] init];
        }
        return sharedHelper;
    }
    - (BOOL)isGameCenterAvailable {
        // check for presence of GKLocalPlayer API
        Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
    
        // check if the device is running iOS 4.1 or later
        NSString *reqSysVer = @"4.1";
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        BOOL osVersionSupported = ([currSysVer compare:reqSysVer
                                               options:NSNumericSearch] != NSOrderedAscending);
    
        return (gcClass && osVersionSupported);
    }
    - (id)init {
        if ((self = [super init])) {
            gameCenterAvailable = [self isGameCenterAvailable];
            if (gameCenterAvailable) {
                NSNotificationCenter *nc =
                [NSNotificationCenter defaultCenter];
                [nc addObserver:self
                       selector:@selector(authenticationChanged)
                           name:GKPlayerAuthenticationDidChangeNotificationName
                         object:nil];
            }
        }
        return self;
    }
    - (void)authenticationChanged {
    
        if ([GKLocalPlayer localPlayer].isAuthenticated && !userAuthenticated) {
            NSLog(@"Authentication changed: player authenticated.");
            userAuthenticated = TRUE;
    
            [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
    
                NSLog(@"Received invite");
                self.pendingInvite = acceptedInvite;
                self.pendingPlayersToInvite = playersToInvite;
                [delegate inviteReceived];
    
            };
    
        } else if (![GKLocalPlayer localPlayer].isAuthenticated && userAuthenticated) {
            NSLog(@"Authentication changed: player not authenticated");
            userAuthenticated = FALSE;
        }
    
    }
    - (void)lookupPlayers {
    
        NSLog(@"Looking up %d players...", match.playerIDs.count);
        [GKPlayer loadPlayersForIdentifiers:match.playerIDs withCompletionHandler:^(NSArray *players, NSError *error) {
    
            if (error != nil) {
                NSLog(@"Error retrieving player info: %@", error.localizedDescription);
                matchStarted = NO;
                [delegate matchEnded];
            } else {
    
                // Populate players dict
                self.playersDict = [NSMutableDictionary dictionaryWithCapacity:players.count];
                for (GKPlayer *player in players) {
                    NSLog(@"Found player: %@", player.alias);
                    [playersDict setObject:player forKey:player.playerID];
                }
    
                // Notify delegate match can begin
                matchStarted = YES;
                [delegate matchStarted];
    
            }
        }];
    
    }
    
    #pragma mark User functions
    
    - (void)authenticateLocalUser {
    
        if (!gameCenterAvailable) return;
    
        NSLog(@"Authenticating local user...");
        if ([GKLocalPlayer localPlayer].authenticated == NO) {
            [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil];
        } else {
            NSLog(@"Already authenticated!");
        }
    }
    
    - (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id<GCHelperDelegate>)theDelegate {
    
        if (!gameCenterAvailable) return;
    
        matchStarted = NO;
        self.match = nil;
        self.presentingViewController = viewController;
        delegate = theDelegate;
    
        if (pendingInvite != nil) {
    
            [presentingViewController dismissModalViewControllerAnimated:NO];
            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease];
            mmvc.matchmakerDelegate = self;
            [presentingViewController presentModalViewController:mmvc animated:YES];
    
            self.pendingInvite = nil;
            self.pendingPlayersToInvite = nil;
    
        } else {
    
            [presentingViewController dismissModalViewControllerAnimated:NO];
            GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
            request.minPlayers = minPlayers;
            request.maxPlayers = maxPlayers;
            request.playersToInvite = pendingPlayersToInvite;
    
            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
            mmvc.matchmakerDelegate = self;
    
            [presentingViewController presentModalViewController:mmvc animated:YES];
    
            self.pendingInvite = nil;
            self.pendingPlayersToInvite = nil;
    
        }
    
    }
    
    #pragma mark GKMatchmakerViewControllerDelegate
    
    // The user has cancelled matchmaking
    - (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController {
        [presentingViewController dismissModalViewControllerAnimated:YES];
    }
    
    // Matchmaking has failed with an error
    - (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error {
        [presentingViewController dismissModalViewControllerAnimated:YES];
        NSLog(@"Error finding match: %@", error.localizedDescription);
    }
    
    // A peer-to-peer match has been found, the game should start
    - (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch {
        [presentingViewController dismissModalViewControllerAnimated:YES];
        self.match = theMatch;
        match.delegate = self;
        if (!matchStarted && match.expectedPlayerCount == 0) {
            NSLog(@"Ready to start match!");
            [self lookupPlayers];
        }
    }
    
    #pragma mark GKMatchDelegate
    
    // The match received data sent from the player.
    - (void)match:(GKMatch *)theMatch didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
        if (match != theMatch) return;
    
        [delegate match:theMatch didReceiveData:data fromPlayer:playerID];
    }
    
    // The player state changed (eg. connected or disconnected)
    - (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
        if (match != theMatch) return;
    
        switch (state) {
            case GKPlayerStateConnected:
                // handle a new player connection.
                NSLog(@"Player connected!");
    
                if (!matchStarted && theMatch.expectedPlayerCount == 0) {
                    NSLog(@"Ready to start match!");
                    [self lookupPlayers];
                }
    
                break;
            case GKPlayerStateDisconnected:
                // a player just disconnected.
                NSLog(@"Player disconnected!");
                matchStarted = NO;
                [delegate matchEnded];
                break;
        }
    }
    
    // The match was unable to connect with the player due to an error.
    - (void)match:(GKMatch *)theMatch connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error {
    
        if (match != theMatch) return;
    
        NSLog(@"Failed to connect to player with error: %@", error.localizedDescription);
        matchStarted = NO;
        [delegate matchEnded];
    }
    
    // The match was unable to be established with any players due to an error.
    - (void)match:(GKMatch *)theMatch didFailWithError:(NSError *)error {
    
        if (match != theMatch) return;
    
        NSLog(@"Match failed with error: %@", error.localizedDescription);
        matchStarted = NO;
        [delegate matchEnded];
    }
    
    - (void)reportScore:(int64_t)score forCategory:(NSString *)category {
        // Only execute if OS supports Game Center & player is logged in
        if ([self isGameCenterAvailable] && [GKLocalPlayer localPlayer].authenticated == YES)
        {
            // Create score object
            GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];
    
            // Set the score value
            scoreReporter.value = score;
    
            // Try to send
            [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
                if (error != nil)
                {
                    // Handle reporting error here by adding object to a serializable array, to be sent again later
                    [unsentScores addObject:scoreReporter];
                }
            }];
        }
    }
    
    - (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent {
    
        if ([self isGameCenterAvailable] && [GKLocalPlayer localPlayer].authenticated == YES)
        {
            GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
            if (achievement)
            {
                achievement.percentComplete = percent;
                [achievement reportAchievementWithCompletionHandler:^(NSError *error)
                 {
                     if (error != nil)
                     {
                         // Retain the achievement object and try again later (not shown).
                     }
                 }];
            }
    
            return YES;
        }
    
        return NO;
    }
    
    
    @end
    

    最后,这就是我如何从我的游戏层调用游戏中心(我尝试了两种不同的选项,但没有一个可行)

    选项1

    [[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController: [[[UIApplication sharedApplication] keyWindow] rootViewController] delegate: self];
    

    选项2

    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
            UINavigationController *viewController = [app navController];
            [[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:viewController delegate:self];
    

    任何帮助将不胜感激。 提前致谢...


    我几个月来一直在处理多人游戏,邀请函对我来说是一个真正的问题......并且和你一样,我使用了Ray的教程来让我开始。 我今天意识到,Ray的代码有一个错误,如果两个客户端都有GKMatchmakerView,那么邀请将无法工作。 您需要在第一次收到邀请时按照以下方式解除邀请:

            [gcdelegate.viewController  dismissViewControllerAnimated:YES
                                     completion:^{
                                         GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:pendingInvite];
                                         mmvc.matchmakerDelegate = self;
                                         [gcdelegate.viewController presentModalViewController:mmvc animated:YES];
                                         self.pendingInvite = nil;
                                         self.pendingPlayersToInvite = nil;
                                         boo_invite=true;
                                     }];
    

    好吧,它似乎再次没有任何改变我们的代码或网络设置。 我打开了支持Apple支持,错误记录等的票据,而且似乎其中一些工作正常......

    现在我们知道这是Game Center沙箱中的一个bug。 据我所知,游戏中心的sanbox版本并不稳定,苹果公司的人们对这项服务没有给予足够的重视。 也无法检查互联网上的系统状态。

    我仍然继续与Apple支持商讨,以了解其原因,并在完成时将此处的所有对话分享给他人。

    快乐编码...

    链接地址: http://www.djcxy.com/p/68231.html

    上一篇: Cant receive game center invitations

    下一篇: Allow Authenticated IOS Game Center Users to Auto