物理エンジン 2.0

物理エンジン ビヘイビアをオブジェクトに追加すると、物理法則にのっとったリアルな挙動でオブジェクトを移動できます。拡張機能は内部的に Box2D を使っています。これは高速で完全な剛体物理シミュレーションライブラリです。

ビヘイビアは 3 つの大きな概念で構成されています。ボディを含むワールド、ボディ、およびボディをリンクするジョイントです。これらすべてについて、ここでくわしく説明します。

制限事項:上記で述べられているように、この拡張機能は剛体の物理シミュレーションです。つまりボディは変形できません。やわらかい形状、衣服、液体などには対応していません。

ワールド

ワールドはシミュレーションが実行される場所です。ボディとジョイントはワールドに追加することで、他のエンティティと相互作用できるようになります。
ただしこれは原理の説明であって、実際に自分でワールドにオブジェクトを配置する必要はありません。物理ビヘイビアを使用するオブジェクトは、ワールドに自動的に追加されます。また、ワールドは一度に 1 つしか存在できません。2 つの独立したシミュレーションを同時に実行することはできません。
GDevelop のシーンサイズと同様に、ワールドサイズは無限であるため、オブジェクトがどこにあるのかを気にする必要はありません。オブジェクトは常に物理法則に従います。

ワールドには 3 つのプロパティがあります。

  • 重力:2 つの成分(X と Y)で構成され、おなじみの重力のように機能し、すべてのオブジェクトに力を加えて、それらを指定された方向に押します。オブジェクトは重力スケール係数にも対応していますが、これについてはボディに関する節でくわしく説明します。
  • タイムスケール:シミュレーションが使用する時間のスケールを定義します。タイムスケール= 0.5 の場合はシミュレーションが半分の速度で実行され、タイムスケール= 2 の場合はシミュレーションが 2 倍の速度で実行され、タイムスケール= 0 の場合はシミュレーションが一時停止します。バレットタイム(スローモーション)エフェクトにたいへん便利です。
  • スケール:GDevelop は距離やサイズをピクセル単位で扱いますが、物理エンジンはメートル法を使用します。そこで単位変換のためにスケールファクター(拡大率)を設定する必要があります(ここにもスケール X と Y の 2つの成分があります)。スケールの数値は、1 メートルが何ピクセルかを表しています。たとえばスケー ル値 50 は、GDevelop 内で 50 ピクセルの距離が物理演算ワールドの 1 メートルに変換されることを意味します。
ワールドスケールを決定するにあたって最も重要なルールは、可動/ダイナミックオブジェクトのサイズが 0.1〜10 メートルの範囲内におさまるようにすることです。この範囲を外れると、シミュレーションの精度が失われます。たとえば 100 × 100 ピクセルていどのオブジェクトサイズで作業している場合、ワールドスケール 100 なら問題ありません。この場合オブジェクトのボディサイズは約 1 x 1 メートル相当になります。スタティックオブジェクトの場合はもっと長くでき、50 メートルに拡大しても大丈夫です。

ボディ

ボディは物理エンジン拡張機能の中核です。これはオブジェクトがどのように動くか、どんな形状をとるか、どれだけ跳ね返るのか、回転できるのか、移動できるのかなどを定義します。

物理エンジンビヘイビアをオブジェクトに追加すると、エディター上で直接ボディの設定を調整できます。
たくさんのオプションがあるため、以下に分類して説明します。

ボディタイプ

GDevelop は 3 つの基本的なボディタイプをサポートしています。

  • ダイナミック:もっとも一般的なタイプであるダイナミック(動的)ボディは重力の影響を受け、他のダイナミックボディ、スタティックボディ、キネマティックボディと衝突させることができます。フォースとインパルスを適用し、速度も変更できます。移動しなければならないものはほとんど、ダイナミックボディにする必要があります。
  • スタティック:スタティック(静的)オブジェクトは重力の影響を受けず、フォースやインパルス、速度の変更によって移動しません。ダイナミックオブジェクトのみと衝突し、キネマティックやほかのスタティックボディを無視します。地面、動かない壁、プラットフォームなど、ワールド内の静的な構造物に適しています。
  • キネマティック:キネマティックは非常に特殊です。スタティックオブジェクトのように重力やフォース、インパルスの影響を受けませんが、ダイナミックオブジェクトのように速度を設定して移動できます。キネマティックはダイナミックオブジェクトとのみ衝突し、移動する壁やプラットフォームをシミュレートするのに最適です。

ダイナミック関連設定:

  • バレット:「はい」(またはチェックをオン)に設定すると、オブジェクトは継続的衝突検出アルゴリズムを使用します。パフォーマンスは若干犠牲になりますが、高速移動時の衝突判定精度が大幅に改善します。弾丸(または非常に高速なオブジェクト)を正しくシミュレートするのに役立ち、弾丸が細いオブジェクトをすり抜けてしまう可能性を減らします。
このオプションは本当に必要なときだけ使うようにしてください。移動するオブジェクトすべてに使用すると、パフォーマンスに深刻な影響を与える可能性があります。
  • 回転を固定:「はい」(またはチェックをオン)に設定すると、オブジェクトは回転しなくなります。プレーヤーが壁に衝突するたびに、あるいは斜面をくだっているあいだじゅう、回転してしまうことを想像すると、このオプションの存在意義が理解できるでしょう。
  • スリープ可能:「はい」(またはチェックをオン)に設定すると、しばらく動かなかったオブジェクトを物理エンジンがスリープ状態にしてパフォーマンスを向上できます。これは単なるパフォーマンス設定であり、シミュレーション自体には影響しません。
イベント条件を使用して、ボディがスリープしているかどうかを確認できます。オブジェクトがスリープ中であれば、それはしばらく安定状態にあったことを意味し、バランスゲームを作成するのに役立ちます。

ボディシェイプ

ボディシェイプの設定はボディの形状とサイズを決定します。シェイプタイプに応じて、その大きさを調整するためのさまざまな設定があります。

  • ボックス(四角形):オブジェクトの中心軸に沿った長方形です。幅と高さを特に指定しなければ、オブジェクトと同じ大きさになります。
  • サークル(円形):オブジェクトを中心とする円です。半径を特に指定しなければ、オブジェクトの幅と高さの平均で計算されます。オブジェクトが正方形の場合は、オブジェクトの境界ボックス内に内接する円になります。
  • エッジ(線形):オブジェクトの中心に沿った細い線です。このシェイプには体積(面積)がないため、ダイナミックボディとしては正常に機能しません。地面やプラットフォームなどのスタティックな形状に使用することを想定しています。長さと角度を特に指定しなければ、エッジはオブジェクトの幅と同じ長さの水平線になります。
  • ポリゴン(多角形):頂点によって定義されるカスタム形状です。ポリゴンは凸面である必要があり、この条件が満たされない場合、形状はデフォルトのボックスにフォールバックします。頂点の数は 3 以上(そうでないと凸状にできないので)、8 以下(ポリゴンが保持できる頂点の最大数)です。3 ≦ 頂点数 ≦ 8。

カスタムシェイプタイプと大きさに加えて、ボディシェイプは 2 つの追加設定を持ちます。

  • オフセット:オフセットには 2 つの成分(X と Y)があり、オブジェクトの中心からシェイプをずらすために使います。
  • スケール:シェイプも拡大縮小できます。これはシェイプの大きさとオフセットをスケールします。大きさを指定しなければ、たとえばボックスシェイプは元のオブジェクトと同じ大きさになります。この場合は自動的にスケーリングするので、シェイプのスケールを変更する必要はありません。シェイプタイプがポリゴンの場合、スケールすると頂点の位置も移動します。スケーリングの原点はポリゴン原点になります。(訳注:ビヘイビアの設定画面にあるオプションは 2021/1 時点で多言語化対応していないため、言語設定が日本語であっても「Polygon Origin」と表示されます)ポリゴン原点を「中央」に設定してシェイプを縮小すると、頂点はオブジェクトの中央に向かって移動します。

ボディの設定

物理ボディには、タイプと形状に加えて、衝突時のボディの動作、重力によるボディへの影響、および空気抵抗によって失われるエネルギーを指定する追加の設定があります。各設定は以下の通りです。

  • 密度(Density):密度は重さを決定します。一般的な公式は 密度=質量÷体積 ですが、3 次元の奥行きがないため、これを 密度=質量÷面積 と仮定して問題ありません。同じ密度で面積/大きさの違う 2 つのボディは違う質量になります。したがってオブジェクトのサイズを変更するときは密度も考慮する必要があります。

    密度はマイナスになりません!
  • 摩擦(Friction):摩擦は、何かと接触中のボディに移動方向と反対の方向に力を加えます。摩擦が大きいほど、接触中のオブジェクトは速度が低下します。具体例を挙げると、砂で作られたプラットフォームの摩擦はほとんど 1(非常に高い)になり、氷で作られたプラットフォームの摩擦係数はほぼ 0 になります。

    摩擦はマイナスになりません!

    2 つのオブジェクトが接触しているときの摩擦の合計は、オブジェクトの摩擦係数を使った式 friction = sqrt(frictionA * frictionB) で計算されます。
  • 反発(Restitution):オブジェクトが各衝突で保持するまたは失うエネルギーの割合を指定します。値ゼロは衝突が完全に非弾性であり、オブジェクトがまったく跳ね返らないことを意味します。反発= 1 の場合、衝突は完全に弾性的であり、オブジェクトは毎回同じエネルギーで跳ね返ります。ボールを地面に落とすと、毎回同じ高さまで跳ね返り続けると想像してください。1 より大きい反発の値も有効ですが、衝突のたびにオブジェクトにエネルギーが与えられ、おそらくシミュレーションが制御不能になります。

    反発はマイナスになりません!

    2 つのオブジェクトが衝突したときの反発の合計は、オブジェクトの反発係数を使った式 restitution = max(restitutionA, restitutionB) で計算されます。
  • 線形減衰(Linear Damping):線形減衰は、常にオブジェクトの速度を低下させます。値が大きいほど、オブジェクトの速度が急速に低下します。空気抵抗を想像するといいでしょう。値をとても大きくすると、液体内を移動するオブジェクトをシミュレートできます。

    任意の値を使用できますが、マイナスの値を設定するとオブジェクトが速度を増していき、非物理的な動きになります
  • 角度減衰(Angular Damping):角度減衰は線形減衰に似ていますが、オブジェクトの線形速度が遅くなる代わりに角速度を低下させ、オブジェクトの回転がゆっくりになっていきます。

    任意の値を使用できますが、マイナスの値を設定するとオブジェクトが角速度を増していき、非物理的な動きになります
  • 重力スケール(Gravity Scale):ワールドの重力に重力スケールを掛けた値が、オブジェクトに適用する重力になります。これはベクトルではなく数値であることに注意してください。重力の向きは変更できず、その強さだけを変更できます。任意の数値が有効です。いくつかの例を挙げましょう。重力スケールが 1 の場合、適用される重力はワールド重力そのままになります。2 の場合、このオブジェクトの重力は 2 倍になり、0.5 の場合、重力は半分になります。0 の場合、オブジェクトは重力の影響を受けません。-1 の場合、重力は反転します。
負の重力スケールを設定して、特定のオブジェクトの重力を反転できます。

レイヤーとマスク

レイヤーとマスクは、オブジェクト間の衝突をフィルタリングする方法です。ゾンビのゲームを作成しているものと想像してください。プレイヤーを地面と衝突させ、ゾンビをプレイヤーとも地面とも衝突させたいが、ゾンビ同士を衝突させたくはありません。このような場合に、衝突フィルターが必要になります。

フィルターはどのように機能するのでしょうか?  ルールはたった 1 つです。

2 つのオブジェクト A と B は、A のレイヤーのどれかが B のマスクのどれかに一致し、なおかつ B のレイヤーのどれかが A のマスクのどれかに一致した場合に、衝突可能になります

先ほどのゾンビ問題は、次のようにすると解決します。

  • 地面:最初のレイヤーと、最初と 2 番目のマスクを有効にします。
  • プレイヤー:最初のレイヤーと、最初と 2 番目のマスクを有効にします。
  • ゾンビ:2 番目のレイヤーと、最初のマスクのみを有効にします。

なぜこれでうまくいくのでしょうか。

  • 地面とプレイヤー:地面のレイヤーはプレイヤーのマスク(最初)と一致し、なおかつプレイヤーのレイヤーが地面のマスク(最初)と一致します。
  • 地面とゾンビ:地面のレイヤーはゾンビのマスク(最初)と一致し、なおかつゾンビのレイヤーが地面のマスク(2 番目)と一致します。
  • プレイヤーとゾンビ:プレイヤーのレイヤーはゾンビのマスク(最初)と一致し、なおかつゾンビのレイヤーがプレイヤーのマスク(2 番目)と一致します。
  • ゾンビとゾンビ:ゾンビは 2 番目のレイヤーだけが有効で、最初のマスクだけが有効です。そのためゾンビ同士は衝突できません。

最大で 16 個のレイヤーと 16 個のマスクを利用できます。今回このちょっとした問題を解決するには、2 つずつのレイヤーとマスクで十分でした。

移動

オブジェクトの設定が済んだら、シミュレーションが始まります。重力が物を押しはじめ、オブジェクトが動き、衝突しますが、プレイヤーは見ているだけで何も操作できません。自分でオブジェクトを移動できるようにするには、イベントシステムを使う必要があります。オブジェクトとやり取りし、希望する方法でオブジェクトを移動するための便利なアクションを次に示します。

GDevelop の組み込み機能であるフォース(移動カテゴリー)は、物理エンジンビヘイビアと組み合わせて使用できません。ビヘイビアを使う場合は、組み込み機能の代わりに物理エンジンが提供するアクションを使用しましょう。
  • フォース:フォースはオブジェクトを移動させるために加えられる力です。フォースは一般的に、オブジェクトに一定時間使用して、その動きを大きく変更します。オブジェクトにフォースを適用したときに生じる速度は、フォースの大きさとオブジェクトの質量に依存します。同じフォースが適用された場合、重いオブジェクトは軽いオブジェクトよりもゆっくり動きます。

    フォースを適用する場合は作用点の指定が必須です。

  • トルク:フォースに似ていますが、こちらは移動ではなく回転力です。トルクはオブジェクトに角加速度を与え、時間の経過とともに回転を速くしたり遅くしたりします。
  • インパルス:フォースに似ていますが、タイムステップに依存しません。代わりに「一定量」の速度を瞬間的に与えます。単発での使用を想定しています。ジャンプのシミュレーションではこれが日常的に使われています。ジャンプボタンを押すたびに、上向きのインパルスを追加します。

    インパルスを追加する場合は作用点の指定が必須です。

  • 角度インパルス:インパルスに似ていますが、こちらは回転力に作用して、回転速度を瞬間的に変更します。
  • 速度:オブジェクトの速度を直接変更できます。たとえば一定速度で歩行しているキャラクターの速度を、ボタンを押したタイミングで変更します。
  • 角速度:角速度(回転速度)も直接変更できます。
オブジェクトの位置も直接変更できますが、少なくとも新しい位置が修正されるまでは非物理的な動きになるでしょう。実生活では、オブジェクトはまったくテレポートしません。

フォースとインパルスには作用点が必要なことに注意してください。これはとても重要です。花瓶の下を押す(移動する)ことと、上を押す(たぶん倒れる)ことは同じではありません。ドアを押し開けるときは、蝶つがいではなくドアノブ側を押すはずです。
作用点がオブジェクトの質量中心と異なる場合、何らかの種類のトルク/回転が生じるでしょう。

オブジェクトの質量中心は、物理エンジンビヘイビアの式 MassCenterX()MassCenterY() で取得できます。

ジョイントでオブジェクトの動きを制御する

ジョイントは、何らかのルールにのっとってオブジェクトの動きを制限します。あるジョイントはオブジェクトの回転中心を固定して、別のジョイントは 2 つのオブジェクトを連結します。複雑なジョイントになるとこれを組み合わせて、ボディ間の距離を一定に保ったまま自由に回転させて、自動車の車輪をシミュレートするといった具合です。

ジョイント ID
ジョイントを作成するときに、変数名を渡すことができます。GDevelop は指定された変数に、ジョイントの一意の識別番号(ID)を格納します。このジョイント ID を指定することで、作成後のジョイントを変更したり、プロパティ値を確認したり、削除できます。屋根からひもで鍵を吊り下げるジョイントを想像してください。このジョイント ID を変数に保存しておくと、あるオブジェクトがひもと衝突しているかどうかを確認し、保存された ID を指定してジョイントを削除し、鍵を落とすことができます。

ジョイント ID は常にゼロよりも大きい数値になります。

一般的にはジョイントには 2 つのオブジェクト(先ほどの例ではひもと鍵)が必要ですが、一部の「例外」があります。くわしくは回転ジョイントの説明を参照してください。

すべてのタイプのジョイントに共通のプロパティ、条件、およびアクションのリストは次のとおりです。

  • ジョイントの最初/2 番目のオブジェクトである:検査するオブジェクトが指定したジョイントの最初または 2 番目のオブジェクトであれば、それを選択する条件です。
  • ジョイントの最初/2 番目のアンカーの X/Y 位置:指定したジョイントの最初または 2 番目のアンカーポイントの位置を取得する式です。
  • ジョイントの反動力/反動トルク:ジョイントの反動力または反動トルクをチェックする条件と式です。この値はジョイントが平衡状態からどのていどかけ離れているかを示す指標になります。ジョイントの反動力が大きいと、ジョイントがかなり大きな力で平衡位置から引き離されたことを意味します。壊れやすいジョイントを作るのに便利です。
  • ジョイントを削除する:指定したジョイントを削除するアクションです。もしジョイントが歯車ジョイントの子だった場合は、歯車も削除されます。またジョイントが接続しているオブジェクトがどれか削除されると、ジョイントも削除されます。

ジョイントにはさまざまな種類があり、それぞれに固有の動作とプロパティがあります。以下に一覧を示します。

1 回だけ実行されるイベント(たとえばシーンの開始時)でジョイントを作成するように注意してください。もしフレームごとにジョイントを作成すると、数秒で数百のジョイントが作成され、パフォーマンスの低下や非物理的な動作、メモリ枯渇によるクラッシュのおそれがあります。

距離ジョイント

距離ジョイントは 2 つのオブジェクトを指定した距離で分離しようとします。距離はジョイントのアンカーポイントを基準に計算します。 オブジェクトが指定した距離を常に保てるとは限りませんが、オシレーターの式にもとづいて距離を保とうとし続けます。

設定:

  • 長さ:目標距離です。マイナス値を設定した場合は、ジョイント作成時のオブジェクト間の距離が使用されます。
  • 減衰率:オブジェクトが受ける「抵抗」です。値が低いとオブジェクトは速く動き、値が高いとオブジェクトはゆっくり動きます。
  • バネの硬さ:オブジェクトが振動する速さです。オブジェクトを目標の長さに近づける力の強さです。値が大きいほどオブジェクトは強い力で引かれ、短い時間で目標の長さに戻ろうとします。
減衰率とバネの硬さの値を低くすると、目標の長さに近づくまでに時間がかかる柔らかいジョイントになります。一方、両方の値を高くすると、非常に硬いジョイントになります。

回転ジョイント

回転ジョイントは「ピン」のように機能します。「ヒンジ(蝶つがい)」とも呼ばれ、ある一点を中心にオブジェクトを回転させます。 回転ジョイントには 2 つのタイプがあります。ほとんど同じですが、ちょっとした違いがあります。

  • 2 つのオブジェクト間の回転ジョイント:2 つのオブジェクトを「ピン留め」します。オブジェクトはアンカーポイントを共有する形で一緒に移動し、またオブジェクトはそれぞれアンカーポイントを中心に回転します。2 枚のカードをピンで留めて、それを飛ばしたところを想像してみてください。カードは一緒に移動し、ピンを中心に自由に回転するでしょう。
  • 1 つのオブジェクトの回転ジョイント:ジョイントは通常 2 つのオブジェクト間で機能しますが、これは例外の 1 つです。このジョイントは単一のオブジェクトとそのアンカーポイントを使って、指定した位置にオブジェクトをピン留めします。壁にメモを留めたようなものだと考えてください。メモはピンを中心に回転できますが、移動はできません。
単一オブジェクトバージョンのジョイントでは、オブジェクトはジョイントの 2 番目のオブジェクトとして追加されます。最初のオブジェクトは非表示のスタティックボディになります。そのため、このタイプのジョイントを歯車ジョイントに使うことができます。くわしくは歯車ジョイントの節で説明します。

回転ジョイントで設定できる項目は次のとおりです。

  • 角度制限:有効にすると、回転は最小角度と最大角度のあいだに制限されます。角度は両方とも最初のオブジェクトに対する相対指定です。
  • 基準角度:ゼロと見なされるオブジェクト間の角度。すべての角度プロパティでオフセット値として使われます。基準角度が 15 度で、ワールド座標におけるオブジェクト間の角度が 15 度の場合、現在のジョイント角度を取得すると 0 が戻ります。また最大角度を 30 に設定すると(最初のオブジェクトに対して)45 に設定されます。
  • 最小角度:最初のオブジェクトに対するオブジェクト間の最小角度。最大角度以下でなければなりません。
  • 最大角度:最初のオブジェクトに対するオブジェクト間の最大角度。最小角度以上でなければなりません。
角度制限のある回転ジョイントを使用すると、関節をシミュレートできます。つまりラグドールを作れます。
  • モーター:有効にすると、ジョイントは 2 番目のオブジェクトにトルク(回転力)を追加し、外部から力を与えなくても回転するようにします。モーターのように。有効にした場合、モーター速度と最大モータートルクを設定することを忘れないでください。
  • モーターの速度:目標とするモーター速度(度/秒)。これは 2 番目のオブジェクトが最初のオブジェクトの周りを回転しているときに到達しようとする速度です。モーター速度を正の値にするとオブジェクトは時計回りに回転し、負の値にすると反時計回りに回転します。
  • モーターの最大トルク:モーターが目標モーター速度に到達するために発揮できる回転力の最大値。正の値でなければなりません。

またシミュレーション中に次の値を取得できます。

  • ジョイント角度:オブジェクト間の現在の角度。最初のオブジェクトに対する相対角度で、基準角度の影響を受けます。
  • ジョイント速度:オブジェクト間の現在の角速度。最初のオブジェクトに対する 2 番目のオブジェクトの相対角速度です。
  • ジョイントのモータートルク:現在のモータートルク(回転力)。最大モータートルク以下で、目標モーター速度に到達するために必要なトルクになります。
回転ジョイントの使いみちには、ピンボールレバー、トップダウンビューにおけるドア、巻き上げ式の可動橋などがあります。

直動ジョイント

直動ジョイントは「ピストン」のように機能し、「スライダー」としても知られています。ある軸に沿って、オブジェクトを前後にスライドさせます。エレベーターがよい例になるでしょう。エレベーターはレールに沿って上下に移動します。レールは最初のジョイントボディに、エレベーターは 2 番目のジョイントボディに相当します。軸は真上または真下(-90 度または 90 度)を向きます。

直動ジョイントで設定できる項目は次のとおりです。

  • 軸角度:移動方向を示す角度。軸角度 0 は水平移動を意味します。値はワールド座標で指定しますが、最初のオブジェクトが回転した場合は、軸もそれに従って回転します(もしエレベーターレールを回転させると、エレベーターの移動角度も回転するのと同じ理屈です)。
  • 基準角度:回転ジョイントの場合と同様に、この角度は軸にオフセットを設定し、新しい「角度ゼロ」を定義します。基準角度が 15 の場合、(最初のオブジェクト方向に対する)ワールド座標での軸角度 15 は 0 として扱われます。
  • 移動制限:有効にすると、2 番目のオブジェクトの動きは、指定された最小移動量と最大移動量のあいだに制限されます。
  • 最小移動量:2 番目のオブジェクトが最初のオブジェクトから移動できる最小位置。エレベーターの例でいえば、最小移動は地上階になるでしょう。
  • 最大移動量:2 番目のオブジェクトが最初のオブジェクトから移動できる最大位置。エレベーターの例でいえば、屋上階です。
移動制限範囲にはゼロを含める必要があるため(訳注:ジョイント作成時の位置が 0 になるため)、最小移動量 5 と最大移動量 10(範囲 [5, 10])を指定した場合、ゼロを含む範囲 [0, 10] に変換されます。
  • モーター:有効にすると、ジョイントは 2 番目のオブジェクトにフォースを適用し、モーター速度に到達しようとします。有効にした場合、モーター速度とモーターの最大出力を設定することを忘れないでください。
  • モーターの速度:目標とするモーター速度。正の値であれば 2 番目のオブジェクトは軸と同じ方向に動き、負の値であれば反対方向に動きます。
  • モーターの最大出力:モーターが目標モーター速度に到達するために発揮できるフォースの最大値。正の数値でなければなりません。

またシミュレーション中に次の値を取得できます。

  • ジョイント移動量:最初のオブジェクトに対する 2 番目のオブジェクトの現在の移動量です。
  • ジョイント速度:最初のオブジェクトに対する 2 番目のオブジェクトの現在の軸上速度です。
  • ジョイントのモーター出力:2 番目のオブジェクトの現在のモーター出力(フォース)。モーターの最大出力以下で、目標モーター速度に到達するために必要な力になります。

滑車ジョイント

滑車ジョイントは名前のとおりのシンプルなジョイントです。このジョイントは、各オブジェクトから地面までの距離の合計が常に一定になるようにします。もっと分かりやすい説明をするなら、要は滑車をシミュレートします。:-)

固定ポイント A から 3 メートル吊り下げたボックスと、固定ポイント B から 2 メートル吊り下げたサークルがあり、両方のオブジェクトが同じロープの端に取り付けられているとします。ロープの長さは一定なので、もしボックスを A から 1 メートルの位置まで持ち上げると、サークルは同じ分だけ下がって B の下 4 メートルの位置に移動します。この場合でも、ボックスから A までの距離とサークルから B までの距離の合計は、変わらず 5 メートルのままです。
distance(box, A) + distance(circle, B) = constant

比率
簡単でしょう? さて、ここから奇妙な展開になりますが、このジョイントにはある特殊な設定が存在します。「比率」です。この比率により、ロープは一方の側で他方よりも伸びやすくなります。たとえばボックス側の 1 メートルのロープを、サークル側の 2 メートルのロープと等価にすることができます(比率= 1/2 = 0.5)。

先ほどの例に戻ってみましょう。A の 3 メートル下にボックスが吊り下げられ、B の 2 メートル下にサークルが吊り下げられています。ただし今回は比率= 0.5 です。ボックスを 2 メートル持ち上げると、サークルは 4 メートル下がります。ロープの長さは、明らかに一定ではありません。しかし次の式が成り立っています。
distance(box, A) + ratio*distance(circle, B) = constant (最初の式は、この式が比率= 1 の場合の特殊なケースだったことがお分かりでしょう)

また「ロープ」はどこにも存在しないことに注意してください。ジョイントは、オブジェクトとアンカーポイントのあいだの距離だけで機能します。

このジョイントの設定項目は次のとおりです。

  • 最初の接地アンカー:最初のオブジェクトが接続される固定ポイント(例ではポイント A)。
  • 2 番目の接地アンカー:2 番目のオブジェクトが接続される固定ポイント(例ではポイント B)。
  • 最初の長さ:最初のオブジェクトとその接地アンカーのあいだの初期状態のロープの長さ。値が負またはゼロの場合は、ジョイント作成時の距離が使用されます。
  • 2 番目の長さ:2 番目のオブジェクトとその接地アンカーのあいだの初期状態のロープの長さ。値が負またはゼロの場合は、ジョイント作成時の距離が使用されます。
  • 比率:上記で説明した、両側の距離の比率。比率が 0.33 の場合、1 番目の側の 1 メートルは 2 番目の側の 3 メートルに相当します。

歯車ジョイント

このジョイントは非常に特殊で、2 つのボディを直接つなぐのではなく、歯車が他の 2つのジョイントを連結します。これらの子ジョイントは回転または直動ジョイントでなければなりません。
2 つのジョイントが歯車ジョイントを介してリンクされている場合、一方のジョイントが動くと、もう一方のジョイントも動きます。たとえば直動ジョイントの軸に沿ってオブジェクトを移動すると、リンクされた回転ジョイントが回転します。逆も同様です。

このジョイントも非常に注意が必要です。歯車が機能するには、各子ジョイントの最初のボディがスタティックで、2 番目のボディがダイナミックである必要があります。
2 つの回転ジョイント、2 つの直動ジョイント、または回転ジョイントと直動ジョイントを歯車で連動させることができますが、常に各ジョイントの最初のボディはスタティックでなければなりません。

歯車の子ジョイントの最初のボディはスタティックででなければならないという、このことこそが、回転ジョイントの単一オブジェクトバージョンの最初のボディが非表示のスタティックオブジェクトである理由です。

歯車ジョイントの設定項目は次のとおりです。

  • 最初のジョイント:2 番目のジョイントとリンクする回転ジョイントまたは直動ジョイント。
  • 2 番目のジョイント:最初のジョイントとリンクする回転ジョイントまたは直動ジョイント。
  • 比率:滑車ジョイントと同じく、歯車は「比率」に対応しており、似たような感じで機能します。比率= 0.33 で 2 つの回転ジョイントをリンクした場合、最初の子ジョイントの 1 回転は 2 番目の子ジョイントの 3 回転に相当します。ただし滑車ジョイントの比率とは違う部分もあります。歯車の比率はマイナス値にも設定でき、そうした場合は一方のジョイントでプラスに動くと、もう一方のジョイントはマイナスに動きます。たとえば比率= -1 で 2 つの回転ジョイントをリンクした場合、片方の回転ジョイントを時計回りに回すともう片方は反時計回りに回ります。本物の歯車のように。
ギアの存在に必要な条件は、2 つの子ジョイントが存在することです。2 つの子ジョイントのいずれかが削除されると、ギアも自動的に削除されます。

マウスジョイント

このジョイントは必ずしもマウスに関連しているわけではありませんが、しかしその使い方が一般的です。このジョイントは、オブジェクトを目標に向かって移動します。目標位置をマウスまたはタッチ位置で連続的に更新すると、オブジェクトをドラッグできます。

これもまた例外の 1 つですが、これは動作するためにボディを 1 つだけ必要とするジョイントです。ボディとはつまり、目標に向かって移動させるオブジェクトです。

マウスジョイントの設定項目は次のとおりです。

  • オブジェクト:目標位置に向かって移動するオブジェクト。
  • 目標:オブジェクトが到達しようとするターゲットポイント。ジョイントを作成した後、目標位置は何度でも更新できます。
最初の目標位置(ジョイントの作成時)は、オブジェクトのアンカーポイントとしても使用されるため、必ず設定してください。
  • 最大出力:目標位置に到達するためにジョイントがオブジェクトに適用できるフォースの最大値。数値が大きいほど、オブジェクトは速く動きます。正の数値でなければなりません。
  • バネの硬さ:距離ジョイントのバネの硬さと同じような機能で、どれだけ速くオブジェクトが目標位置に移動するかを設定します。
  • 減衰率:距離ジョイントの減衰率と同じような機能で、時間の経過とともにオブジェクトの移動速度をゆっくりにします。
マウスジョイントは、マウスでの使用のみに限定されているわけではありません。任意のワールド座標を目標に指定できます。

車輪ジョイント

特定用途に特化したジョイントです。車輪が必要になったら、このジョイントの出番です。乗り物などの車輪以外の用途を挙げるのはかなり難しいし、実際、車輪に使うなら車輪ジョイントが最善の選択肢です。
もともと乗り物の車輪をシミュレートするために作られたので、このジョイントにはそれしかできませんが、その代わり非常にうまくシミュレートします。

車輪ジョイントは、回転ジョイントと直動ジョイントを組み合わせたようなものです。
ここでの回転ジョイントは 2 番目のオブジェクト(車輪)を回転させるために使用されます。また回転ジョイントにはモーター機能もあるので、自動車両のモーターをシミュレートして車輪を回転させることができます。
直動ジョイント機能は、車両のホイールサスペンションのシミュレートに使われます。直動ジョイントの軸角度を設定して、車輪の移動方向を定義できます。一般に軸の方向は垂直ですが、たとえばバイクの場合などは前輪のサスペンションの方向が垂直ではない(場合によってはかなり傾いている)ことがあります。

車輪として機能するボディは、ジョイントの 2 番目のオブジェクトでなければなりません。

車輪ジョイントの設定項目は次のとおりです。

  • 軸角度:直動ジョイントの軸角度に相当し、車輪と最初のオブジェクト間の移動(またはスライド)方向を決定します。
  • バネの硬さ:サスペンションの硬さで、距離ジョイントのバネの硬さに相当します。値が大きいほど、硬いサスペンションになります。
  • 減衰率:サスペンションの減衰率で、距離ジョイントの減衰率に相当します。値が大きいほど、車輪は緩やかに戻ろうとします。
  • モーター:有効にすると、ジョイントは車輪(2 番目のオブジェクト)にトルクを追加し、モーター速度に到達しようとします。有効にした場合、モーター速度と最大モータートルクを設定することを忘れないでください。
  • モーターの速度:車輪が回転目標とする角速度。正の値を設定すると時計回りに、負の値を設定すると反時計回りになります。
  • モーターの最大トルク:目標モーター速度に到達するためにジョイントが車輪に適用できる回転力の最大値。正の数値でなければなりません。

またシミュレーション中に次の値を取得できます。

  • ジョイント移動量:サスペンション軸に沿った現在の車輪移動量。
  • ジョイント速度:現在の車輪回転速度。
  • ジョイントのモータートルク:車輪に適用されている現在のモータートルク(回転力)。最大モータートルク以下で、目標モーター速度に到達するために必要なトルクになります。

溶接ジョイント

これはとても基本的なジョイントで、2 つのオブジェクトをただくっつけて、それが 1 つであるかのように動かします。

これを使って壊れやすいオブジェクトを作成できますが、乱用はしないでください。つまるところ、オブジェクトはソフトジョイントで接続されるだけです。密度がばらばらのオブジェクトを多数接続すると、物理演算が不正確になるおそれがあります。

溶接ジョイントの設定項目は次のとおりです。

  • 基準角度:最初のオブジェクトの角度に対する 2 番目のオブジェクトの角度。
オブジェクトをジョイント作成時の角度で固定するには、オブジェクト間の相対角度(SecondObject.Angle() - FirstObject.Angle())を基準角度として使用します。
  • バネの硬さ:距離ジョイントのバネの硬さと同じような機能で、どれだけ速くオブジェクトが静止位置に移動するかを設定します。
  • 減衰率:距離ジョイントの減衰率と同じような機能で、時間の経過とともにオブジェクトの移動速度をゆっくりにします。

ロープジョイント

また別の単純なジョイントです。ロープジョイントは 2 つのオブジェクトをロープで仮想的につなぎます。この方法では、ロープの長さよりも遠い距離にオブジェクトを引き離すことはできませんが、それ以下の距離であれば自由に配置できます。

滑車ジョイントが滑車自体を持たないように、ここにロープ自体は存在しません。ジョイントはただオブジェクト間の距離をチェックし、距離が所定の長さより大きい場合に反応します。

ロープジョイントの唯一の設定項目は次のとおりです。

  • 最大長:オブジェクト間の最大距離。初期値が負の場合、ジョイント作成時のオブジェクト間の距離が使用されます。

摩擦ジョイント

摩擦ジョイントは Z 軸の摩擦をシミュレートします。線形摩擦と角摩擦をシミュレートして、2 つのオブジェクト間の相対速度や角速度を遅くします。

オブジェクトの 1 つがスタティックの場合、摩擦ジョイントを使用してトップダウン形式のゲームで摩擦を正しくシミュレートできます。ビリヤード台やトップダウン形式のレーシングゲームに最適です。

摩擦ジョイントの設定項目は次のとおりです。

  • 最大出力:ジョイントがオブジェクトに適用できるフォースの最大値。数値が大きいほど、強い線形摩擦が働きます。
  • 最大トルク:ジョイントがオブジェクトに適用できる回転力の最大値。数値が大きいほど、強い角摩擦が働きます。

モータージョイント

モータージョイントは実在するモーターにはあまり似ておらず、少なくとも直接の関係はありません。2 つのオブジェクトをモータージョイントでリンクすると、オブジェクトはオフセットを考慮した他のオブジェクトとの相対的な目標位置や目標角度に到達しようとします。

次の 2 点を考慮する必要があります。

  • ジョイントは剛性ではありません。オブジェクトは目標の位置または角度から遠く離れる可能性があります。補正係数は、安定姿勢に移行するためにどれだけ速く移動および回転するかを示します。

たとえば、常に立ち上がるパンチングバッグのおもちゃの 1 つを想像してください。地面とバッグをリンクするモータージョイントを使用して、これをシミュレートできます。この場合、バッグオブジェクトをどれくらい強く押しているかに関わらずジョイントはそれを元の角度に戻そうとしますが、必ず戻せるとは限りません。

  • 障害物がある場合、モータージョイントは停止します。

パンチングバッグの例に戻ると、何か大きな物体でバッグを地面に押さえつけた場合、現実がそうであるように、モータージョイントもこれを押し戻すことができません。

このジョイントはアンカーポイントを使いません。オフセット位置は、線形オフセットと角度オフセットのみを使用して設定しなければなりません。このジョイントのアンカーポイントにアクセスすると、オブジェクトの位置が返ります。

モータージョイントの設定項目は次のとおりです。

  • オフセット X/Y 位置:最初のオブジェクトに対する 2 番目のオブジェクトのオフセット位置。ジョイント作成時のオブジェクトの位置をそのまま設定するには、SecondObject.X() - FirstObject.X()SecondObject.Y() - FirstObject.Y() の式を使います。
  • オフセット角度:最初のオブジェクトに対する 2 番目のオブジェクトの角度オフセット。ジョイント作成時のオブジェクトの角度をそのまま設定するには、SecondObject.Angle() - FirstObject.Angle() の式を使います。
  • 最大出力:オブジェクトを目標位置に移動するためにジョイントがオブジェクトに適用できるフォースの最大値。数値が大きいほど、オブジェクトは速く動きます(そうする必要があれば)。この値がゼロの場合は、線形補正が働かず、オブジェクトは目標位置に向かって移動しません。
  • 最大トルク:ジョイントが目標角度に回転するためにオブジェクトに適用できる回転力の最大値。数値が大きいほど、オブジェクトは速く回転します(そうする必要があれば)。この値がゼロの場合は、角度補正が働かず、オブジェクトは目標角度に向かって回転しません。
  • 補正係数:オブジェクトが目標位置と角度に到達するためにどのくらい速く移動および回転するかを示します。補正が高いほど、オブジェクトの移動や回転が速くなります。補正は、ジョイントが使用できる最大出力と最大トルク(回転力)によって制限されます。