Search code examples
ioscocos2d-iphonecrashinterstitial

Cocos2d on iOS: EXC_BAD_ACCESS in CCGraphicsBufferGLUnsynchronized when leaving app after ad


I have integrated the SKD of UnityAds into my game to show full screen interstitial video ads.

When the video is finished, a link to the AppStore is provided by the ad framework. When I select this link, the AppStore is opened. My app crashes in this moment, throwing EXC_BAD_ACCESS in CCGraphicsBufferGLUnsynchronized.

When starting my app, the UnityAds SDK is initialized like this:

[[UnityAds sharedInstance] startWithGameId:UNITYADS_MYAPP_ID
                                        andViewController:[CCDirector sharedDirector]
                ];

As you can see, I am passing [CCDirector sharedDirector] as the view controller. I am mentioning this, as this might by a part of the problem?

Later I am calling the UnityAds SDK from within a Cocos2D scene like this:

-(void)showFullscreenAd {
    //  Stop Cocos2D rendering
    [[CCDirector sharedDirector] pause];
    [[CCDirector sharedDirector] stopAnimation];

    //  Is an ad available?
    if ([[UnityAds sharedInstance] canShowAds]) {
        //  Display the ad
        [[UnityAds sharedInstance] setZone:@"rewardedVideoZone"];
        [[UnityAds sharedInstance] show];
    }
}

As you can see I am stopping Cocos2D rendering before displaying the add.

When I select the AppStore link in the add, my app crashes. This is the code Xcode points me to after the crash (in class CCGraphicsBufferGLUnsynchronized)

-(void)prepare
{
    _count = 0;

    GLenum target = (GLenum)_type;
    glBindBuffer(_type, _buffer);
 ==>    _ptr = _mapBufferRange(target, 0, (GLsizei)(_capacity*_elementSize), BUFFER_ACCESS_WRITE);
    glBindBuffer(target, 0);
    CC_CHECK_GL_ERROR_DEBUG();
}

Can someone point me into the right direction for debugging?

I am running my app on an iPad and iPhone under iOS 8.1.3


Solution

  • OK, I found a solution myself. Seems like the crash occurs because the app is in the background and rendering continues. So all I had to do was to make sure that rendering is not resumed after the app was moved to the background.

    I do it like this now:

    //  Added a flag to control resuming of rendering
    @property (readwrite) bool resumeRendering;
    
    
    [...]
    
    
    -(void)showFullscreenAd {
        //  Stop Cocos2D rendering
        [[CCDirector sharedDirector] pause];
        [[CCDirector sharedDirector] stopAnimation];
    
        // Set to resume redering by default
         _resumeRendering = YES;
    
        //  Is an ad available?
        if ([[UnityAds sharedInstance] canShowAds]) {
            //  Display the ad
            [[UnityAds sharedInstance] setZone:@"rewardedVideoZone"];
            [[UnityAds sharedInstance] show];
        }
    }
    
    
    [...]
    
    
    #pragma mark - UnityAdsDelegate
    
    //  This method is called when the interstitial ad is discarded
    //  check if rendering should be resumed
    -(void)unityAdsDidHide {
        if ( _resumeRendering ) {
            [[CCDirector sharedDirector] resume];
            [[CCDirector sharedDirector] startAnimation];
        }
    
        // do anything else here
        // In my case I transfer to the next scene
        [...]
    }
    
    -(void)unityAdsWillLeaveApplication {
       // Will leave application. Make sure rendering is not resumed anymore
        _resumeRendering = NO;
    }
    

    When the user clicks the AppStore link in the ad now, the method unityAdsWillLeaveApplication will be called and I can mark resumeRendering as false.

    Hope this helps other with the same problem.