Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
キネマティックキャラクター(2D)
はじめに
はい、奇妙な名前に聞こえますね。「キネマティック・キャラクター」それは、何ですか?名前の理由は、物理エンジンが出てきたときに、それらが(主に衝突応答を扱ったため)「ダイナミクス」エンジンと呼ばれたからです。ダイナミクスエンジンを使ってキャラクターコントローラーを作ろうとする試みは数多く行われましたが、思ったほど簡単ではありませんでした。Godotには、(2d/platformerのデモで見ることができるように)色々と発見できるダイナミックキャラクターコントローラーの最高の実装の1つがありますが、それを使用するには、かなりのレベルのスキルと物理エンジンの理解(または試行錯誤の忍耐)が必要です。
Havokなどの一部の物理エンジンは、最適なオプションとしてダイナミックキャラクターコントローラーに誓いをたてているように見えますが、他の物理エンジン(PhysX)は、むしろキネマティックコントローラーを促進します。
だから、違いは何ですか?:
ダイナミックキャラクターコントローラーは、無限慣性テンソルを持つリジットボディを使用します。 回転できないリジットボディです。 物理エンジンは常にオブジェクトの移動と衝突を許可し、その後、すべて一緒に衝突を解決します。これにより、ダイナミックキャラクターコントローラーは、プラットフォーマーデモで見られるように、他の物理オブジェクトとシームレスに対話できます。 ただし、これらの相互作用は常に予測できるとは限りません。 衝突は解決するために複数のフレームを必要とする可能性があるため、いくつかの衝突はわずかにずれているように見える場合があります。 これらの問題は修正できますが、ある程度のスキルが必要です。
キネマティックキャラクターコントローラーは、常に非衝突状態で始まり、常に非衝突状態に移行すると想定されています。 衝突状態で開始した場合、リジットボディのように自身を解放しようとしますが、これは例外であり、ルールではありません。 これにより、制御と動作がより予測可能になり、プログラムが簡単になります。 ただし、欠点としては、コードで手動で行わない限り、他の物理オブジェクトと直接やり取りすることはできません。
この短いチュートリアルでは、キネマティックキャラクターコントローラーに焦点を当てます。 基本的に、衝突を処理する昔ながらの方法です。内部では必ずしも単純ではありませんが、よく隠されており、素晴らしくシンプルなAPIとして提示されています。
Physics process
キネマティックボディまたはキャラクターのロジックを管理するには、常に物理プロセスを使用することをお勧めします。これは、物理ステップの前に呼び出され、その実行が物理サーバーと同期しているため、常に毎秒同じ回数とも呼ばれるためです。 これにより、通常のプロセスを使用するよりも物理学と動きの計算が予測可能な方法で機能します。フレームレートが高すぎたり低すぎたりするとスパイクが発生したり、精度が低下したりします。
extends CharacterBody2D
func _physics_process(delta):
pass
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
}
}
シーンの設定
テスト用に、ここにシーンがあります(タイルマップチュートリアルから): kinematic_character_2d_starter.zip。 キャラクターの新しいシーンを作成します。 ロボットスプライトを使用して、次のようなシーンを作成します:

CollisionShape2Dノードの横に警告アイコンがあります。 それは、形状を定義していないためです。 CollisionShape2Dのshapeプロパティで新しいCircleShape2Dを作成します。 <CircleShape2D>をクリックしてオプションに移動し、半径を30に設定します:

注: 物理のチュートリアルで前述したように、物理エンジンはほとんどの種類の形状のスケールを処理できないため(コリジョンポリゴン、プレーン、セグメントのみが機能します)、シェイプのパラメーター(半径など)を拡大縮小するのではなく、常に値を変更してください。スケールが形状のスケールに影響するため、同じことがキネマティック/リジッド/スタティックボディ自体にも当てはまります。
ここで、キャラクターのスクリプトを作成します。上記の例として使用したスクリプトがベースとして機能するはずです。
最後に、タイルマップでそのキャラクターシーンをインスタンス化し、マップシーンをメインのシーンにします。再生を押すと実行されます。

キネマティック キャラクタの移動
キャラクターシーンに戻り、スクリプトを開くと、魔法が始まります! キネマティックボディはデフォルトでは何もしませんが、CharacterBody2D.move_and_collide()
という便利な関数があります。 この関数は、Vector2 を引数として取り、その運動を キネマティックボディに適用しようとします。 衝突が発生した場合、衝突の瞬間に停止します。
それでは、スプライトが床に当たるまで下に移動しましょう:
extends CharacterBody2D
func _physics_process(delta):
move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
// Move down 1 pixel per physics frame
MoveAndCollide(new Vector2(0, 1));
}
}
その結果、キャラクターは移動しますが、床に当たるとすぐに停止します。 かなりクールですね?
次のステップでは、ミックスに重力を追加します。これにより、通常のゲームキャラクターのように動作します:
extends CharacterBody2D
const GRAVITY = 200.0
func _physics_process(delta):
velocity.y += delta * GRAVITY
var motion = velocity * delta
move_and_collide(motion)
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
Velocity = velocity;
var motion = velocity * (float)delta;
MoveAndCollide(motion);
}
}
これでキャラクターがスムーズに落ちます。 方向キーをタッチして、左右に歩いてみましょう。(少なくとも速度の場合)使用されている値はピクセル/秒であることに注意してください。
これにより、左右キーを押すことで基本的な歩行サポートが追加されます:
extends CharacterBody2D
const GRAVITY = 200.0
const WALK_SPEED = 200
func _physics_process(delta):
velocity.y += delta * GRAVITY
if Input.is_action_pressed("ui_left"):
velocity.x = -WALK_SPEED
elif Input.is_action_pressed("ui_right"):
velocity.x = WALK_SPEED
else:
velocity.x = 0
# "move_and_slide" already takes delta time into account.
move_and_slide()
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
private const int WalkSpeed = 200;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
if (Input.IsActionPressed("ui_left"))
{
velocity.X = -WalkSpeed;
}
else if (Input.IsActionPressed("ui_right"))
{
velocity.X = WalkSpeed;
}
else
{
velocity.X = 0;
}
Velocity = velocity;
// "MoveAndSlide" already takes delta time into account.
MoveAndSlide();
}
}
そして、それを試してみてください。
これはプラットフォーマーにとって良い出発点です。 より完全なデモは、エンジンとともに配布されるデモzip、または https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character にあります。