ios - 实现可点击形状的最佳方法?

标签 ios objective-c swift sprite-kit core-graphics

我正在构建一个应用程序,它提供类似于 Photoshop 或 illustrator 的可编辑 Canvas (当前使用 SpriteKit)。正如您想象的那样,在显示大量节点(1000+)时,我遇到了一些性能问题。

目前,我有一个带有 SKShapeNodesSKScene。它们目前没有任何图像,只是填充了颜色。它们的形状路径 (CGPaths) 从圆形到贝塞尔路径不等。每个形状当前都有一个 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

http://www.sdkboy.com/2014/01/spritekit-bit-blitting-by-drawing-to-a-texture-for-performance-optimization/

因此,如果您不需要每个节点始终可触摸,您可以在有和没有PhysicsBodys之间切换,或者将层从位 block 传输切换到事件层。

关于ios - 实现可点击形状的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44467843/

相关文章:

ios - 如何在 UIView 中屏蔽 UIImage View ?

objective-c - 泄漏是如何发生的?

swift - 为类函数创建并运行带有多个参数的选择器

ios - Pod安装没有权限

ios - 发送到实例 0x8c9a6d0 的无法识别的选择器

ios - 顺利停止 CABasicAnimation

objective-c - 我应该在哪里创建我的线程? ( Objective-C )

ios - 如何使用 Alamofire 更改全局变量?

ios - 如何快速创建不可变数组的可变副本?

ios - ARKit 3D Modell 没有纹理