@ godel9 には適切な解決策が提案されていますが、私自身のテストでは、予期しない動作に対する説明は正しくありません。
SKPhysicsBody クラス リファレンスから:
フォースは、1 つのシミュレーション ステップ (1 フレーム) に対して適用されます。
-update メソッドに関するSKScene クラス リファレンスのセクションを参照してください。
...シーンがビューに表示され、一時停止されていない限り、フレームごとに 1 回だけ呼び出されます。
したがって、SKScene の -update メソッドで -applyForce: を呼び出しても問題は発生しないと想定できます。しかし、観測されたように、重力よりもはるかに大きな上向きの力 (400 ニュートン対 9.81) を加えたにもかかわらず、力は重力を超えません。
2 つのノードを作成するテスト プロジェクトを作成しました。1 つは自然に落下し、affectedByGravity を TRUE に設定し、もう 1 つは予想される同じ重力ベクトル (x 方向に 0 ニュートン、y 方向に -9.81) で -applyForce を呼び出します。次に、1 つのタイム ステップでの各ノードの速度の差と、タイム ステップの長さを計算しました。これから、加速度(速度の変化/時間の変化)を記録しました。
これは、私の SKScene サブクラスのスニペットです。
- (id)initWithSize:(CGSize)size
{
if (self = [super initWithSize:size])
{
self.backgroundColor = [UIColor purpleColor];
SKShapeNode *node = [[SKShapeNode alloc] init];
node.path = CGPathCreateWithEllipseInRect(CGRectMake(0, 0, 10, 10), nil);
node.name = @"n";
node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:5];
node.position = CGPointMake(0, 450);
node.physicsBody.linearDamping = 0;
node.physicsBody.affectedByGravity = NO;
[self addChild:node];
node = [[SKShapeNode alloc] init];
node.path = CGPathCreateWithEllipseInRect(CGRectMake(0, 0, 10, 10), nil);
node.name = @"n2";
node.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:5];
node.position = CGPointMake(20, 450);
node.physicsBody.linearDamping = 0;
[self addChild:node];
}
return self;
}
- (void)update:(NSTimeInterval)currentTime
{
SKNode *node = [self childNodeWithName:@"n"];
SKNode *node2 = [self childNodeWithName:@"n2"];
CGFloat acc1 = (node.physicsBody.velocity.dy - self.previousVelocity) / (currentTime - self.previousTime);
CGFloat acc2 = (node2.physicsBody.velocity.dy - self.previousVelocity2) / (currentTime - self.previousTime);
[node2.physicsBody applyForce:CGVectorMake(0, node.physicsBody.mass * -150 * self.physicsWorld.gravity.dy)];
NSLog(@"x:%f, y:%f, acc1:%f, acc2:%f", node.position.x, node.position.y, acc1, acc2);
self.previousVelocity = node.physicsBody.velocity.dy;
self.previousTime = currentTime;
self.previousVelocity2 = node2.physicsBody.velocity.dy;
}
結果は異常です。シミュレーションで重力の影響を受けるノードの加速度は、力が手動で適用されたノードと比較して、一貫して 150 倍になります。さまざまなサイズと密度のノードでこれを試みましたが、同じスカラー乗数が存在します。
このことから、SpriteKit にはデフォルトの「ピクセルとメートル」の比率が内部的にあると推測する必要があります。つまり、各「メートル」は正確に 150 ピクセルに等しいということです。そうしないと、シーンが大きすぎて力の反応が遅くなることが多いため、これは便利な場合があります (飛行機を地上から見ると、飛行機は非常に高速で移動しているが、非常にゆっくりと移動しているように見えます)。スプライト キットのドキュメントでは、正確な物理計算は推奨されないことが頻繁に示唆されていますが (具体的には「数字をごまかす」セクションで確認できます)、この矛盾を特定するのに長い時間がかかりました。お役に立てれば!