SpriteKit のメタボール エフェクトに取り組んでいます。バッファーの色範囲を圧縮するシェーダーを備えた SKEffectNode があります。このエフェクト ノードには、その子として 100 数の SKSpriteNode があります。エフェクトは数秒間うまく機能しますが、突然、数フレームの間にすべてのスプライトノードが画面から消え、ノード数が 100 奇数から 2 に減少します (残りの 2 つはエフェクトノードだと思います)。それ自体、およびボールを保持するコンテナを形成するエッジ チェーン?)
ボール スプライト ノードをシーンのルート ノードに直接追加すると、これは発生しません。数秒後に積極的にカリングされるように見えるのは、エフェクトノードの子になったときだけです。
興味深いことに (これは、フレーム レートが非常に低い場合にシミュレーターで確認できます)、SpriteNode は、現在画面に表示されている垂直方向 (画面の上部から下部) でカリングされるようです。
ビューのshowsPhysics
プロパティが true に設定されている場合、SKSpriteNode の物理ボディがまだ画面上にあり、転がっていることがわかります。しかし、それらの視覚的表現は消失し、ビューのノード数は枯渇しています。ドキュメントによると、showsNodeCount
「シーンに表示される物理体を示しています」。そのため、ノードが表示されなくなったため、ノード数が減少しました。
これを引き起こしている可能性のあるもの、またはデバッグに使用できるツールを知っている人はいますか?
標準の SpriteKit iOS Swift 2.2 Xcode 7 テンプレートでは、GameScene ファイルを次のように置き換えます。
import SpriteKit
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
// create walls to contain balls
let box = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 0, y: 0, width: 800, height: 800))
let boxNode = SKNode()
boxNode.physicsBody = box
addChild(boxNode)
let radius: CGFloat = 5
let texture = createMetaballTexture(radius)
let centre = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
let rows = 12
let columns = 10
let metaballs = SKEffectNode()
let shaderString = [
"void main()",
"{",
"vec4 c = texture2D(u_texture, v_tex_coord);",
"gl_FragColor = smoothstep(0.3, 0.6, c); ",
"}"].joinWithSeparator("\n")
let map = SKShader(source: shaderString)
metaballs.shader = map
for i in 0...(rows * columns) {
let ball = SKSpriteNode(texture: texture)
let body = SKPhysicsBody(circleOfRadius: radius)
body.friction = 0.1
body.restitution = 0.8
ball.physicsBody = body
ball.position = CGPoint(x: centre.x + CGFloat(i % columns) * radius, y: centre.y + CGFloat(i / rows) * radius)
ball.blendMode = .Add
metaballs.addChild(ball) // change this to "addChild(ball)", and the nodes don't get culled
}
addChild(metaballs)
physicsWorld.speed = 0.2
backgroundColor = SKColor.darkGrayColor()
}
func createMetaballTexture(radius: CGFloat) -> SKTexture {
let metaballScale: CGFloat = 8
let ellipseOrigin = (metaballScale / 2) - 1.5
UIGraphicsBeginImageContext(CGSize(width: radius * metaballScale, height: radius * metaballScale))
let context = UIGraphicsGetCurrentContext()
SKColor.whiteColor().setFill()
CGContextFillEllipseInRect(context, CGRect(x: radius * ellipseOrigin, y: radius * ellipseOrigin, width: radius * 3, height: radius * 3))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return SKTexture(CGImage: blur(image!))
}
}
func blur(image: UIImage) -> CGImage {
let gaussianBlurFilter = CIFilter(name: "CIGaussianBlur")
let inputImage = CIImage(CGImage: image.CGImage!)
gaussianBlurFilter?.setValue(inputImage, forKey:kCIInputImageKey)
gaussianBlurFilter?.setValue(5, forKey: kCIInputRadiusKey)
let outputImage = gaussianBlurFilter?.outputImage
let context = CIContext(options: nil)
return context.createCGImage(outputImage!, fromRect: inputImage.extent)
}