Textures are an essential part of Unity Projects, and you need to be aware of Texture size and compression. On mobile and console, it is even more crucial to keep sizes low, due to the limited run-time memory and disk space. Choosing the correct compression is essential for getting Textures down to a good size to save memory bandwidth.
By automating the Asset audit process, you can avoid accidentally or unknowingly changing Asset settings. The AssetAuditor package on Github covers many aspects of the audit process. Not only does Asset Auditing help recover performance for Textures, but you can apply it to a multitude of Asset types in Unity as well. Read more about Asset Auditing in the Understanding Optimisation in Unity best practice guide.
Texture compression offers significant performance benefits when you apply it correctly. On newer mobile devices, you should favor ASTC compressed Texture formats. If ASTC is not available on your target devices, use ETC2 on Android and PVRTC on iOS.
Unity 4.3 onwards provides support for ASTC compression added by ARM. This is significantly beneficial at build time, because it allows Unity to compress ASTC faster than ETC2 or PVRTC. On iOS, ASTC is available on A8 chips and later; on Android, ASTC is available on most modern chipsets.
Mali GPUs (Mali T-760 MP8 and up) require ASTC compression over ETC2.
For more information, see the official ARM documentation in Section 4.2.3 ASTC Texture compression.
If the hardware does not support ASTC (for example, on Adreno GPUs) you must choose a fallback, such as ETC2. For additional information about ASTC, see the NVidia article Using ASTC Texture compression for Game Assets.
PVRTC was the main Texture compression format on iOS until Apple added ASTC. If you use PVRTC on Android, you should replace it with ETC2 if possible.
Note: The PVRTC Texture format on iOS and ETC format (Android 4.x devices) requires square Textures. When compressing a non-square Texture, two behaviors can occur:
If no Sprite uses the Texture and the compressed memory footprint is smaller than it would be if left uncompressed, Unity resizes the Texture based on the non-power-of-two (NPOT) Texture scale factor.
Otherwise, Unity does not resize the Texture, and marks it as uncompressed.
Unity uploads a Texture directly to the GPU after it finishes loading, and does not wait until the Texture becomes visible in the Camera frustum.
When a loading thread finishes loading Scenes or Assets, Unity needs to awaken them. Where and how loading happens depends on Unity version and the calls used to initialize the load.
If you load an Asset from AssetBundles, Resources, or Scenes, Unity goes from the preloading thread (disk I/O) to the graphics thread (GPU upload). If you use Unity 5.5 or later, and you enable Graphics Jobs, Unity goes from the preloading jobs directly to the GPU.
Unity awakes Assets on the main thread directly after awakening all Scene GameObjects. If you use AssetBundle.LoadAsset, Resources.Load or SceneManager.LoadScene to load Assets and Scenes, Unity blocks the main thread and wakes up all Assets. If you’re using the non-blocking versions of those calls (for example, AssetBundle.LoadAssetAsync), Unity uses time-slicing to wake the Assets up.
While loading several Textures at once, if either the upload rate is not fast enough or the main thread stalls, you can adjust Texture buffers. Changing the default values, though, can lead to high memory pressure. You can read more about memory restrictions in Texture buffers when using time-slice awake in the RingBuffer section of the Memory Management in Unity guide.
Note: If GPU memory overloads, the GPU unloads the least-recently-used Texture and forces the CPU to re-upload it the next time it enters the camera frustum.