我正在构建一个应用程序,它提供类似于 Photoshop 或 illustrator 的可编辑 Canvas (当前使用 SpriteKit
)。正如您想象的那样,在显示大量节点(1000+)时,我遇到了一些性能问题。
目前,我有一个带有 SKShapeNodes
的 SKScene
。它们目前没有任何图像,只是填充了颜色。它们的形状路径 (CGPath
s) 从圆形到贝塞尔路径不等。每个形状当前都有一个 SKPhysicsBody
,其路径与用于检测点击的渲染形状相同。
性能问题可以通过以下方式描述:
- 添加 1000 个节点(圆圈)时速度缓慢,每个节点使用约 0.1mb 内存
- 移动 1000 个节点(圆圈)时缓慢
- 从 1000 个节点(圆圈)生成纹理时速度缓慢
禁用PhysicsBodies不会显着提高性能,但确实会提高CPU负载(从恒定的60%跃升至1%左右)
大多数用户不会使用 1000 个节点,但我想实现最佳解决方案。
我想要的是两个有两层:
- 一个渲染层,我希望能够在其上渲染带有笔划和填充的
CGPath
(最好选择笔划结束样式以及其他小东西) - 一个交互层,我希望能够在其上检测
CGPath
内的点击,并用颜色描边 CGPath 以指示突出显示。
如何实现此解决方案或类似的解决方案来提高渲染 1000 个圆圈的速度?
最佳答案
不要使用 SKShapeNode,每个 shapenode 需要 1 次绘制调用。您可以创建一个形状,然后将其“转换”到 SpriteNode,然后再将其添加到场景中:
func shapeToSprite(_ shape: SKShapeNode) -> SKSpriteNode {
let sprite = SKSpriteNode(texture: SKView().texture(from: shape))
sprite.physicsBody = shape.physicsBody // Or create a new PB from alpha mask (may be slower, IDK)
shape.physicsBody = nil
return sprite
}
override func didMove(to view: SKView) {
let shape = SKShapeNode(circleOfRadius: 60)
addChild(shapeToSprite(shape))
}
如果您需要以无法通过缩放或 SKWarpGeometry 实现的方式不断编辑形状的大小/形状,这会很糟糕
要检测这样的点击,您只需执行以下任一操作:1、为 SpriteNode 设置名称,然后在 TouchesBegan 中查找它;或者 2、子类化 SpriteNode 并覆盖它的 TouchesBegan。
此外,如果您只需要一个静态图像,您可以将数千个节点位传输到 1 个纹理上。 Sprite Kit: A Lot of sprites (1000+) with Bit Blitting
因此,如果您不需要每个节点始终可触摸,您可以在有和没有PhysicsBodys之间切换,或者将层从位 block 传输切换到事件层。
关于ios - 实现可点击形状的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44467843/