Weird nosense CCSpriteBatchNode Exception - ios

There is something weird going on in my cocos2d game I can't figure out the problem.
I have a very simple files structure for my game, 1 intro layer, 1 main menu layer, 1 game layer.
While I was developing I skiped the menu layer in order for the game jump from intro layer to save time.
Now I finished the game, I added back the main menu and when game layer is called from it it crashes!!??
it never crashes if I skip the main menu layer.
Edit:
Important, If I have remove the main menu layer it works just fine... main menu doesn't add any texture atlas, there is only one I am using entire the whole game.
this is the message error:
"CCSprite: Batched sprites should use the same texture as the batchnode"
from this gamelayer code:
_myitens = [CCSpriteBatchNode batchNodeWithFile:#"mytextureatlas.png";
The funny thing is Main menu Layer only feature is to have a button(image from file and not texture atlas) that calls the game layer....
it is very confusing I can't see how to approach this issue
any tips are valid thanks

One of the more common causes, and in particular if the problem depends on which scene you load first, occurs when you have the same image in two atlases.
For instance, assuming you have mytextureatlas.plist and notmytextureatlas.plist and both contain an image with the same name, say "player.png". If you first load mytextureatlas all seems fine. However when you load notmytextureatlas first, and later try to add a player.png sprite to the batch node using mytextureatlas, cocos2d will actually use the player.png from notmytextureatlas, provoking this error.
Double-check that all image names across all texture atlases are unique.

How are you adding sprites to _myitems? You are adding children which have been created with a different texture, that's the meaning of the error and that's what happening.
The exception is not non-sense, it means a precise condition which somewhere you fail to obey: a batchnode must have children initialized with the same texture of the batchnode itself (and it makes sense, since it's used to batch GL calls).
For example:
_myitems = [CCSpriteBatchNode batchNodeWithFile:#"mytextureatlas.png"];
[_myitems addChild:[CCSprite spriteWithTexture:#"othertexture.png"]];
Will generate the error. You should try with:
[_myitems addChild:[CCSprite spriteWithTexture:_myitems.textureAtlas.texture]];

Related

Changing SCNNode scale has no effect

I'm new to ARKit and SceneKit. I have a rather complex scene coming from an 3D artist. He replaced some items with SceneKit objects. I now try to change the properties of one of the SCNNodes, in this case the scale property, in another case the position in space, and in yet another I have a SCNText where I change the string property:
feedScaler?.scale = SCNVector3Make(1.0, scale, 1.0)
feedText?.string = String(feedValue)
feedIndicator?.position.y = someNewValue
So, pretty straight forward. When I run the scene though, it seems that the changes here are only commited once, before the scene appears. Then nothing happens. Here's the thing:
the method which updates the properties runs once per frame
I print out the property values of the nodes to the console and they update each frame
the text updates, too, and is the only update which is actually rendered and visible.
Note: There's also animations in that scene that do not play unless I uncheck "Use scene time base". Maybe that is a hint regarding how the Scene's animations are handled...
I found the issue. I used a clone of the scene which caused the references to get lost. The documentation says:
Cloning or copying a node creates a duplicate of the node object, but not the geometries, lights, cameras, and other SceneKit objects attached to it—instead, each copied node shares references to these objects.
When the original gets lost all the references get useless.

SpriteKit Load Texture First Time Lag Even With Preloading

Here is my problem: Despite doing these:
1) Preloading all of my texture atlases
2) Having my atlases stored in Singletons so they are not disposed of by ARC
3) Having all my animation arrays stored in Singleton
SpriteKit STILL has a short "lag jitter" when adding enemies to my scene ONLY the first time they are added. After the texture is drawn once, it never lags again when that texture is added to the scene. Memory can be seen going up when the textures are drawn on the screen finally, which looks like they aren't getting preloaded.
I am currently preloading ALL of my texture atlases in my AppDelegate on startup using...
SKTextureAtlas.preloadTextureAtlases(primaryAtlas, withCompletionHandler: { () -> Void in
})
primaryAtlas is an array of all 4 of my atlases which are stored in a Singleton.
Let me point out some things I have already tried and what my current setup is.
1) The array of frames for my animations are stored in Singletons and get their images from the Atlases which are in a different singleton. They used to be in the same Singleton.
2) I've tried storing ALL my textures in a Singleton which were all loaded from the atlases. But currently my animations are stored, while my single textures are functions that fetch that texture from the atlases.
3) I've turned off all animations for enemies (don't run the SKAction) and the jitter still happens when they're added and not animating.
I've been trying to fix this for a very long time and there honestly doesn't seem to be a solution.
There seems to be a similar StackOverflow question I found here with no answer: Spritekit: First texture draw slow (preloaded)
Here is a picture of some analysis I did with Instruments.
Make sure that your texture atlases are used as singleton class properties, because if you create variables of texture atlases inside method scope which do preloading, they will be deallocated after method returns

SceneKit - Adding a new SCNNode to the scene causes severe lag

I found out that adding SCNNodes (with SCNGeometry) to the scene causes a severe lag spike.
According to the Time Profiler it has to generate the geometry (at least the functions/methods are called like that). It does that at the time when the node is added to the scene, not when the node is created. Hence, creating a pool with SCNNodes will not work.
Is there a way to get rid of this lag? I'd like to be able to add nodes to the scene without any FPS drop.
The only idea I have so far is adding everything to the scene already and then hiding / un-hiding it, though this is not really a clean solution.
Here's a shot from Time Profiler:
looks like your are adding a node with an SCNShape or SCNText attached to it and these kinds of geometries are expensive to create (you have to discretize and triangulate the Bézier curve, and eventually have to compute and offset curve for the chamfer).
You can try to preload the following methods from SCNSceneRenderer : -prepareObject:shouldAbortBlock:, -prepareObjects:withCompletionHandler:

how to fix occasional stutter in my game?

The context:
In my SKScene I have:
1) a few sprites with no physics controlled by touch using touchesMoved: which instantly changes sprite position property based on touch location,
2) one sprite that while colliding with the others changes its physicsBody.velocity instantly.
That's all - no other fancy processing.
The issue:
I found occasional and random stuttering all of the sprites independently without any FPS dropping.
The questions:
In the context of my performance issue:
1) Is there any reason to update sprite position or velocity in update: method rather than update them instantly?
2) Is there any sense to use SKAction rather than changing directly position or velocity property?
3) If 2 then can make any difference running SKActions instantly or run them in update: method?
Apple says about
update:
method:
This is the primary place to implement your own in-game simulation, including input handling, artificial intelligence, game scripting, and other similar game logic. Often, you use this method to make changes to nodes or to run actions on nodes.
but nothing more like "must,..." or "should, because...".
4) Isn't SpriteKit done like all the changes made to the nodes instantly are processed in respective loop update phase or do I have always go to the appropriate loop method to make/fire changes there to avoid any rendering performance loss or interference?

SKPhysicsWorld bodyWithTexture not working well with complex shapes

Am I the only one whose having issues with the new bodyWithTexture function of SKPhysicsBody?
I'm new to iOS development and maybe it's me, but I'm trying to create a game where I need to detect if a ball is inside a path.
I'm loading both from images dynamically (as the level proceeds the paths are more and more complex), and I'm setting a physics body to both the ball (bodyWithCircle) and from the dynamic path which is a PNG file of a path and all the rest is transparent background. I'm using the new bodyWithTexture function (yes I know it's supported only under iOS 8), and after assigning bit masks I've defined a contact between the ball and path and am informed with begin/end contact.
SKSpriteNode *lvlPath = [SKSpriteNode spriteNodeWithImageNamed:currentLevel.imagePath];
lvlPath.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
lvlPath.physicsBody = [SKPhysicsBody bodyWithTexture:lvlPath.texture size:lvlPath.frame.size];
now for simple paths like straight line, it works great. once it comes to complicated paths - the mechanism is going crazy, at least in my simluator (running iOS 8).
i've created another simple app just to check this issue, and saw that it's going crazy when the path is a complex shape. when the ball enters the path in one direction it seems to be working (begin/end contact), but going the reverse direction suddenly acts weird when still inside the path it reports to have ended contact, and then like randomly flips begin/end contact.
help... since the levels are loaded dynamically, this is a really cool feature for me, saving me the definitions of all levels as CGPathRef and creating a polygon for each level (and perhaps device).
thanks all,
Eyal
edit
example screenshot:
https://www.dropbox.com/s/e8v9g1kajtvakfq/screenshot%20bodywithtexture.jpg?dl=0
in this example the ball with the arrow is inited using bodyWithCircle, and the C shaped object is inited using bodyWithTexture. I'm debug printing "didBeginContact" and "didEndContact" and it freaks out in the top line there, you can see it's with "didEndContact" while the two object are definitely at contact. If I jiggle it (I'm moving it with the cursor) it suddenly flips to "didBeginContact".
With Simpler objects (like horizontal/vertical lines with round corners) it works perfectly.

Resources