Получение текстуры SpriteKit из SKView, возвращающей ноль после 104 вызовов - PullRequest
0 голосов
/ 30 апреля 2018

У меня странное поведение в SpriteKit при создании текстуры. Функция ниже показывает вам, что я делаю. Короче говоря, я нахожусь в SceneKit и делаю SCNNode из массива цветов (например, пиксель / воксель). Отлично работает. Однако после ровно 104 вызовов возвращаемая текстура равна нулю. После этого, ударил или пропустил, будет ли текстура ноль или нет. Я также предоставляю точную информацию о цвете. Мысли?

   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
}

1 Ответ

0 голосов
/ 30 апреля 2018

Здесь пригодится autoreleasepool, он позволяет вам освободить память после завершения autoreleasepool, чтобы у вас не было свободного места перед повторным использованием.

Конечно, это не решит вашу основную проблему, когда вы создаете слишком много текстур и исчерпываете пространство памяти, но это позволит вам, по крайней мере, сделать еще немного, потому что освободит временную память, которая view.texture(from:node) держится за.

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
}
...