Кэширование текстуры с помощью CCTextureCacheTexture caching using CCTextureCache

В CocosSharp CCTextureCache класс предоставляет стандартный способ упорядочить, кэш и выгрузки содержимого. Это особенно полезно для больших игр, которые может не поместиться полностью в ОЗУ, упрощая процесс группирования и уничтожения текстур.CocosSharp’s CCTextureCache class provides a standard way to organize, cache, and unload content. It is especially useful for large games which may not fit entirely into RAM, simplifying the process of grouping and disposing of textures.

CCTextureCache Класс является важной частью процесса разработки игр CocosSharp.The CCTextureCache class is an essential part of CocosSharp game development. Большинство CocosSharp играми воспользуйтесь CCTextureCache объекта, даже если явно не столько методы CocosSharp используется внутренне общего текстуры кэша.Most CocosSharp games use the CCTextureCache object, even if not explicitly, as many CocosSharp methods internally use a shared texture cache.

В этом руководстве описывается CCTextureCache и почему это важно для разработки игр.This guide covers the CCTextureCache and why it is important for game development. В частности здесь рассматривается:Specifically it covers:

  • Почему текстуры кэширования: вопросы и ответыWhy texture caching matters
  • Время существования текстурыTexture lifespan
  • С помощью SharedTextureCacheUsing SharedTextureCache
  • Отложенная загрузка и предварительную загрузку с AddImageLazy loading vs. pre-loading with AddImage
  • Удаление текстурыDisposing textures

Почему текстуры кэширования: вопросы и ответыWhy texture caching matters

Кэширование текстуры — это важно учитывать при разработке игр, как загрузка текстуры является длительной операции и текстуры требуется значительный объем оперативной памяти во время выполнения.Texture caching is an important consideration in game development as texture loading is a time-consuming operation and textures require a significant amount of RAM at runtime.

Как и в случае с любой операции файл загрузки текстур с диска может быть дорогостоящей операцией.As with any file operation, loading textures from disk can be a costly operation. Загрузка текстуры может занять дополнительное время, если загружаемый файл требует обработки, например распаковать (как в случае для изображений png и jpg).Texture loading can take extra time if the file being loaded requires processing, such as being decompressed (as is the case for png and jpg images). Кэширование текстуры можно уменьшить количество раз, что приложение должно загрузить файлы с диска.Texture caching can reduce the number of times that the application must load files from disk.

Как упоминалось выше, также текстурами большой объем памяти для среды выполнения.As mentioned above, textures also occupy a large amount of runtime memory. Например фонового изображения, подобранные по разрешение iPhone 6 (1344 x 750) должны занимать 4 мегабайт в оперативной памяти, даже если PNG-файл имеет размер только несколько килобайт.For example a background image sized to the resolution of an iPhone 6 (1344x750) would occupy 4 megabytes of RAM – even if the PNG file is only few kilobytes in size. Кэширование текстуры предоставляет способ совместного использования текстуры ссылки внутри приложения, а также легко выгрузить все содержимое во время перехода между различными состояниями игр.Texture caching provides a way to share texture references within an app and also an easy way to unload all content when transitioning between different game states.

Время существования текстурыTexture lifespan

Текстуры CocosSharp может храниться в памяти для всей продолжительности выполнения приложения, или они могут быть ограниченный срок действия.CocosSharp textures may be kept in memory for the entire length of an app’s execution, or they may be short lived. Чтобы свести к минимуму памяти использования приложения следует освободить текстуры, ставшие ненужными.To minimize memory usage an app should dispose of textures when no longer needed. Само собой это означает, что текстуры может быть удален и повторно загружено на более позднее время, которое может увеличить время загрузки или вызвать снижение производительности во время загрузки.Of course, this means that textures may be disposed and re-loaded at a later time, which can increase load times or hurt performance during loads.

Текстуры загрузки часто требуется компромисс между временем использования и нагрузки памяти / производительность во время выполнения.Texture loading often requires a tradeoff between memory usage and load times/runtime performance. Игры, которые используют небольшой объем памяти текстуры можно хранить все текстуры в памяти, чем требуется, но игры большего размера может потребоваться выгрузить текстуры, чтобы освободить место.Games which use a small amount of texture memory can keep all textures in memory as needed, but larger games may need to unload textures to free up space.

В примере ниже показан простой игры, который загружает текстуры, при необходимости и сохраняет их в памяти для всей продолжительности выполнения:The following diagram shows a simple game which loads textures as needed and keeps them in memory for the entire length of execution:

Первые две полосы представляют текстур, которые нужны немедленно после выполнения игры.The first two bars represent textures which are needed immediately upon the game’s execution. Следующие три полосы представляют текстуры для каждого уровня, загрузится в требуемом объеме.The following three bars represent textures for each level, loaded as needed.

Если игра велико достаточно его со временем загружает достаточно текстуры, чтобы заполнить весь объем ОЗУ, предоставляемых устройства и операционной системы.If the game was large enough it would eventually load enough textures to fill all RAM provided by the device and OS. Чтобы решить эту проблему, игры может выгрузить данные текстуры, когда оно больше не нужно.To solve this, a game may unload texture data when it is no longer needed. Например в примере ниже показан игры, который выгружает Level1Texture, когда он больше не используется, а затем загружает Level2Texture для следующего уровня.For example, the following diagram shows a game which unloads Level1Texture when it is no longer needed, then loads Level2Texture for the next level. Конечным результатом является то, что только три текстуры, хранятся в памяти в любой момент времени:The end result is that only three textures are held in memory at any given time:

Приведенной выше схеме указывает, что использование памяти текстуры можно уменьшить путем выгрузки, а для этого может потребоваться время дополнительной загрузки, если игрок решает воспроизведения уровнем.The diagram shown above indicates that texture memory usage can be reduced by unloading, but this may require additional loading times if a player decides to replay a level. Также стоит отметить, что текстуры UITexture и MainCharacter загружаются и никогда не выгружается.It’s also worth noting that the UITexture and MainCharacter textures are loaded and never unloaded. Это означает, что эти текстуры требуются на всех уровнях, поэтому всегда хранятся в памяти.This implies that these textures are needed in all levels, so they are always kept in memory.

С помощью SharedTextureCacheUsing SharedTextureCache

CocosSharp автоматически кэширует текстуры, при загрузке их с помощью CCSprite конструктор.CocosSharp automatically caches textures when loading them through the CCSprite constructor. Например следующий код создает только один экземпляр текстуры:For example the following code only creates one texture instance:

for (int i = 0; i < 100; i++)
{
    CCSprite starSprite = new CCSprite ("star.png");
    starSprite.PositionX = i * 32;
    this.AddChild (starSprite);
} 

Автоматически кэширует CocosSharp star.png текстуры, чтобы избежать ресурсоемких вместо создания многочисленных идентичные CCTexture2D экземпляров.CocosSharp automatically caches the star.png texture to avoid the expensive alternative of creating numerous identical CCTexture2D instances. Это достигается путем AddImage вызываемой в общем CCTextureCache экземпляра, в частности CCTextureCache.SharedTextureCache.Shared.This is accomplished by AddImage being called on a shared CCTextureCache instance, specifically CCTextureCache.SharedTextureCache.Shared. Чтобы понять, каким образом SharedTextureCache используется взглянуть на следующий код, который функционально идентичен вызову CCSprite конструктор с параметром строки:To understand how the SharedTextureCache is used we can look at the following code which is functionally identical to calling the CCSprite constructor with a string parameter:


CCSprite starSprite = new CCSprite ();
 starSprite.Texture = CCTextureCache.SharedTextureCache.AddImage ("star.png");

AddImage проверяет, если аргумент файла (в данном случае star.png) уже загружен.AddImage checks if the argument file (in this case star.png) has already been loaded. Если Да, то возвращается кэшированный экземпляр.If so, then the cached instance is returned. Если затем не загружен из файловой системы, а также ссылку на текстура хранится внутренним образом для последующих AddImage вызовов.If not then it is loaded from the file system, and a reference to the texture is stored internally for subsequent AddImage calls. Другими словами star.png образ загружается только один раз, а последующие вызовы требуют нет доступа к дополнительный диск или память дополнительных текстур.In other words the star.png image is only loaded once, and subsequent calls require no additional disk access or additional texture memory.

Отложенная загрузка и предварительную загрузку с AddImageLazy loading vs. pre-loading with AddImage

AddImage позволяет коду для записи же запрошенную текстуру уже загружена ли или нет.AddImage allows code to be written the same whether the requested texture is already loaded or not. Это означает, что это содержимое не будет загружен, если она нужна; Тем не менее могут возникать проблемы с производительностью во время выполнения из-за непредсказуемым содержимое загрузки.This means that content will not be loaded until it is needed; however, this can also cause performance problems at runtime due to unpredictable content loading.

Например, рассмотрим игру, где можно обновить оружия игрока.For example consider a game where the player’s weapon can be upgraded. При обновлении оружия и снаряды визуально изменится, приводит к новой текстуры используется.When upgraded, the weapon and projectiles will visibly change, resulting in new textures being used. Если содержимое является отложенной загрузке затем текстуры, связанный с обновленной оружие не будет загружен изначально, а лишь через некоторое время, когда игрок получает обновления.If the content is lazy-loaded then the textures associated with upgraded weapons will not be loaded initially, but rather at a later time when the player acquires the upgrades.

Эта загрузка середины игровой процесс может привести к игру, чтобы pop, который является коротким, но заметно запрет на выполнение.This mid-gameplay loading can cause the game to pop, which is a short but noticeable freeze in execution. Чтобы избежать этого, код может предсказать, какие текстуры будет требоваться заранее и предварительно загрузить их.To prevent this, the code can predict which textures may be needed up front and pre-load them. Например ниже может использоваться для предварительной загрузки текстуры:For example, the following may be used to pre-load textures:

void PreLoadImages()
{
    var cache = CCTextureCache.SharedTextureCache;

    cache.AddImage ("powerup1.png");
    cache.AddImage ("powerup2.png");
    cache.AddImage ("powerup3.png");

    cache.AddImage ("enemy1.png");
    cache.AddImage ("enemy2.png");
    cache.AddImage ("enemy3.png");

    // pre-load any additional content here to 
    // prevent pops at runtime
} 

Эта предварительная загрузка может привести к потере памяти и может увеличить время запуска.This pre-loading can result in wasted memory and can increase startup time. Например, проигрыватель может получить фактически никогда не питания представленный powerup3.png текстуры, поэтому он будет загружаться без необходимости.For example, the player may never actually obtain a power-up represented by the powerup3.png texture, so it will be unnecessarily loaded. Само собой, это может быть затраты для оплаты во избежание потенциальных pop в игровой процесс, поэтому, как правило, лучше предварительной загрузки содержимого он помещается в оперативной памяти.Of course this may be a necessary cost to pay to avoid a potential pop in gameplay, so it’s usually best to preload content if it will fit in RAM.

Удаление текстурыDisposing textures

Если игры не требует больше памяти текстуры, чем доступно на устройстве минимальное спецификаций текстуры не обязательно должны быть удален.If a game does not require more texture memory than is available on the minimum spec device then textures do not need to be disposed. С другой стороны игры большего размера может потребоваться освободить память текстур, чтобы освободить место для нового содержимого.On the other hand, larger games may need to free up texture memory to make room for new content. Например, игра может использовать большой объем памяти, хранения текстур для среды.For example a game may use a large amount of memory storing textures for an environment. Среды используется только в определенном уровне затем оно должно ли быть выгружено при завершении уровень.If the environment is only used in a specific level then it should be unloaded when the level ends.

Удаление одной текстурыDisposing a single texture

Удалить одну текстуру, сначала необходимо вызова Dispose метод, а затем вручную удалить из CCTextureCache.Removing a single texture first requires calling the Dispose method, then manual removal from the CCTextureCache.

Ниже показано, как полностью удалить спрайт вместе с его текстуры фона:The following shows how to completely remove a background sprite along with its texture:

void DisposeBackground()
{
    // Assuming this is called from a CCLayer:
    this.RemoveChild (backgroundSprite);

    CCTextureCache.SharedTextureCache.RemoveTexture (backgroundsprite.Texture);

    backgroundSprite.Texture.Dispose ();
} 

Непосредственно disposing текстуры может быть эффективным, при работе с небольшим числом текстур, но это может стать ошибкам при работе с большими наборами текстуры.Directly disposing textures can be effective when dealing with a small number of textures but this can become error-prone when dealing with larger texture sets.

Текстуры могут быть сгруппированы в настраиваемый (без общего доступа) CCTextureCache экземпляров для упрощения очистки текстуры.Textures can be grouped into custom (non-shared) CCTextureCache instances to simplify texture cleanup.

Например, рассмотрим пример там, где содержимое предварительно загружается с помощью определенного уровня CCTextureCache экземпляра.For example, consider an example where content is preloaded using a level-specific CCTextureCache instance. CCTextureCache Экземпляр может быть определено в класс, определяющий уровень (который может быть CCLayer или CCScene):The CCTextureCache instance may be defined in the class defining the level (which may be a CCLayer or CCScene):

CCTextureCache levelTextures; 

levelTextures Экземпляр затем может использоваться для предварительной загрузки текстуры соответствующие уровню:The levelTextures instance can then be used to preload the level-specific textures:


void PreloadLevelTextures(CCApplication application)
{
    levelTextures = new CCTextureCache (application);

    levelTextures.AddImage ("Background.png");
    levelTextures.AddImage ("Foreground.png");
    levelTextures.AddImage ("Enemy1.png");
    levelTextures.AddImage ("Enemy2.png");
    levelTextures.AddImage ("Enemy3.png");

    levelTextures.AddImage ("Powerups.png");
    levelTextures.AddImage ("Particles.png");
} 

Наконец по окончании уровень текстуры может быть все удален за один раз через CCTextureCache:Finally when the level ends, the textures can be all disposed at once through the CCTextureCache:

void EndLevel()
{
    levelTextures.Dispose ();
    // Perform any other end-level cleanup
} 

Метод Dispose будет dispose всех внутренних текстур, очищая память, занятая эти текстуры.The Dispose method will dispose all internal textures, clearing out the memory used by these textures. Объединение CCTextureCache.Shared с уровня или игровой режим определенного CCTextureCache экземпляра приводит некоторые текстуры, сохранение через весь игры, а также некоторые выгружается, как завершить уровни, аналогичную схему, представленного в начале этого руководства:Combining CCTextureCache.Shared with a level or game mode-specific CCTextureCache instance results in some textures persisting through the entire game, and some being unloaded as levels end, similar to the diagram presented at the beginning of this guide:

СводкаSummary

В этом руководстве показано, как использовать CCTextureCache класс баланс производительности памяти использования и среды выполнения.This guide shows how to use the CCTextureCache class to balance memory usage and runtime performance. CCTexturCache.SharedTextureCache можно явно или неявно используется для загрузки и кэширования текстуры в течение жизненного цикла приложения, а CCTextureCache экземпляры можно использовать для выгрузки текстуры, чтобы сократить объем памяти.CCTexturCache.SharedTextureCache can be explicitly or implicitly used to load and cache textures for the life of the application, while CCTextureCache instances can be used to unload textures to reduce memory usage.