はじめに
RayCast3Dは点の判定だけですが、広い範囲を一度に検出したいことがありませんか?爆発の範囲判定、キャラクターの前方をブロックチェック、敵集団の検出など。ShapeCast3Dなら、球や円柱などの形状を使って、より現実的で広範囲な判定が可能です。
ShapeCast3Dとは?
ShapeCast3Dは、Shape3D(球・カプセル・ボックスなど)を掃引(スイープ)させることで、広い範囲の衝突を検出するノードです。RayCast3D(点の判定)に対して、ShapeCast3Dは形状を持つため、より複雑で現実的な判定が可能になります。複数ヒット検出にも対応しています。
継承ツリー:
ShapeCast3D ↓ Node3D ↓ Node

このノードを使うべき場面
使うべき場面:
- 爆発やAoE(範囲攻撃)の被弾判定。一度に複数敵を検出
- キャラクター前方の広域チェック(障害物群の検出)
- 敵グループが一定範囲内にいるかの判定
- 射撃ゲームの貫通弾が複数の敵を通る判定
- 地震やノックバック効果で範囲内のオブジェクトに影響を与えたい場合
使わない場面:
- 単一ターゲットへの正確な判定(RayCast3Dが効率的)
- 常時衝突判定(Area3Dを使用)
主なプロパティと機能
| プロパティ | 型 | 説明 | 使用例 |
|---|---|---|---|
shape |
Shape3D | 掃引に使用する形状(SphereShape3D、CapsuleShape3D、BoxShape3D等) | var sphere = SphereShape3D.new(); sphere.radius = 5.0; shapecast.shape = sphere |
target_position |
Vector3 | 形状の終点(ローカル座標)。ノード位置から終点までが掃引パス | shapecast.target_position = Vector3(0, 0, -50) |
enabled |
bool | ShapeCast3Dの判定を有効にするか | shapecast.enabled = true |
collision_mask |
int | どのフィジクスレイヤーを検出するか | shapecast.collision_mask = 0b0011 |
max_results |
int | 最大何個のオブジェクトを検出するか(0で無制限) | shapecast.max_results = 10 |
exclude_parent |
bool | 親ノードを検出対象から除外するか | shapecast.exclude_parent = true |
重要メソッド
| メソッド | 戻り値 | 説明 | 使用例 |
|---|---|---|---|
is_colliding() |
bool | 何かに衝突しているか | if shapecast.is_colliding(): |
get_collision_count() |
int | 衝突したオブジェクトの数 | var count = shapecast.get_collision_count() |
get_collider(index: int) |
Node | 指定インデックスの衝突したノード | var obj = shapecast.get_collider(0) |
get_collision_point(index: int) |
Vector3 | 指定インデックスの衝突地点(世界座標) | var point = shapecast.get_collision_point(0) |
get_collision_normal(index: int) |
Vector3 | 指定インデックスの衝突面の法線 | var normal = shapecast.get_collision_normal(0) |
force_shapecast_update() |
void | 直ちに判定を更新 | shapecast.force_shapecast_update() |
GDScriptコード例1:爆発範囲判定の実装
extends Node3D
@onready var explosion_check = $ExplosionArea # ShapeCast3Dを配置
@export var explosion_radius = 20.0
@export var explosion_damage = 50.0
func _ready():
# 爆発判定用の球形Shapeを設定
var sphere = SphereShape3D.new()
sphere.radius = explosion_radius
explosion_check.shape = sphere
# 爆発位置から周囲をチェック(掃引なし)
explosion_check.target_position = Vector3.ZERO
explosion_check.enabled = true
explosion_check.collision_mask = 0b0010 # レイヤー1を検出
func trigger_explosion(position: Vector3):
print("爆発!位置: %s" % position)
global_position = position
# 範囲内の全オブジェクトを検出
explosion_check.force_shapecast_update()
if explosion_check.is_colliding():
var hit_count = explosion_check.get_collision_count()
print("爆発で %d個のオブジェクトに命中" % hit_count)
for i in range(hit_count):
var collider = explosion_check.get_collider(i)
var collision_point = explosion_check.get_collision_point(i)
print("命中オブジェクト: %s" % collider.name)
# ダメージ処理
if collider.has_method("take_damage"):
collider.take_damage(explosion_damage)
# ノックバック処理
if collider.has_method("apply_knockback"):
var knockback_dir = (collision_point - position).normalized()
collider.apply_knockback(knockback_dir * 30.0)
GDScriptコード例2:前方チェック(複数障害物検出)
extends CharacterBody3D
@onready var forward_check = $ForwardCheck # ShapeCast3Dを配置
@export var check_distance = 10.0
@export var check_radius = 2.0
func _ready():
# カプセル形状で前方の広域チェック
var capsule = CapsuleShape3D.new()
capsule.radius = check_radius
capsule.height = check_radius * 2
forward_check.shape = capsule
# ノード位置から前方check_distanceまで掃引
forward_check.target_position = Vector3(0, 0, -check_distance)
forward_check.enabled = true
forward_check.collision_mask = 0b0011
func _physics_process(delta):
var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if input_dir.length() > 0:
# 移動方向を更新
var direction = input_dir.normalized()
var angle = atan2(direction.x, -direction.y)
rotation.y = angle
# 前方の障害物をチェック
forward_check.force_shapecast_update()
if forward_check.is_colliding():
var hit_count = forward_check.get_collision_count()
print("前方に %d個の障害物を検出" % hit_count)
for i in range(hit_count):
var obstacle = forward_check.get_collider(i)
print("- %s" % obstacle.name)
else:
print("前方クリア。進みます")
もっと使いこなす:カスタマイズできるパラメータ
まずは基本を動かしてみてから、余裕が出たら試してみてください。
| パラメータ | 型 | 説明 | 実装例 |
|---|---|---|---|
collision_group |
int | 自身が属するフィジクスグループ | shapecast.collision_group = 0b0001 |
max_results |
int | 検出上限(0は無制限。大量検出時はパフォーマンス注意) | shapecast.max_results = 5 # 最大5個まで |
hit_from_inside |
bool | 形状の内側からの衝突も検出 | shapecast.hit_from_inside = true |
get_collision_shape(index) |
Shape3D | 指定インデックスの衝突形状を取得 | var shape = shapecast.get_collision_shape(0) |
RayCast3D vs ShapeCast3D 使い分け表
| 特性 | RayCast3D | ShapeCast3D |
|---|---|---|
| 判定範囲 | 点(光線) | 形状(球・カプセル・ボックス) |
| 複数ヒット検出 | 最初の1つだけ | 複数オブジェクト同時検出 |
| 処理速度 | 高速 | やや遅い(形状判定のため) |
| 使用場面 | FPS射撃、視線チェック | 爆発判定、範囲攻撃 |
| セットアップ | target_positionのみ | shape + target_position |
カスタマイズの実装例:複雑な形状(ボックス型判定)
extends Node3D
@onready var box_cast = $BoxCast # ShapeCast3D
func _ready():
# 矩形状の判定範囲(例:レーザービーム)
var box = BoxShape3D.new()
box.size = Vector3(4.0, 4.0, 50.0) # 幅4m, 高さ4m, 長さ50m
box_cast.shape = box
box_cast.target_position = Vector3(0, 0, 0) # 掃引なし、現在地のみ検出
box_cast.enabled = true
func fire_laser():
box_cast.force_shapecast_update()
var affected = []
if box_cast.is_colliding():
for i in range(box_cast.get_collision_count()):
affected.append(box_cast.get_collider(i))
print("レーザーに巻き込まれたオブジェクト: %d個" % affected.size())
return affected
まとめ
ShapeCast3Dは、広い範囲を効率的に判定し、複数ターゲットに一度にアクセスできる強力なノードです。
- RayCast3Dとは違い、形状を持つため爆発や範囲攻撃の判定に最適です
- SphereShape3D・CapsuleShape3D・BoxShape3Dなど、ゲーム設計に応じて形状を選択できます
- get_collision_count()で複数ヒットを処理し、より複雑なゲーム機構を実装できます
次回は、大量のメッシュを効率的に描画する「MultiMeshInstance3D」について詳しく解説します。
シリーズ:Godot 4 ノード解説
001~040:各種ノード
041~080:
041: Marker3D | 042: Node3D | 043: Camera3D | 044: Light3D | 045: MeshInstance3D |
046: AnimationPlayer | 047: AnimationTree | 048: Skeleton3D | 049: IKSkeleton3D | 050: Skin |
051: CollisionShape3D | 052: RigidBody3D | 053: CharacterBody3D | 054: StaticBody3D | 055: Area3D |
056: PhysicsDirectSpaceState3D | 057: ShapeCast3D | 058: RayCast3D | 059: Decal | 060: GPUParticles3D |
061: CPUParticles3D | 062: WorldEnvironment | 063: OmniLight3D | 064: SpotLight3D | 065: DirectionalLight3D |
066: ReflectionProbe | 067: LightmapGI | 068: VoxelGI | 069: Occluder3D | 070: VisualInstance3D |
071: BoneAttachment3D | 072: VehicleBody3D | 073: SpringArm3D | 074: RayCast3D | 075: ShapeCast3D |
076: MultiMeshInstance3D | 077: Node | 078: CanvasLayer | 079: Control | 080: Label
この記事はGodot 4.xをもとに執筆しています。


コメント