やりたいこと
GodotのTileMapで横スクロールな2Dステージを作ったとします。
そこでキャラが乗っているタイルの情報が欲しくなりました。
ダメージ床だったらダメージ処理したり、衝突したタイルを破壊したりできます。
タイル情報を検出する方法
TileSetの設定
まずTileSetを設定します。
画像から領域を切って、コリジョンを設定します。
タイルでステージを作る
TileSetからタイルを選んでTileMapに配置します。
今回は横長タイルにしました。
キャラの作成
キャラにはKinematicBody2Dを設定します。
今回は2Dユニティちゃんをお借りしました。🙏🙏🙏🙏🙏🙏🙏
移動処理を書きます。詳細な処理の記載は省いています。
func _physics_process(delta: float): # 落下処理 velocity.y += GRAVITY * delta velocity.y = min(velocity.y, MAX_FALLING_SPEED) # 移動処理 velocity = move_and_slide_with_snap(velocity, Vector2(0, 4), Vector2.UP, true, 4, deg2rad(48))
コリジョンからタイル情報を検出する
ここからが本題です。
move_and_slide_with_snap
で移動している場合、get_slide_collision
で KinematicCollision2D が得られます。
KinematicCollision2Dの各プロパティはタイルマップの場合、以下の通りになります
collider
: CollisionObject2Dcollider_shape
: TileMapcollider_shape_index
: シェイプ番号 (タイルごとのシェイプ)
collider_shape_index
が重要です。乗っているタイルによってここの値が変化することが確認できます。
CollisionObject2Dに登録されているコリジョンシェイプの番号になるので、TIleIDにどうにかして変換する必要があります。
いろいろ調べて、以下の方法で上手くいきました。
func _process(delta: float): var collision := get_slide_collision(0) if collision: # TileMapに衝突しているかどうか var tilemap := collision.collider_shape as TileMap if tilemap: var tileset := tilemap.tile_set # collider_shape_indexを使ってメタデータ(タイル位置)を取得 var tile_pos = Physics2DServer.body_get_shape_metadata( collision.collider.get_rid(), collision.collider_shape_index) # タイル位置を使ってTIleMapからタイルIDを取得 var tile_id := tilemap.get_cellv(tile_pos) # タイルIDを表示 print(tileset.tile_get_name(tile_id));
実行画面
出力ログ
--- Debugging process started --- Godot Engine v3.2.2.stable.official - https://godotengine.org OpenGL ES 3.0 Renderer: Intel(R) Iris(R) Plus Graphics 基本チップ ハーフチップ 右上がり斜面 左上がり斜面 右上がり斜面
まとめ
CollisionObject2Dにメタデータという形で記録されたタイル位置情報を collider_shape_index
を使ってタイル情報を得る方法の紹介でした。
おまけ(調べた方法)
TileMapのソースコードを読みました。
Godotはエンジンのお気持ちが知りたくなったら、ソースコードを見に行けばいいのでお手軽ですね。
タイルのコリジョンシェイプをbody(CollisionObject2D)へ登録している箇所があります。
_add_shape(shape_idx, q, shape, shapes[j], xform, Vector2(E->key().x, E->key().y));
シェイプ情報以外にもタイルの位置情報をメタデータとして登録しています。
void TileMap::_add_shape(int &shape_idx, const Quadrant &p_q, const Ref<Shape2D> &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata) { PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); if (!use_parent) { ps->body_add_shape(p_q.body, p_shape->get_rid(), p_xform); ps->body_set_shape_metadata(p_q.body, shape_idx, p_metadata);
どうにかしてこのメタデータを取り出せばタイル位置が判明します。
Physics2DServerはGDScriptからも叩けるので、Physics2DServer.body_get_shape_metadataでメタデータを取ることができることが分かりました。
ライセンス表記
この記事はユニティちゃんライセンス条項の元に提供されています