16

だから私はphysicsBodyと重力がそれに影響を与えるオブジェクトを持っています。ダイナミックでもあります。

現在、ユーザーが画面に触れると、次のコードを実行します。

applyForce(0, 400)

オブジェクトは約 200 上昇し、その後重力により下降します。これは時々しか起こりません。また、オブジェクトが Y 方向に 50 単位しか移動しない場合もあります。

パターンが見つかりません... プロジェクトをドロップボックスに置いたので、誰かが見たいときに開くことができます。

https://www.dropbox.com/sh/z0nt79pd0l5psfg/bJTbaS2JpY

編集: これは、プレイヤーが衝撃の後、地面から少し跳ね返ったときに発生するようです。プレイヤーがまったく跳ねないようにする方法はありますか?

編集 2: 摩擦パラメーターを使用してこれを解決しようとしましたが、摩擦が 0 の場合にのみプレーヤーが「ジャンプ」できるようにしました (これは、プレーヤーが空中にいるすべてのケースであると考えられます) が、摩擦は 0 より大きいように見えます常に。プレイヤーがオブジェクトに触れているかどうかを検出する方法はありますか (y 位置を使用する以外に)。

ありがとう

4

2 に答える 2

19

@ 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 ピクセルに等しいということです。そうしないと、シーンが大きすぎて力の反応が遅くなることが多いため、これは便利な場合があります (飛行機を地上から見ると、飛行機は非常に高速で移動しているが、非常にゆっくりと移動しているように見えます)。スプライト キットのドキュメントでは、正確な物理計算は推奨されないことが頻繁に示唆されていますが (具体的には「数字をごまかす」セクションで確認できます)、この矛盾を特定するのに長い時間がかかりました。お役に立てれば!

于 2013-11-17T21:52:52.440 に答える