残念ながら、SKShapeNode は、あなたがしようとしていることにはあまり適していません。ただし、いくつかの注意点はありますが、これを最適化する方法があります。
fps の最大の問題の最初の 1 つは、追加する各線セグメントが別の描画であるため、描画カウントが非常に高くなることです。インスタンスを設定showsDrawCount
するSKView
と、私が何を意味するかがわかります。
この回答では、1回の描画で複数のskshapenode? 、一度何かを描画している場合、問題を解決するためshouldRasterize
に a のプロパティを使用する方法に関する詳細情報を取得できます。SKEffectNode
これを行わないと、フレームごとに多数の描画にプロセッサ時間が費やされます。
したがって、ドローが主な問題であり、希望するパフォーマンスが得られないことがわかります。ただし、時間の経過とともに一貫して描画したいと考えているようです。そのため、私が提案することは、実行可能な解決策になる可能性があります。
私が提案しているソリューションのロジックは次のとおりです。
1 -SKSpriteNode
キャンバスとして使用できる を作成します。
2 -SKShapeNode
現在の線分のみを描画するために使用されるものを作成します。
3 - それをSKShapeNode
キャンバスの子にします。
4 - 新しい線分を描きますSKShapeNode
5 - SKView
`textureFromNode' メソッドを使用して、キャンバスに現在描画されているものを保存します。
6 - キャンバスのテクスチャをそのテクスチャに設定します。
#4 に戻りSKShapeNode
、次の線分の新しいパスを作成します。
必要に応じて繰り返します。
その結果、ドロー カウントが 2 ドローを超えることはなくなり、ドロー カウントが高くなる問題が解決されます。
基本的に、テクスチャで以前に描画されたものを保持しているSKShapeNode
ため、最新の線分に対して 1 つの描画とSKTexture
.
繰り返しますが、私はまだこのプロセスを試していません。ラグがある場合は、textureFromNode
各フレームでその呼び出しになります。何かがあなたのボトルネックになるとしたら、それはそれです!
解決しようとしている別の問題が必要なので、今日この理論を試してみるかもしれませんtextureFromNode
。そのため、その方法がどれほど速い/遅いかを確実に知ることができます! 笑
アップデート
これは完全なコードではありませんが、必要な描画パフォーマンス (60fps) を実現するための重要な部分です。
基本的なノード要素は次のとおりです。
コンテナー -> キャッシュする必要があるすべての要素を含む SKNode
canvas -> 描かれたセグメントのキャッシュされたバージョンを表示する SKSpriteNode
セグメントのプール -> 最初にセグメントを描画するために使用され、必要に応じて再利用されます
最初に SKShapeNodes のプールを作成します。
pool = [[NSMutableArray alloc]init];
//populate the SKShapeNode pool
// the amount of segments in pool, dictates how many segments
// will be drawn before caching occurs.
for (int index = 0; index < 5; index++)
{
SKShapeNode *segment = [[SKShapeNode alloc]init];
segment.strokeColor = [SKColor whiteColor];
segment.glowWidth = 1;
[pool addObject:segment];
}
プールから SKShapeNode を取得するための次の create メソッド:
-(SKShapeNode *)getShapeNode
{
if (pool.count == 0)
{
// if pool is empty,
// cache the current segment draws and return segments to pool
[self cacheSegments];
}
SKShapeNode *segment = pool[0];
[pool removeObjectAtIndex:0];
return segment;
}
次に、プールからセグメントを取得して線を描画するメソッドを作成します。
-(void)drawSegmentFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
{
SKShapeNode *curSegment = [self getShapeNode];
CGMutablePathRef path = CGPathCreateMutable();
curSegment.lineWidth = 3;
curSegment.strokeColor = [SKColor whiteColor];
curSegment.glowWidth = 1;
curSegment.name = @"segment";
CGPathMoveToPoint(path, NULL, fromPoint.x, fromPoint.y);
CGPathAddLineToPoint(path, NULL, toPoint.x, toPoint.y);
curSegment.path = path;
lastPoint = toPoint;
[canvas addChild:curSegment];
}
次は、テクスチャを作成し、既存のセグメントをプールに返すメソッドです。
-(void)cacheSegments
{
SKTexture *cacheTexture =[ self.view textureFromNode:container];
canvas.texture = cacheTexture;
[canvas setSize:CGSizeMake(canvas.texture.size.width, canvas.texture.size.height)];
canvas.anchorPoint = CGPointMake(0, 0);
[canvas enumerateChildNodesWithName:@"segment" usingBlock:^(SKNode *node, BOOL *stop)
{
[node removeFromParent];
[pool addObject:node];
}];
}
最後に、タッチ ハンドラー:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self cacheSegments];
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInNode:self];
lastPoint = location;
[self drawSegmentFromPoint:lastPoint toPoint:location];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
CGPoint location = [touch locationInNode:self];
[self drawSegmentFromPoint:lastPoint toPoint:location];
}
}
前述したように、これは包括的なコードではありません。アプリケーションに実装できる概念について十分に理解していることを前提としています。これらは、私のベアボーン実装の単なる例です。