Sprite kit SKTexture缓存和重用在SpriteKit中是如何工作的?

Sprite kit SKTexture缓存和重用在SpriteKit中是如何工作的?,sprite-kit,sktexture,sktextureatlas,Sprite Kit,Sktexture,Sktextureatlas,在StackOverflow上经常提到SpriteKit有自己的功能 内部缓存和重用 如果我不做任何努力重用纹理或地图集,什么是缓存 我可以从SpriteKit中获得重用行为吗?SpriteKit中的纹理缓存 -@learncoso2d 这是一个很长的故事,从iOS 9开始 纹理的大量图像数据没有直接保存在SKTexture 对象(见附件。) SKTexture延迟加载数据,直到必要时。创建一个 纹理,即使是从一个大的图像文件,是快速和消耗很少 记忆 纹理的数据通常在相应的 创建精灵

在StackOverflow上经常提到SpriteKit有自己的功能 内部缓存和重用

如果我不做任何努力重用纹理或地图集,什么是缓存 我可以从SpriteKit中获得重用行为吗?

SpriteKit中的纹理缓存 -@learncoso2d

这是一个很长的故事,从iOS 9开始

纹理的大量图像数据没有直接保存在
SKTexture
对象(见附件。)

  • SKTexture
    延迟加载数据,直到必要时。创建一个 纹理,即使是从一个大的图像文件,是快速和消耗很少 记忆

  • 纹理的数据通常在相应的 创建精灵节点。(或者,当需要数据时, 例如,当调用
    size
    方法时)

  • 纹理的数据已准备好在渲染过程中进行渲染(第一次) 渲染过程

SpriteKit有一些内置的缓存用于纹理庞大的图像 数据。两个特点:

  • SpriteKit会缓存纹理的大量图像数据,直到 SpriteKit感觉就像摆脱了它

    • 根据
      SKTexture
      类参考:“一旦SKTexture 对象已准备好进行渲染,它将一直保持准备状态,直到所有对象都变强 将删除对纹理对象的引用。“

    • 在当前的iOS中,它往往会停留更长的时间,甚至更长 在整个场景消失之后。引用一个苹果 技术支持:“iOS会释放用户缓存的内存 +TextureWithimageName:或+ImageName:当它认为合适时,例如 实例,当它检测到内存不足时。“

    • 在模拟器中,运行一个测试项目,我能够看到 纹理内存在
      从父对象中移除后立即回收。
      不过,在物理设备上运行时,内存似乎
      徘徊;重复渲染和取消分配纹理
      导致没有额外的磁盘访问

    • 我想知道:渲染内存是否可以在某些情况下提前释放 内存关键情况(当纹理保留但未保留时) 当前是否显示)

  • SpriteKit巧妙地重用缓存的海量图像数据

    • 在我的实验中,很难不重用它

    • 假设有一个纹理显示在精灵节点中,但是 与重用
      SKTexture
      对象相比,您可以调用
      [SKTexture]
      TextureWithimageName::
      用于相同的图像名称。质地 指针将与原始纹理不相同,但 将共享庞大的图像数据

    • 无论图像文件是地图集的一部分还是 不是

    • 无论原始纹理是否使用
      [SKTexture textureWithImageNamed::
      或使用
      [SKTextureAtlas]
      TextureName::

    • 另一个示例:假设您创建了纹理图集对象 使用
      [SKTextureAtlas atlasNamed::
      。你拿它的一个 使用
      textureNamed:
      创建纹理,并且不保留图集。 在精灵节点中显示纹理(因此纹理是 强烈保留在你的应用程序中),但你不必费心跟踪 缓存中的特定
      SKTexture
      。然后你做所有这些 再次:新纹理图集,新纹理,新节点。全部 这些对象将是新分配的,但它们是相对独立的 轻量的同时,重要的是:庞大的图像数据 最初加载的数据将在实例之间透明共享

    • 试试这个:你按名字加载一个怪物地图册,然后取一个 它的一个兽人纹理,并在兽人精灵节点中渲染。 然后,播放器返回主屏幕。你给兽人节点编码 在应用程序状态保存期间,然后在 应用程序状态恢复。(当它编码时,它不会 对其二进制数据进行编码;改为对其名称进行编码。)在 恢复应用程序,你创建另一个兽人(使用新地图册、纹理、, 和节点)。这个新的兽人会与地球共享庞大的兽人数据吗 解码兽人?对是的,会的

    • 这几乎是获得纹理而不是重复使用的唯一方法 纹理图像数据将使用
      [SKTexture]进行初始化
      纹理图像:
      。当然,也许UIImage会自己做 图像文件的内部缓存,但无论哪种方式,
      SKTexture
      负责数据,不会重用渲染数据 其他地方

    • 简言之:如果你有两个相同的精灵出现在你的房间里 同时,他们肯定在使用内存 效率高

  • 把这两点放在一起:SpriteKit有一个内置的缓存 保存重要的海量图像数据并灵活地重用

    换句话说,它只是起作用

    没有承诺。在运行测试应用程序的模拟器中,我可以很容易地证明 SpriteKit正在删除缓存中的纹理数据 真的结束了

    不过,在原型设计过程中,您可能会惊讶地发现 即使你从未重复使用过一个atlas或一个应用程序,你的应用程序也会表现良好 质地

    SpriteKit也有Atlas缓存 SpriteKit有一个专门用于纹理地图集的缓存机制。 它的工作原理如下:

    • 调用
      [SKTextureAtlas atlasNamed:
      加载纹理图集。 (如前所述,这还没有加载庞大的图像数据。)

    • 您在应用程序中的某个位置强烈保留了atlas

    • 稍后,如果使用相同的 atlas名称,返回的对象将与 保留地图集。使用
      textureNamed:
      ,指针也将相同。(更新: iOS10下的纹理不一定相同。)

    纹理对象,它应该是mentio
     All Heap
    & Anon VM
        (MiB)  Test
    ---------  ------------------------------------------------------
    
       106.67  baseline
       106.67  preload atlases but no nodes
    
       110.81  load A1
       110.81  load A1 and reuse in different two sprite nodes
       110.81  load A1 with retained atlas
       110.81  load A1,A1
       110.81  load A1,A1 with retained atlas
       110.81  load A1,A2
       110.81  load A1,A2 with retained atlas
       110.81  load A1 two different ways*
       110.81  load A1 two different ways* with retained atlas
       110.81  load A1 or A2 randomly on each tap
       110.81  load A1 or A2 randomly on each tap with retained atlas
    
       114.87  load A1,B1
       114.87  load A1,A2,B1,B2
       114.87  load A1,A2,B1,B2 with preload atlases
    
    * Load A1 two different ways: Once using [SKTexture
      textureWithImageNamed:] and once using [SKTextureAtlas
      textureNamed:].