Cocos2d 和 SpriteBatchNode:无法识别是哪个精灵帧导致 Assertion 失败 [英] Cocos2d and SpriteBatchNode: cannot identify which sprite frame is causing an Assertion to fail

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

问题描述

我已经问过类似的问题,但我不知道如何正确调试它.这就是 问题.

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

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

I added some Exceptions handler (catches all Objective-C) exceptions and that's the result of what I see:

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

当试图用另一个场景替换一个场景时会发生这种情况,但并非总是发生.它与新场景有关,因为我试图通过从游戏的不同部分调用替换来隔离"问题,但它仍然会带来麻烦.

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.

在游戏场景中,我有几个精灵表和精灵批处理节点,但由于我无法隔离精灵表 ID,我无法理解哪个精灵帧给我带来了问题,我也不知道理解为什么这种情况只是偶尔发生.

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.

我想:

  • 了解哪个 sprite 框架名称为我提供了 AssertionFailure
  • 了解它属于哪个精灵表

这应该有助于我了解这是命名问题还是与其他问题有关.

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..

我尝试了答案,但我无法读取文件名"信息,这是调试器所说的摘要不可用":

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;
}

推荐答案

在这种情况下,日志记录是您的朋友.每次创建 CCAnimate 动作(或 CCAnimation)时,都应该记录如下内容:

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);

您可能想要添加更多细节,例如向 CCAnimate 添加了哪些精灵帧名称.如果您缓存 CCAnimation 并在以后重用它们(在重用时记录每个 CCAnimation),您可能还需要添加额外的日志记录.

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).

现在,当您收到该错误时,您应该在调用堆栈中选择 [CCSprite setDisplayFrame:] 方法.然后调试器将显示它想要设置的 CCSpriteFrame 的值.查找指针值,它会读取类似 0x254fb22e 的内容.

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.

在您的日志中搜索该值,这将带您回到正在创建 CCAnimate.."日志之一.从上面的日志行中,您可以看到它包含的精灵帧名称.由于您还记录了arrayOfSpriteFrames",因此您可以获得它们的指针值,将其与导致断言的 CCSpriteFrame 的指针值进行比较.

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.

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

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.

根据调试器中可用的信息(以及您对调试的熟练程度),可能有一种更快的方法来执行此操作,但这是一种方法,肯定会导致您在相对的情况下找到有问题的 sprite 帧名称时间短.

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.

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

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.

您不需要记录哪个精灵帧名称属于哪个纹理图集.只需打开每个图集的 plist 并搜索精灵帧名称.plist 是一个 XML 文件.

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.

提示:此问题的常见原因可能是在两个不同的纹理图集中具有相同的精灵帧名称 - 当您请求具有重复名称的精灵帧时,cocos2d 可能会使用任一纹理.

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:

  • CCSpriteFrame 类的开源代码
  • 添加一个带有 'copy' 属性的 NSString* 属性 'filename'
  • 每次创建 CCSpriteFrame 对象时,将文件名分配给 CCSpriteFrame

现在,只要您在调试器中看到 CCSpriteFrame,它就会在调试器视图中显示关联的文件名.

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

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

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