【问题标题】:Getting SpriteKit texture from SKView returning nil after 104 calls从 SKView 获取 SpriteKit 纹理在 104 次调用后返回 nil
【发布时间】:2018-10-10 19:01:32
【问题描述】:

在创建纹理时,我在 SpriteKit 中有一些奇怪的行为。下面的函数向您展示了我在做什么。简而言之,我在 SceneKit 中并用一组颜色制作了一个 SCNNode(想想像素/体素)。它就像一个魅力。然而,恰好在 104 次调用之后,返回的纹理为 nil。之后,无论纹理是否为 nil,都会受到影响。我还提供了准确的颜色信息。想法?

   func create2dModelSK(with colors: [String]) -> SCNNode? {
    let geo = SCNBox(width: 1.0, height: 1.0, length: 0.1, chamferRadius: 0.0)

    let base = SCNNode(geometry: geo)

    let view = SKSpriteNode(color: .white, size: CGSize(width: 160, height: 160))
    view.anchorPoint = CGPoint(x: 0, y: 1)
    var xOffset = 0
    var yOffset = 0
    var count = 0
    for _ in 0...15 {
        for _ in 0...15 {
            guard let newColor = UIColor(hexString: "#" + colors[count] + "ff") else { return base }

            let n = SKSpriteNode(color: newColor, size: CGSize(width: 10, height: 10))
            n.anchorPoint = CGPoint(x: 0, y: 1)
            n.position = CGPoint(x: xOffset, y: yOffset)
            view.addChild(n)
            xOffset += 10
            count += 1
        }
        xOffset = 0
        yOffset -= 10
    }
    let skView = SKView(frame: CGRect(x: 0, y: 0, width: 160, height: 160))

    let texture = skView.texture(from: view)
    //AFTER being called 104 times, texture is nil.
    let faceMaterial = SCNMaterial()
    faceMaterial.diffuse.contents = texture

    let sideMaterial = SCNMaterial()
    sideMaterial.diffuse.contents = UIColor.white

    let materialsForBox = [faceMaterial,sideMaterial,faceMaterial,sideMaterial,sideMaterial,sideMaterial]
    base.geometry?.materials = materialsForBox

    let scale = SCNVector3(x: 0.1, y: 0.1, z: 0.1)
    base.scale = scale

    return base
}

【问题讨论】:

  • 纹理空间不足

标签: sprite-kit scenekit


【解决方案1】:

这就是autoreleasepool 派上用场的地方,它允许您在autoreleasepool 完成时释放内存,这样您就不会在再次使用之前耗尽空间。

当然这不会解决你的主要问题,你创建了太多纹理并且内存空间不足,但它至少可以让你做更多,因为它会释放 @987654323 的临时内存@正在坚持。

func create2dModelSK(with colors: [String]) -> SCNNode? {
    let geo = SCNBox(width: 1.0, height: 1.0, length: 0.1, chamferRadius: 0.0)

    let base = SCNNode(geometry: geo)

    let view = SKSpriteNode(color: .white, size: CGSize(width: 160, height: 160))
    view.anchorPoint = CGPoint(x: 0, y: 1)
    var xOffset = 0
    var yOffset = 0
    var count = 0
    for _ in 0...15 {
        for _ in 0...15 {
            guard let newColor = UIColor(hexString: "#" + colors[count] + "ff") else { return base }

            let n = SKSpriteNode(color: newColor, size: CGSize(width: 10, height: 10))
            n.anchorPoint = CGPoint(x: 0, y: 1)
            n.position = CGPoint(x: xOffset, y: yOffset)
            view.addChild(n)
            xOffset += 10
            count += 1
        }
        xOffset = 0
        yOffset -= 10
    }
    autoreleasepool{
        let skView = SKView(frame: CGRect(x: 0, y: 0, width: 160, height: 160))

        let texture = skView.texture(from: view)
        //AFTER being called 104 times, texture is nil.
        let faceMaterial = SCNMaterial()
        faceMaterial.diffuse.contents = texture

        let sideMaterial = SCNMaterial()
        sideMaterial.diffuse.contents = UIColor.white

        let materialsForBox = [faceMaterial,sideMaterial,faceMaterial,sideMaterial,sideMaterial,sideMaterial]
        base.geometry?.materials = materialsForBox
    }
    let scale = SCNVector3(x: 0.1, y: 0.1, z: 0.1)
    base.scale = scale

    return base
}

【讨论】:

  • 顺便说一句,避免调用节点“视图”,因为这只会增加混乱
  • 感谢您的快速回答。有没有更好的方法来考虑添加这么多纹理?我不认为我需要超过 1000 个。
  • 你想做什么?
  • 我正在将 SCNNodes 添加到 ARKit 场景中。每个节点都需要它自己的纹理以及提供给上述函数的数据。数据是从许多位置提供的,但它们都会输入到场景中。
  • 另外,在你的答案中调用 autoreleasepool 不起作用,因为它变成了它自己的范围。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多