Cocos trial loading speed optimization

Publish Time:2024-12-01

Cocos Performance Optimization

Cocos startup can be divided into 5 phases: Cocos engine loading, Cocos engine running, Cocos static resource loading, Cocos scene running, and Cocos dynamic resource loading.


image.png


Since Cocos engine loading and running cannot be controlled by the business side, black screen time optimization is left with Cocos static resource loading. There are two approaches for static resource loading: resource compression and resource caching (disk, memory).

1. Resource Compression

Resource compression mainly focuses on compressing image resources. Tinify supports online compression of PNG and JPG format images, generally reducing size by 75% without noticeable visual differences - highly recommended.

If some level of distortion is acceptable, PNG and JPG images can also be compressed in the Cocos Creator editor. Choose PNG for PNG format images and JPG for JPG format, then adjust image quality - lower quality means smaller size but more distortion.


image.png

2. Resource Caching

Resource caching includes disk caching and memory caching.

For native platforms, resources are stored locally. For Web platforms, resources can be cached on disk through HTTP caching or PWA.

Resources can also be cached in memory. Generally, games have multiple scenes, like different levels. If a scene won't be re-entered, its resources don't need caching. For scenes that will be revisited, caching can speed up subsequent loading.

Generally, disk storage space is large, so disk caching isn't problematic. However, memory is precious - caching everything can lead to high memory usage and potential memory leaks, so usually only resident resources are cached.

3. CPU Optimization

3.1 Using Texture Atlas

Games require extensive calculations and rendering, which is CPU-intensive. CPU optimization is crucial - high CPU load can cause device overheating, reduced frame rates, or crashes. CPU handles instruction parsing and execution, so high load mainly comes from too many instructions, especially time-consuming ones. In games, this primarily means drawcall instructions. For drawcall optimization, fewer calls are better. The most effective way is batch processing through texture atlases - combining textures into one large atlas for single-pass rendering, reducing content switch loading time.

3.2 Font Rendering Optimization

Fonts have two implementation methods: bitmap fonts and FreeType fonts.

Bitmap fonts render all characters into one image - simple and efficient as characters are pre-rendered. The downside is large memory usage for large character sets (like Chinese characters) and inflexibility with fixed resolution causing aliasing on high-DPI screens.

FreeType fonts (like TTF) define font rendering data rather than pixels, calculating and rendering at runtime. This avoids scaling issues but requires computation, usually optimized through caching.

For cases with only numbers and letters and many frequently changing text nodes, bitmap fonts can effectively reduce drawcalls from text rendering.

3.3 Node Creation and Destruction Optimization

Node creation and destruction is performance-intensive, so avoid frequent operations and minimize node count. For numerous repetitive objects like enemies or bullets, use object pooling - cache used nodes instead of destroying them, allowing reuse without recreation.

Collision detection is also performance-intensive. Prefer box or circle colliders over polygon colliders.

4. Memory Optimization

Resource caching, especially images, consumes significant memory. Resources include static (loaded immediately on scene entry) and dynamic (loaded asynchronously like network images/audio via cc.loader.load or cc.loader.loadRes).

Memory reduction has two approaches: reducing unnecessary resources and resource compression.

Reducing Unnecessary Resources

Example: For different background images on mobile vs PC, dynamically load platform-specific resources rather than including both and controlling visibility.

For backgrounds, if simple colors or patterns suffice, implement programmatically instead of using large design assets.

When creating texture atlases, only combine related images to avoid loading entire atlases for single sprites.

Resource compression mainly means texture compression.

Simple size compression tools like Tinify only reduce disk storage, not memory usage. Use 2x or 1x resolution for lower-resolution requirements.

Reducing Memory Footprint

Texture compression algorithms (Etc1, Etc2, PVRTC) optimize memory usage. While JPG/PNG compress data, GPU can't read them directly - CPU must decode first. Compressed textures can be rendered directly by GPU, optimizing both memory and CPU usage.

Note that texture compression is usually lossy with adjustable compression rates. Different platforms require different algorithms based on GPU support.

Unused memory should be released to prevent leaks, either automatically or manually. Static resources can be auto-released by enabling scene auto-release:


image.png


This releases static resources on scene changes.

For earlier release, use cc.assetManager.releaseAsset manually.

Note that dynamically loaded resources aren't auto-released with scene changes - use cc.setAutoReleaseRecursively:


image.png


This enables auto-release of dynamic resources on scene changes. Alternatively, use cc.loader.releaseRes for manual release.