Cocos2d和SpriteBatchNode:无法识别哪个sprite框架导致断言失败 [英] Cocos2d and SpriteBatchNode: cannot identify which sprite frame is causing an Assertion to fail

查看:468
本文介绍了Cocos2d和SpriteBatchNode:无法识别哪个sprite框架导致断言失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经问过类似的东西,但我无法弄清楚如何调试这个。这是问题



我添加了一些异常处理程序(捕获所有Objective-C)异常,这是我看到的结果:







问题是使用setTexture方法,它在断言时失败,验证需要显示的纹理名称是否与当前Sprite批处理节点中的纹理名称相同。

发生在尝试用另一个场景替换一个场景但不是所有的时间发生。它与新的场景有关,因为我试图通过调用替换从游戏的不同部分隔离的问题,它仍然给麻烦。



在游戏场景中,我有一些sprite工作表和sprite批处理节点,但由于我不能隔离一个sprite工作表id我不能理解哪个sprite帧给我的问题,以及我不明白为什么这个



我想:




  • 了解哪个sprite frame name给我AssertionFailure

  • 了解其所属的sprite表格



要了解这是否是命名问题,或者这是否与其他问题有关。



希望不要对这个问题太过愧疚。



编辑:我试过的答案,但我不能读取'fileName'信息,这里是调试器说总结不可用:





创建文件名属性:

  / ** TMP:解决文件名* / 
@property文件名;

- (id)initWithTexture:(CCTexture2D *)texture rectInPixels:(CGRect)rect rotate:(BOOL)rotate offset:(CGPoint)offset originalSize:(CGSize)originalSize
{
if((self = [super init]))
{
self.fileName = [NSString stringWithFormat:@GLUINT texture name:%i,texture.name];
self.texture = texture;
rectInPixels_ = rect;
rect_ = CC_RECT_PIXELS_TO_POINTS(rect);
offsetInPixels_ = offset;
offset_ = CC_POINT_PIXELS_TO_POINTS(offsetInPixels_);
originalSizeInPixels_ = originalSize;
originalSize_ = CC_SIZE_PIXELS_TO_POINTS(originalSizeInPixels_);
rotated_ = rotate;
}
return self;
}

- (id)initWithTextureFilename:(NSString *)filename rectInPixels:(CGRect)rect rotate:(BOOL)rotate offset:(CGPoint)offset originalSize:(CGSize)originalSize
{
if((self = [super init]))
{
self.fileName = fileName; // TMP
texture_ = nil;
textureFilename_ = [filename copy];
rectInPixels_ = rect;
rect_ = CC_RECT_PIXELS_TO_POINTS(rect);
offsetInPixels_ = offset
offset_ = CC_POINT_PIXELS_TO_POINTS(offsetInPixels_);
originalSizeInPixels_ = originalSize;
originalSize_ = CC_SIZE_PIXELS_TO_POINTS(originalSizeInPixels_);
rotated_ = rotate;
}
return self;
}


解决方案

朋友。每次你创建一个CCAnimate动作(或CCAnimation),你应该记录如下:

  sprite frame names'loop 
NSLog(@为CCAnimate添加精灵帧名称:%@,spriteFrameName);

//创建CCAnimate之后
NSLog(@使用sprite框架创建CCAnimate%@:%@,animate,arrayOfSpriteFrames);
/ pre>

你可能想要添加更多的细节,像添加到CCAnimate的精灵帧名称。如果缓存CCAnimations和



现在当你收到这个错误,你应该选择 [CCSprite setDisplayFrame:] 方法,然后调试器将显示它想要设置的CCSpriteFrame的值。查找指针值,它将读取 0x254fb22e



在日志中搜索该值,这将带你回到创建CCAnimate ..日志。从上面的日志行因为你还记录了'arrayOfSpriteFrames',你可以得到他们的指针值,与引起断言的CCSpriteFrame的指针值进行比较。



当你有一个匹配,它是精灵帧数组中的第四个项目,只需查找添加到CCAnimate的第四个精灵帧名称。



可能是一个更快的方式来做这个取决于哪些信息在调试器中可用(以及你在调试中有多么精通),但这是一种方法,肯定会导致你在相对较短的时间内违规的精灵帧名称。 / p>

请注意,指针值不是唯一的 - 可能使用相同的指针值创建了一个不同的CCAnimate。特别地,如果存在CCAnimate播放和停止的高频率,则可能发生另一CCAnimate被分配在前一个CCAnimate的完全相同的存储器位置。所以要小心,如果结果似乎不匹配。快速找出的方法是在不同的设备或模拟器与设备上测试,因为指针值和分配策略不同。



您不需要记录哪个sprite框架名称属于哪个纹理图集。只需打开每个地图集的plist并搜索精灵帧名称。

提示:此问题的常见原因可能是在两个不同的纹理地图中有相同的精灵帧名称 -



另一个提示:如果日志看起来令人生畏,我可以使用任何一个纹理只需执行以下操作:




  • 为CCSpriteFrame类打开源代码

  • 添加一个NSString *每次创建CCSpriteFrame对象时,将文件名分配给CCSpriteFrame



现在每当你在调试器中看到CCSpriteFrame时,它会在调试器视图中显示相关的文件名。


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) exceptions and that's the result of what I see:

The problem is with the setTexture method and it fails at the assertion verifying whether the texture name that needs to be displayed is the same as the one in the current sprite batch node.

This happens when trying to replace one scene with another but doesn't happen all the times. It has to do with the new scene as I tried to "isolate" the problem by calling the replace from a different part of the game and it still does give trouble.

In the game scene I have a couple of sprite sheets and sprite batch nodes but as I don't manage to isolate a sprite sheet id I cannot understand which sprite frame is giving me the problem, as well as I don't understand why this happens only sometimes.

I would like to:

  • understand which sprite frame name gives me the AssertionFailure
  • understand to which sprite sheet it belongs

This should help me to understand if it is a naming problem or if this has to do with something else.

Hoping not to be too lame with this question..

EDIT: I tried the answer but I am not able to read the 'fileName' information, here is what the debugger says "Summary unavailable":

That's how I create the filename property:

/** TMP: Bug solving filename */
@property (copy) NSString *fileName;

-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
{
    if( (self=[super init]) )
    {
        self.fileName = [NSString stringWithFormat:@"GLUINT texture name: %i", texture.name];
        self.texture = texture;
        rectInPixels_ = rect;
        rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
        offsetInPixels_ = offset;
        offset_ = CC_POINT_PIXELS_TO_POINTS( offsetInPixels_ );
        originalSizeInPixels_ = originalSize;
        originalSize_ = CC_SIZE_PIXELS_TO_POINTS( originalSizeInPixels_ );
        rotated_ = rotated;
    }
    return self;
}

-(id) initWithTextureFilename:(NSString *)filename rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize
{
    if( (self=[super init]) )
    {
        self.fileName = fileName; //TMP
        texture_ = nil;
        textureFilename_ = [filename copy];
        rectInPixels_ = rect;
        rect_ = CC_RECT_PIXELS_TO_POINTS( rect );
        offsetInPixels_ = offset;
        offset_ = CC_POINT_PIXELS_TO_POINTS( offsetInPixels_ );
        originalSizeInPixels_ = originalSize;
        originalSize_ = CC_SIZE_PIXELS_TO_POINTS( originalSizeInPixels_ );
        rotated_ = rotated;
    }
    return self;
}

解决方案

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.

这篇关于Cocos2d和SpriteBatchNode:无法识别哪个sprite框架导致断言失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆