Optimize game performance SpriteKit of 15 recommendations

This translation from 15 tips to optimize your SpriteKit game

SpriteKit is a fast, simple two-dimensional game framework by Apple's own media library support, direct access to the GPU.

But with the preparation of the game, you may find the frame rate began to decline, and so has the equipment for the iPad Pro 120Hz refresh rate of the display, efforts will need to update every frame time control within 8 milliseconds.

If you encounter a frame rate, an animation or the like unstable performance problem may be identified and solve the problem about 15 optimization method, and a small amount of code is a schematic.

Be careful when using a texture atlas

Texture Atlas plurality of individual resources placed in the same finished drawing, so that they can be loaded at the same time. Then, by rendering only a part of resources effectively rendering, which allows maintaining a texture spritekit active, and only the moving window drawn therefrom.

This has greatly improved the performance, because a large change state (unload a texture during rendering and load another texture) overhead. However, developers often all of the images will be added to a separate atlases, which is actually played the opposite effect, because according to their own Xcode fitting algorithm built into the resource atlases, and because it does not know the actual resources location of use, so you may find completely unrelated elves appear in the same atlases.

For example, the game has a level of 2 elf, another eight sprites, elves and a 52, they are focused on the same texture map. This means that Xcode must be two unrelated sprite loaded into memory to access the sprite it actually needs to be drawn, which is very inefficient.

Therefore, you should create multiple texture atlas to fit the actual content: for example, a centralized view of all animation a player, and all the other elves focus on specific world map.

As required preload textures

When I say to load textures will bring the cost of performance from your application package, you should not be surprised. If the image is small, it may be small, but if you try to load a full-screen background image, load time enough to exceed your budget - which can lead to dropped frames.

To solve this problem, it should be pre-loaded in the background texture, effectively pre-cached for immediate use when needed, so that the possibility of dropped frames will be reduced.

To understand how this works, it is important to understand SKtexture works with UIImage similar: data when you need to use it really is loaded. Thus, even for very large images, such code is almost instantaneous:

1
let texture = SKTexture(imageNamed: "Thrash")

However, once you put this texture node is assigned to a sprite in your game scene, it needs to be loaded in order to be drawn out. Ideally, we want to display the scene before (possibly during the loading screen) to load, to avoid the frame problem, so this should be pre-loaded:

1
2
3
texture.preload {
print("The texture is ready!")
}

Direction of the object

When you create a simple SpriteKit games, create artwork in any way easier to understand are meaningful.

In practice, this usually means that allows players spacecraft default on point, because many people think it's the direction it should be. However, SpriteKit has a different idea: For SpriteKit, the 90 degrees (3 o'clock) is the default orientation of the object, so in order to make a match, you will find yourself often add CGFloat.pi / 2 radians in the calculation.

When performance becomes more critical, we need to reconsider. We may think that is the default vertical upward direction of the object, but SpriteKit do not think so, and it continues to add additional algorithms to switch between the two objects, add unnecessary overhead.

So: make sure your resources toward the right direction, and for your game scene is a reasonable size.

Replacement, do not mix

Despite the need for all calculations, but to draw pixels on the screen (rendering the finished product) is still one of the slowest part of making games. This is because it is very complicated: Most elves have irregular shapes and transparency, we usually have to establish multiple layers in the scene, and joined to make vivid the object of complex effects.

A lot of this is inevitable, but you can make a simple change: If you draw sprites no transparency (that is, it is a physical form, such as background image), then you can tell SpriteKit not render it in time alpha blending, as follows:

yourSprite.blendMode = .replace

In practice, this means that by simply copying the pixels of the sprite to any existing content need not be read --SpriteKit draw up the existing color values, and then mixed with the new color values.

Remove a player can not see the node

SpriteKit may well automatically remove our game scene, something out of this screen will not be drawn. But they are still included in the calculation of physics, if not draw something, SpriteKit still continue to check if something visible.

Therefore, if something truly away from the screen and do not need the near future, it is best to call removeFromParent on it (). If desired, you can then add it back later, but at the same time, it will save some unnecessary additional calculated as SpriteKit.

Restrictions on the use and effects of crop nodes

Both node types way we allow other nodes custom drawing, which drawing or shear is applied Core Image filter. However, both the use of off-screen rendering buffer: content nodes need to be rendered to private frame buffer, and then copied back to the main scene. This extra transfer speed is very slow, so both types should be used with caution.

Although there is no way to reduce the cost of cutting the node (! Except avoid them as much as possible), the effect can be reduced by the cost of the node indicating the frame buffer buffer SpriteKit generated:

1
effectNode.shouldRasterize = true

Note: If the effect of changing the node, then the effect of grid node is a bad idea, because you often additional data stored in RAM, and then throw it away. On the other hand, if the effect node changes every few seconds or less only once, the rasterization is a good idea.

Pit particle system

Particle system with a relatively cheap, simple and impressive effects, but it is also very easy to get carried away - especially since you can click one hour in Xcode's built-in editor, without feeling the actual performance impact.

The problem is that Xcode particle editor can not simulate real-world game environments - your special function may be useful in the testing tool, but when they are presented may lower your frame rate.

The culprit was a special birth rate, expressed SpriteKit create velocity of the particles. If you set it to 500 or more, may look great, but it is very high computational cost - Try to use half of the value and use more particles, the individual particles take up more space.

Disabled brothers draw order

SKView has a Boolean property named ignoresSiblingOrder when it is set to false, have a serious impact on performance.

It refers to sequential drawing similar manner SpriteKit render node in the game scene. When considering it, SpriteKit Z depending on their position and their position as a child of the parent node to render nodes.

This is very slow and usually unnecessary, because we can use to control the Z position draw depth and eliminate extra sorting.

Annoying is that by default, ignoresSiblingOrder set to false, which means you will get slow draw behavior. If so, it can be added to any of the views in the controller provided inside the rendered scene is true:

1
yourSKView.ignoresSiblingOrder = true

ZPosition now ensure that node attributes used to control the drawing position thereof.

Using the GPU shader

Although you can use texture, cropping and effect nodes to create some interesting effects, but using fragment shader can do more, but they are also faster.

Fragment shader language is referred to as a dedicated small program written GLSL, which runs on each node in the pixel. They allow you to create incredible effects, such as water ripples, electrostatic noise, embossing, interlacing, etc., and modern computer design extremely efficient in dealing with them - modern GPU may have run concurrently 2000-4000 dedicated shader processor.

If you want to get an advanced shader effects library, written by the author and use all of these SpriteKit test, GitHub repository ShadeKit : ShaderKit There are 26 different shaders for trial, each shader has a comprehensive records, you can modify or create your own.

However, in order to obtain additional performance, there is need to do three things:

  1. While shaders can be loaded from a string, but preferably they are loaded from the package file shader. This is because even create shaders from two identical strings, SpriteKit will think they are different, and therefore can not share them.
  2. The same shaders assigned to a plurality of different nodes, much faster than doing so create a single shader.
  3. Try not to constantly adjust your clothes and property, as it may lead to SpriteKit recompile the shader code.

Choose wisely your physical body

SpriteKit provides us with a series of physical entities, we may be used to represent a node in space: circular, rectangular, composite shape, even a perfect collision detection pixel level. Each have their uses, but broadly speaking, you will select one of the three:

  1. Pixel-perfect collision detection is the most accurate, but also the most expensive. This should be used with caution, such as prepare for the players.
  2. Most of the time, rectangular collision detection and fast approaching, so it is a reasonable default choice.
  3. Round collision detection is by far the fastest of all the options, and about 3-4 times faster than the square. The disadvantage is that it is not suitable for most of the elves, but if you can use the circle, the best use of it.

You may find init (body :) initialization process helps to overcome particularly troublesome physical processes. Can be constructed from a composite of several other physical entities, such as three circles connected together and a rectangle.

Whatever you choose, unless you absolutely need to, do not enable usesPreciseCollisionDetection Boolean value. By default, SpriteKit every frame of the physical be evaluated to see if the collision occurred, but if you have a fast-moving small objects, you might miss collision, because a lot of movement between the two.

In this case, enable usesPreciseCollisionDetection is reasonable, because it uses an iterative detection algorithm - instead of the ball 100 moves directly to 150, it checks the movement between frames from to determine whether the collision. Since this process is very slow, so only use it when needed in particular.

Whenever possible, use a static physical body

We must evaluate each frame having a physical entity objects to see how they moved and whether they collide. If the properties of the physical body isDynamic set to false, the number of calculations performed will SpriteKit reduced, it will no longer applied to it in response to gravity, friction, force or pulse, and when it does not collide with another object is mobile.

Therefore, we should find those places instead of using a static body dynamic. Static body can still rebound wall as something else, they themselves will not move.

Careful selection bit mask

SpriteKit physical entity has three bit mask:

  1. Class bit mask determines what type of object it is, we can define up to 32 of them.
  2. Collision bit mask determines whether the object of this thing rebound in the physical world.
  3. Contact with the test bit mask determines the impact of our concern.

Distinguish between 2 and 3 will bring significant performance optimization, and also allows for additional functionality. For example, we might say that the power players and do not collide, but they did have contact, which means that players will not rebound when confronted with the power back, but we were told that the player touches it, so we can respond.

Similarly, we permit allowing the player and wall collision but no link between them, which means that players can not pass through walls, and we do not have the callback said players met the wall.

Therefore, to optimize the physics engine:

  • Reduce the number of content distribution in a collision bit mask, so SpriteKit must emulate less rebound.
  • Greatly reducing the number of content-contact test assignment bit mask, so SpriteKit will try to call our code infrequently.

And draw close attention node count

By default, SpriteKit will have in the lower right corner of the display screen on the current number of nodes, and the number of frames per second frame rate on most iOS devices reach 60fps, 120fps reached on ProMotion device.

However, if you experience performance problems, you can display another useful additional diagnostic value here: Draw count. To enable this feature, the controller will need to view showsDrawCount = true added to SKView configuration code, and then run the game again.

"Draw count" rendering of a game drawing required number of transfers. SpriteKit can not simultaneously draw all content, because there are a lot of layers, and so have a lot of effect. Therefore, it will draw in more scenes during the game. As I said above, cropping and effect nodes need to pass their own, because their private frame buffer, which means that they will have a peak performance.

After the drawing process is enabled, you can also be useful in other applications, the value of performance analysis: If the frame rate is highly volatile and is found to have 20 or more drawing process, giving priority to see if its value can drop.

Tip: One of the elves have a cut node will cost you twice the rendering process.

Add logic to prevent update () function

update () method (as well as other frame cycle events, such as didEvaluatelActions () and didSimulatePhysics ()) on most devices called once every 16ms, 8ms or call every once in a ProMotion device. This is a very short period of time, which means you need to limit the function of the function implemented.

So, you can re-take the initiative to check them, rather than take the initiative to check things? For example, instead of checking update () whether all enemies have been destroyed, but delete the last time retained a group of enemy activities and trigger functions. This change eliminates the costly from a branch operation time sensitive process.

Always test on your oldest hardware support

Different iOS devices running at breakneck speed, so the only way to ensure the game is fast enough to be tested on the oldest, slowest device deployment target support in iOS.

If you deploy the iPad, the device may be the oldest original iPad Air or iPad Air 2; on the iPhone it is likely that iPhone 5s or 6. Either way, if your game runs smoothly on those old equipment, there is no the new problem!

Additional information: The period in response to events separately

This game does not help performance, but it can help you better organize your game code. Often you see people dump a lot of features into their SKScene subclass, but not really necessary. Scene with delegate property may be automatically processed frame period event.

To try it, start by creating a new class in line with SKSceneDelegate, and then create an instance in the main view and assign it to delegate property. Now enter any event you want to delegate frame loop process:

1
2
3
4
5
update()
didEvaluateActions()
didSimulatePhysics()
didApplyConstraints()
didFinishUpdate()

This will make your code more intelligent simpler architecture

Original: Big Box  optimize game performance SpriteKit of 15 recommendations


Guess you like

Origin www.cnblogs.com/petewell/p/11615087.html