SKShapeNode 性能不佳

Posted

技术标签:

【中文标题】SKShapeNode 性能不佳【英文标题】:SKShapeNode bad Performance 【发布时间】:2021-12-15 14:31:39 【问题描述】:

在学习和使用 Swift 和 Spritekit 时,我遇到了一个问题: 我似乎无法在运行时创建许多 SKShapeNode。 我正在尝试用“随机”三角形填充屏幕

这些棕色三角形是这样创建的 SKShapeNode:

func createTwoFloorTrianglesAtLocation(xPos:CGFloat, yPos:CGFloat, width:CGFloat, height:CGFloat, orientation:Bool) -> [SKShapeNode] 
    
    let path1 = UIBezierPath()
    let path2 = UIBezierPath()
    
    if orientation 
        path1.move(to: CGPoint(x: xPos, y: yPos))
        path1.addLine(to: CGPoint(x: xPos, y: yPos + height))
        path1.addLine(to: CGPoint(x: xPos + width, y: yPos))
        
        path2.move(to: CGPoint(x: xPos + width, y: yPos))
        path2.addLine(to: CGPoint(x: xPos + width, y: yPos + height))
        path2.addLine(to: CGPoint(x: xPos, y: yPos + height))
     else 
        path1.move(to: CGPoint(x: xPos, y: yPos))
        path1.addLine(to: CGPoint(x: xPos + width, y: yPos + height))
        path1.addLine(to: CGPoint(x: xPos, y: yPos + height))
        
        path2.move(to: CGPoint(x: xPos + width, y: yPos))
        path2.addLine(to: CGPoint(x: xPos, y: yPos))
        path2.addLine(to: CGPoint(x: xPos + width, y: yPos + height))
    
    
    
    let triangle1 = SKShapeNode(path: path1.cgPath)
    triangle1.fillColor = groundColors[GKRandomSource.sharedRandom().nextInt(upperBound: groundColors.count)]!
    triangle1.name = "colorSprite"
    triangle1.lineWidth = 0.0
    
    let triangle2 = SKShapeNode(path: path2.cgPath)
    triangle2.fillColor = groundColors[GKRandomSource.sharedRandom().nextInt(upperBound: groundColors.count)]!
    triangle2.name = "colorSprite"
    triangle2.lineWidth = 0.0
    
    return [triangle1, triangle2]

我将调用 #addChild(SKNode) 的这些三角形添加到 GameScene。

这些三角形不会移动或其他任何东西,它们应该会在游戏后期通过“画线”在它们上方消失。

问题是我在 XCode 模拟器和真实设备(iPhone 13 Pro Max)上的 FPS 和高 CPU 使用率以及高功率使用率都非常差。 如果我减少三角形的数量,它会变得更好,但我不想那样做。

有没有办法解决这个问题?

我还在网上看到 (Create an SKTexture from an SKShapeNode) 有人使用 SKSpriteNode 而不是 SKShapeNode。 但是,如果在将 ShapeNodes 作为子节点添加到场景之前使用以下代码将它们“转换”为 SpriteNodes,我会看到左下角的节点计数器也在 1000 左右,但没有呈现矩形。

func addNodesToParent(_ stuff:[SKShapeNode]) 
    for n in stuff 
        addChild(SKSpriteNode(texture: self.view?.texture(from: n)))
        //addChild(n)
    

我希望有人有我可以尝试的想法。 提前致谢,

您好, 妮可

//编辑1: 尝试使用 CGPoints 数组而不是 CGPath,遗憾的是它并没有改变性能中的任何内容。 代码:

func createTwoFloorTrianglesAtLocation(xPos:CGFloat, yPos:CGFloat, width:CGFloat, height:CGFloat, orientation:Bool) -> [SKShapeNode] 
    var p1:[CGPoint]
    var p2:[CGPoint]
    
    if orientation 
        p1 = [CGPoint(x: xPos, y: yPos), CGPoint(x: xPos, y: yPos + height), CGPoint(x: xPos + width, y: yPos)]
        p2 = [CGPoint(x: xPos + width, y: yPos), CGPoint(x: xPos + width, y: yPos + height), CGPoint(x: xPos, y: yPos + height)]
        
     else 
        p1 = [CGPoint(x: xPos, y: yPos), CGPoint(x: xPos + width, y: yPos + height), CGPoint(x: xPos, y: yPos + height)]
        p2 = [CGPoint(x: xPos + width, y: yPos), CGPoint(x: xPos, y: yPos), CGPoint(x: xPos + width, y: yPos + height)]
        
    
    
    let triangle1 = SKShapeNode(points: &p1, count: p1.count)
    triangle1.fillColor = groundColors[GKRandomSource.sharedRandom().nextInt(upperBound: groundColors.count)]!
    triangle1.name = "colorSprite"
    triangle1.lineWidth = 0.0
    
    let triangle2 = SKShapeNode(points: &p2, count: p2.count)
    triangle2.fillColor = groundColors[GKRandomSource.sharedRandom().nextInt(upperBound: groundColors.count)]!
    triangle2.name = "colorSprite"
    triangle2.lineWidth = 0.0
    
    return [triangle1, triangle2]

【问题讨论】:

您是否尝试使用点数组而不是 cgpath 创建三角形? 现在试过了,遗憾的是性能变化不大(现在只是在模拟器中尝试过,但我认为它与真实设备不会有太大差异)。我用其中的新代码更新了我的帖子,也许我做错了什么? 您是否尝试为每个节点设置不同的名称?类似于 xpos_ypos_2。 发现有趣的article。尤其是第 4 部分(替换而不是混合),第 5 部分:(删除玩家看不到的节点)和第 8 部分(禁用兄弟顺序) 所以我基本上尝试了你告诉/链接我的所有内容,遗憾的是没有任何效果。但我认为文章中提到的一些东西并不真正适合我的用例,但它并没有改变任何东西。 【参考方案1】:

SKShapeNode 相对昂贵。当你有很多场景时,你的场景肯定会陷入困境。渲染到纹理是一个很好的方法。这会将大量 SKShapeNode(或标签或其他图形节点)减少到单个 SKTexture。

func renderToTexture() -> SKTexture? 
    let container:SKNode = SKNode()
    
    //create shapes
    for _ in 0...100 
        let shape = SKShapeNode(circleOfRadius: CGFloat.random(in:1...30))
        shape.position.x = CGFloat.random(in: 0..<frame.width)
        shape.position.y = CGFloat.random(in: 0..<frame.height)
        container.addChild(shape)
    
    
    //render container to a single texture
    let texture:SKTexture? = self.view?.texture(from:container)
    return texture

将此纹理分配给精灵节点,您将获得 1 个绘制调用。进行渲染很昂贵,但如果将许多图形节点减少到一个,从长远来看会更便宜。注意:由于生成的纹理不是图谱,因此这 1 个调用永远不会与其他调用一起批处理。

【讨论】:

谢谢,我回家后会试试这个。我会让你知道进展如何!

以上是关于SKShapeNode 性能不佳的主要内容,如果未能解决你的问题,请参考以下文章

sklearn 中 GMM 的意外性能不佳

NSFetchedResultsController 性能不佳

UICollectionView 滚动性能不佳

BizTalk SOAP 接收位置性能不佳

Django ORM 与 Oracle 的性能不佳

RandomForestClassifier 性能不佳