Cocos2d and SpriteBatchNode: cannot identify which sprite frame is causing an Assertion to fail

前端 未结 2 1711
盖世英雄少女心
盖世英雄少女心 2021-01-24 02:54

I have already asked something similar but I can\'t figure out properly how to debug this. That\'s the question.

I added some Exceptions handler (catches all Objective-C

2条回答
  •  无人及你
    2021-01-24 03:46

    In such cases logging is your friend. Every time you create a CCAnimate action (or CCAnimation) you should log something like this:

    // during 'create sprite frames from sprite frame names' loop
    NSLog(@"adding sprite frame name for CCAnimate: %@", spriteFrameName);
    
    // after CCAnimate was created
    NSLog(@"creating CCAnimate %@ with sprite frames: %@, animate, arrayOfSpriteFrames);
    

    You will probably want to add more detail, like which sprite frame names were added to that CCAnimate. You may also have to add additional logging if you cache CCAnimations and reuse them later (log each CCAnimation when reused).

    Now when you receive that error you should select the [CCSprite setDisplayFrame:] method in the call stack. The debugger will then show you the value for the CCSpriteFrame it wants to set. Look for the pointer value, it will read something like 0x254fb22e.

    Search for that value in your log, this will bring you back to one of the "creating CCAnimate.." logs. From the log lines above you can see the sprite frame names it contains. Since you also logged the 'arrayOfSpriteFrames' you can get their pointer value, compare it with the pointer value of the CCSpriteFrame that caused the assertion.

    When you have a match, and it's the fourth item in the sprite frame array, just look up the name of the fourth sprite frame name added to the CCAnimate.

    There may be a quicker way to do this depending on which information is available in the debugger (and how well versed you are in debugging), but this is one approach that will definitely lead you to the offending sprite frame name in relatively short time.

    Note that the pointer values are not unique - it's possible that a different CCAnimate was created with the same pointer value. Especially if there's a high frequence of CCAnimate playing and stopping it can happen that another CCAnimate is allocated at the exact same memory location of a previous one. So be wary if the results don't seem to match up. A quick way to find out is to test on different devices or Simulator vs. Device, as pointer values and allocation strategies vary.

    You don't need to log which sprite frame name belongs to which texture atlas. Simply open the plist of each atlas and search for the sprite frame name. The plist is an XML file.

    Tip: common cause for this problem can be having the same sprite frame name in two different texture atlases - cocos2d may use either texture when you request a sprite frame with a duplicate name.

    Another Tip: if the logging seems daunting, I'd simply do the following:

    • open source code for CCSpriteFrame class
    • add a NSString* property 'filename' with 'copy' attribute
    • every time you create a CCSpriteFrame object, assign the filename to the CCSpriteFrame

    Now whenever you see a CCSpriteFrame in the debugger, it'll show you the associated filename in the debugger view.

提交回复
热议问题