Preload a Scene to Prevent Lag

how to preload texture atlas to improve performance and reduce lagging? swift, spritekit

I'm not sure what imageLoad does, but here's one way to preload and reuse a texture.

Add the following code to your SKScene subclass

let ballTexture = SKTexture(imageNamed: "Ball")

Modify your addBall method to create your ball sprite from a texture by

func addBall() {
let ball = SKSpriteNode(texture: ballTexture)
...

I recommend you create a performSelector SKAction to add balls at fixed intervals instead of adding them in the update method.

Lastly, I suggest you move self.physicsWorld.contactDelegate = self and self.physicsWorld.speed = 1 from addBall to the didMoveToView method, so they aren't called repeatedly whenever you create balls.

Optimizing SKLabelNode to reduce performance issues

Try to preload SKLabelNode with all chars you need. Maybe, SpriteKit renders only required glyphs into texture.

// Preloaded model label (private property that is initialized in the class init method).
_modelLabel = [[SKLabelNode alloc] initWithFontNamed:_fontName];
_modelLabel.fontColor = _fontColor;
_modelLabel.fontSize = _fontSize;
_modelLabel.text = @"ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz0123456789-+=_()";

And then add your model into scene with minimal alpha (but no zero, because if node has 0 alpha, it will not drawn); Try to keep that node in scene

_modelLabel.alpha = CGFLOAT_MIN;
[self addChild:_modelLabel];

If not helps:

  • Organize nodes by aligning their zPosition (aka z-index). You should disable ignoresSiblingOrder for having control over zPosition.
    Make your all SKLabelNode be drawn at one z level.
  • Switch to bitmap fonts. Writing custom bitmap font renderer is super easy. The only thing you should remember - Make all glyphs be in only texture atlas, so you can draw your text in one draw call
  • Use native labels. I'm not sure, how much does it help. If you're having heavy FPS drops (~5..10FPS) This may help you

What causes the game to lag when I try to spawn instances after a collision?

The way the question was originally written, I would have suggested to use a particle system. However, with the code, I see you are trying to spawn projectiles that can cause damage…

Before going further, I should point you to the profiler, which might give you some insight in what is actually happening. You can enable the Debugger profiler from the bottom panel of the editor, on the profile tab. Once enabled start the game. The profiler will make graphs (you can select what to graph on the left) showing you what takes more time. You may also be interested on the graphs on the Monitors tab. Then you would reproduce the problematic situation, and see what is eating more time (you would looking for some graph suddenly rising around the time your code spawns the projectiles).

I don't know what it is for sure, but I can make some educated guesses and give you some advice on how to handle them.


One of the reasons you might lose frames is shaders loading and compiling.

You can diagnose this problem by checking if this only happens the first time you spawn your projectiles. For the second time the shaders would have already been loaded and compiled, so there would be no frames drops due to this.

That also tells you how to address this: have something with the shader loaded and visible beforehand. On a similar note, try to reuse your shaders.


Anyway, I don't think shaders is the problem. A more likely culprit is physics: When the projectile spawns, it intercepts the other areas, and the multiple projectiles intercept each other. You would address that with collision_layer and collision_mask.

In an ideal scenario, you would not even need this check at all:

if (area.name == "Player"):

Instead you would have the player on its own layer. And these Area2D have a mask that have only collide with that layer. That way Godot will not even check for collisions between the projectiles and something other than the player.


Something else that will ease the above issue is to spread the instantiations.

By the way, if the issue if that the projectile scene is just that heavy to instantiate, aside from trying to making it less heavy (smaller textures, simpler shapes, less expensive shaders…), you can also try spreading the instantiations.

The easiest way to do that is to insert this line in your loop:

yield(get_tree(), "idle_frame")

Or perhaps physics frame is better:

yield(get_tree(), "physics_frame")

This line will have the Godot halt execution until a frame (or physics frame) passes, then Godot resumes the execution of the code on the next line.


Similarly, if instantiating is expensive (or if the problem were a large number of instances being created, which does not seem to be the case), you could pool the instances.

This is probably not necessary in your case... Anyway, the idea is two fold:

  • Have your projectiles instanced in an array (the pool). So when you need them you only have to remove them form the array and add them to the scene. You would only instance more if the array is empty.
  • Similarly, don't queue_free them, instead remove them from the scene (with remove_child) and add them back to the array to be reused.

How do I pre-cache images for quick viewing with javascript?

You don't need to create any page elements, it can all be preloaded using JavaScript:

tempImg = new Image()
tempImg.src="pic2.jpg"

EDIT:

If you have a lot of images, you can use the poor-man's multi-preloader:

preloads = "red.gif,green.gif,blue.gif".split(",")
var tempImg = []

for(var x=0;x<preloads.length;x++) {
tempImg[x] = new Image()
tempImg[x].src = preloads[x]
}

First time setting a gameobject to active it lags

The accepted answer is a workaround, not a solution. Keeping hundreds of UI elements loaded is an utter waste of memory.

You should instead divide up your canvases, as written in this wonderful article by Unity. The reason for the lag is Unity's updating all canvas contents, even disabled objects, when you enable an object for the first time. To prevent unused objects from updating, isolate them in a different canvases. You can even put those canvases as children of your original canvas if you wish.



Related Topics



Leave a reply



Submit