SpriteKit 内存泄漏更改包含 SKTileMapNodes 的场景

2023-12-26

我正在尝试使用 Swift、SpriteKit 和 SKTileMaps 创建一个简单的 2d 平台游戏。但每次我在包含 SKTileMaps 的场景之间切换时,我都会在 Xcode Instruments 中看到大量内存泄漏。

我已经尽可能简单地重现了这个问题。我使用 .sks 文件来创建场景,该文件仅包含 1 个填充了一些图块的tileMap。

视图控制器中用于呈现场景的代码:

if let view = self.view as! SKView? {
        let scene = LoadingScene(size: CGSize(width: 2048, height: 1536))
        scene.scaleMode = .aspectFill
        view.presentScene(scene)

场景代码:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let scene = GameScene(fileNamed: "WorldScene") else{fatalError("Could not open world scene")}
        view?.presentScene(scene)
    }
}

我选择 GameScene 作为 .sks 场景文件中的自定义类。

每次我改变场景时,这都会导致很多小的内存泄漏:

Instruments 中内存泄漏的图片 https://i.stack.imgur.com/b3BGl.png

这是仅一个场景变化造成的泄漏。是我做错了什么还是这是一个 SpriteKit 错误?

Edit1

每次加载瓦片地图时都会发生 SKCTileMapNode::_ensureChunkForTileIndex(unsigned int) 泄漏,而其余的仅在更改场景时出现

Edit2

更改了 GameViewController 以跳过 LoadingScene 并直接进入 GameScene。内存泄漏仍然存在:

if let view = self.view as! SKView? {
    guard let scene = GameScene(fileNamed: "WorldScene") else{fatalError("Could not open world scene")}
    scene.scaleMode = .aspectFill
    view.presentScene(scene)
}

我也遇到过同样的问题,经过研究后,我相信这是所有 SKTileMapNode 固有的问题。这是 SpriteKit 中的一个错误。

当您使用填充了任何图块(不是空白图块地图)的 SKTileMapNode 时,即使加载后续场景,图块地图的内存也将保留。如果您继续使用 SKTileMapNodes 加载关卡,那么内存将不断增加,直到游戏最终崩溃。我已经用我编写的不同游戏以及使用其他人的代码对此进行了测试。

有趣的是,如果图块地图具有所有空白图块(即使它分配了 SKTileSet),则不会发生内存泄漏。

据我猜测,当 SKTileMapNode 中除了空白图块之外还有任何图块时,它正在使用的整个 SKTileSet 都会保存在内存中并且永远不会被删除。

根据我的实验,您可以通过在 didMove 中将 SKTileSet 与空白图块集交换来防止此问题。除了在 didMove (或 didMove 调用的函数)内之外,您不能在其他任何地方执行此操作。

所以我的解决方案是将图块集提取到单独的精灵中,然后“无效”图块​​地图上的图块集。您可以使用以下代码来执行此操作:

extension SKTileMapNode {

func extractSprites(to curScene: SKScene) {

    for col in 0..<numberOfColumns {
        for row in 0..<numberOfRows {

            if tileDefinition(atColumn: col, row: row) != nil {

                let tileDef = tileDefinition(atColumn: col, row: row)
                let newSprite = SKSpriteNode(texture: tileDef!.textures.first!)
                curScene.addChild(newSprite)

                let tempPos = centerOfTile(atColumn: col, row: row)
                newSprite.position = convert(tempPos, to: curScene)
            }
        }
    }

    eraseTileSet()
}

func eraseTileSet() {
    let blankGroup: [SKTileGroup] = []
    let blankTileSet = SKTileSet(tileGroups: blankGroup)
    tileSet = blankTileSet
}
}

基本上在 didMove 中,您需要在每个 SKTileMapNode 上调用 extractSprites。这将简单地从每个图块创建 SKSpriteNode 并将它们放入场景中。然后SKTileSet将被“切换”为空白的。神奇的是,内存泄漏将会消失。

这是一个简化的解决方案,您需要对其进行扩展。这只会将精灵放在那里,但不会定义它们的行为方式。抱歉,这是我找到的唯一解决方案,我相信你的问题是 SpriteKit 中的一个主要错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpriteKit 内存泄漏更改包含 SKTileMapNodes 的场景 的相关文章

  • 旋转后使SKSpriteNode的边缘看起来平滑

    我创建一个 SKSpriteNode 像这样 var shape SKSpriteNode SKSpriteNode color UIColor redColor size CGSizeMake CGFloat sizeOfShape CG
  • 在 Swift 子类中添加便捷初始化器

    作为学习练习 我正在尝试实现一个子类SKShapeNode它提供了一个新的方便的初始值设定项 它接受一个数字并构造一个 ShapeNode 它是数字宽度和高度的正方形 根据斯威夫特书 https developer apple com li
  • iOS 12 和 SKShader 中已弃用 OpenGL ES

    我对 SpriteKit 中着色器的概念和使用非常陌生 我发现本教程介绍了如何使用附加到 Color Sprite 的自定义着色器属性的自定义着色器文件 Fractal fsh 渲染 Mandelbrot 分形 https www wehe
  • 在 SpriteKit 中预加载纹理

    我做了一些研究 但似乎找不到任何可以清楚解释如何在动画中预加载单个纹理和纹理的内容 我目前正在使用Atlas s in Assets xcassets对相关的动画图像进行分组 我的图像出现在 Atlas 中是否意味着它们已被预加载 就单个图
  • AVAudioPlayer 播放时游戏滞后

    我正在创建一个游戏 用户用喷气背包控制角色 当喷气背包与钻石相交时 我将钻石添加到它们的总数中 然后播放声音 然而 声音会使游戏暂停十分之一秒左右并扰乱流程 这是我正在使用的代码 var diamondSound NSBundle main
  • SKVideoNode 作为 SCNSphere 的纹理

    我正在尝试使用 SKVideoNode 作为 SCNView 中 SCNSphere 的视频纹理源 我正在关注这个答案 SKVideoNode 嵌入在 SKScene 中 作为场景套件节点的纹理不起作用 https stackoverflo
  • SKEase动作,如何使用Float改变Action Setter Block?

    在下面的用例中 我尝试为lineWidth of an SKShapeNode SKEase 是精彩的一部分SpriteKit缓动 https github com craiggrummitt SpriteKitEasingSwift来自
  • iOS 9 / Xcode 7:SKSpriteNode spriteNodeWithImageNamed 在某些设备上不起作用

    我在从 SKSpriteNode 的 xcassets 图像集中加载图像时遇到问题 虽然它在 iOS 8 x 上运行良好 SKSpriteNode spriteNodeWithImageNamde 图像名称 它不适用于某些运行 iOS 9
  • SKshapenode 没有响应Physicsbody

    我创建了一个SKShapeNode我已经分配了一个physicsBody到它 然而 当有接触时它不会被触发 的制作SKShapeNode code SKShapeNode gravityline SKSpriteNode lolo SKSp
  • iOS 8 SpriteKit 在从块/操作中添加或删除子项时崩溃

    从 iOS8 开始 我的游戏突然开始崩溃 经过一番调试 我发现游戏在以下两个地方崩溃 sparkNode runAction SKAction sequence Some actions and finally SKAction remov
  • 如何模糊除 2 个节点之外的所有内容。雪碧 (Swift)

    我想模糊我的游戏背景 self view scene paused true 但是按钮和暂停的标签 都是 SKSpriteNode 的 不应该是模糊的 它们都有不同的 Z index 值 按下按钮节点时场景暂停 再次按下按钮时场景恢复 我找
  • 如何在 SKSpriteNode 上创建脉冲效果?

    您好 我想了解如何创建视觉脉冲效果 如下面的视频所示 https www youtube com watch v uiHj KZWjpU https www youtube com watch v uiHj KZWjpU 我点击了视频中发布
  • 如何检测哪个SKSpriteNode已被触摸

    我找到一个类似的问题 https stackoverflow com questions 27922198 how do i detect if an skspritenode has been touched 但我试图检测并识别用户触摸的
  • 从旋转体射击

    我有一个旋转的敌人身体 可以发射子弹 它工作得相当不错 但它似乎会向所有方向射击 除了垂直向下 我已经有一段时间没有学三角函数了 我想我忘记了一些事情 我必须检查敌人的轮换吗 SKAction shoot SKAction moveTo C
  • 为什么我的 ViewController 重新打开后不显示另一个 SKScene?

    所以现在我正在编写一个游戏 但遇到了一个我没有真正找到解决方案的问题 我会尽力为你描述它 所以 为了能够更好地解释我的问题 我为你们创建了一个示意图 现在问题是 我有两个视图控制器 一个称为MenuVc 另一个称为GameVC In Gam
  • 关闭SKScene后,内存仍然居高不下

    我使用dispatch onceNSObject创建数据指针 因此 当主视图控制器出现时 所有游戏资源指针都会被创建 为了玩游戏 用户点击UIButton对应于某个特定级别UI视图控制器 让我称之为 LevelSelectionContro
  • Swift SKSpriteNode:检测点击/双击/长按

    我正在尝试创建 SKSpriteNode 的子类 它可以检测用户交互 点击 双击并按住 然后遵循委托 在我看来 这是一个相对常见的需求 但是 该代码无法在不触发单击的情况下检测双击 我根本没有找到检测按住 长按操作的方法 我这一切都错了吗
  • 使用Sprite Kit如何启用iAd?

    在IOS 7中 我们可以非常轻松地启用iAd 使用 self canDisplayBannerAds YES in code 查看是否加载UIViewController的 但是 我无法在我的 ViewController 加载 SKSce
  • 如何将 CIPixellate Core Image Filter 添加到 Sprite Kit 场景?

    如何将 CIPixellate Core Image Filter 添加到 Sprite Kit 场景 我有一个 SpriteKit 场景 它是 SKScene 或其子类 我想向场景添加一个核心图像滤镜 特别是 CIPixellate 过滤
  • 精灵套件的方向键

    我有兴趣尝试创建一些游戏 即新的精灵套件 然而 对于我想要的游戏 我宁愿使用方向键而不是操纵杆 由于我将从 Cocos 转移过来 我的旧程序不再起作用 所以那个 dpad 也不起作用 遗憾的是 我还没有遇到任何可能有助于在新的精灵套件中实现

随机推荐

  • Android MapView - 设置自动缩放,直到所有 ItemizedOverlay 都可见

    在 onCreate 中硬编码 setZoom 感觉非常过时 我想通过最初让 MapView 设置缩放直到所有 GeoPoints OverlayItems 在地图上可见来增强用户体验 这怎么能自动神奇地完成呢 有点像这样 int minL
  • 是否可以从数据帧转换为矩阵?

    我是Python新手 我有一个巨大的dataframe Person OD A BS1 A BS2 B BS4 B BS8 C BS5 C BS1 D BS9 D BS7 E BS2 E BS7 F BS2 F BS1 G BS1 G BS
  • 如何大声朗读Python列表推导式?

    我的问题是关于Python的列表理解可读性 当我遇到具有复杂 嵌套列表理解的代码时 我发现我必须重新阅读它们几次才能理解其意图 有没有一种直观的方法来朗读列表推导式 看来我应该从中间开始 读 然后读if条件 如果有 并阅读表达 last 以
  • 以 bed 格式从 R 导出文件

    我有一个像这样的数据框 tab gt elements scaffold start end Lengths 1 Dong 1 NVe R4 Nematostella12 1 KQ415659 1 14193 14540 347 2 OK
  • 什么是位置提供商“被动”?在搭载 Android 2.2 的 HTC Desire 上看到

    在进入基于位置的模式之前 我通过调用检查是否存在任何位置提供商 List
  • 如何设置JVM的PATH环境变量

    我正在尝试运行使用 Java 7 ProcessBuilder 安装在我的系统上的可执行文件 我注意到环境变量 PATH 可以通过 System getenv PATH 不包括我自己的自定义设置路径 它返回这个 usr bin bin us
  • Excel表格行列查找

    我在使用某些 Excel 函数时遇到了困难 我有一个带有行标题和列标题以及数据的表 例如 如果我有一种披萨 与其尺寸交叉 数据就是价格 S M L XL Cheese 6 6 5 8 10 Pepperoni 6 5 7 5 10 12 S
  • 使用 argparse 输出来调用函数

    目前我的代码如下所示 它允许我解析我的程序脚本获取的多个参数 有没有更接近 最佳实践 的不同方法 我还没有看到实际使用输出的代码argparse 仅介绍如何设置 def useArguments x 0 while x lt 5 if x
  • Angular 6 - 如何在组件级别应用外部 CSS 样式表(传单)?

    尝试在 Angular 6 组件中使用 Leaflet 根据 css 文件的链接方式 地图显示正常或混乱 缺少的图块顺序不正确 这意味着未考虑 css 我设法让它与 2 个解决方案一起使用 将 css 链接到应用程序级别 全局 但不仅仅链接
  • 您可以在动态计时器上触发 AWS Lambda 吗?

    有没有办法在动态计时器上触发 AWS Lambda 目前 我正在利用预定事件来触发 lambda 但这是一个设定的计时器 有没有办法动态设置从 Lambda 内部触发 Lambda 的时间 这里的想法是 这个 Lambda 执行特定的检查并
  • Rails、yml 和多行

    我一生都无法从我的语言环境文件中获取多行 yaml 来工作 我尝试了多种解决方案的每种组合 但没有成功 我努力了key key gt 双引号 单引号 n 下一行的值 缩进 可能还有其他一些 在我看来我只是使用t key 我在这里撕扯我的头发
  • 将分面 ggplots (facet_wrap) 与 R 中的owplot 对齐

    我正在尝试对齐两个面板图 它们是用facet wrap in ggplot按照以下方式 注意 面板 A 需要保持为空 然而 我注意到面板 B 的 y 轴与面板 C 的最后一个图的 y 轴并不完全对齐 尽管选项axis lb 在两个方面 Co
  • 按日期对 HashMap 进行排序

    在 Java 类中 我有一个按日期重新排序现有 HashMap 的方法 HashMap 是一种类型
  • 在 CodeIgniter 上集成 Bootstrap

    我正在尝试在 codeigniter 网站上使用 bootstrap 但似乎找不到 bootstrap 文件
  • 带参数的路由不起作用

    我正在关注tutorial https openui5 hana ondemand com docs guide 2366345a94f64ec1a80f9d9ce50a59ef html在这里 我陷入了带参数的路由 该示例应用程序未在我的
  • C++ 元函数来确定类型是否可调用

    是否可以编写一个 C 0x 元函数来确定类型是否可调用 我所说的可调用类型是指函数类型 函数指针类型 函数引用类型 这些由boost function types is callable builtin lambda 类型以及任何具有重载的
  • 为什么 Rubocop 不允许 html_safe 或 raw() Rails

    这是我没有通过 Rubocop 的代码 因为 Rails OutputSafety 将字符串标记为 html 安全可能存在安全风险 def number with html delimiter num number with delimit
  • 运行“yarn run”时将参数传递给“node”可执行文件

    节点可以使用各种选项启动 特别有趣的是 inspect flag node inspect node modules bin jest some spec js 是否可以通过 inspect以某种方式标记yarn run 例如 yarn r
  • 使用 Windows 身份验证的 WCF jsonP - 可能吗?

    我正在托管一个输出 jsonp 的 wcf 服务 来自 IIS 打开 Windows 身份验证 的响应是 经过身份验证的服务不支持跨域 javascript 回调 有办法解决这个问题吗 我必须打开 Windows 身份验证 但也想使用 wc
  • SpriteKit 内存泄漏更改包含 SKTileMapNodes 的场景

    我正在尝试使用 Swift SpriteKit 和 SKTileMaps 创建一个简单的 2d 平台游戏 但每次我在包含 SKTileMaps 的场景之间切换时 我都会在 Xcode Instruments 中看到大量内存泄漏 我已经尽可能