协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
physics【开发与工程】Implement 2D and 3D physics in Godot including collision detection, physics bodies, raycasting, and area detection. Use this skill when setting up CharacterBody, RigidBody, StaticBody, configuring collision layers and masks, casting rays, or building physics-driven gameplay.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
For player-controlled characters with manual physics handling.
extends CharacterBody2D
@export var speed: float = 300.0
@export var jump_velocity: float = -500.0
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta):
if not is_on_floor():
velocity.y += gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
var direction = Input.get_axis("left", "right")
velocity.x = direction * speed
move_and_slide()
for i in get_slide_collision_count():
var collision = get_slide_collision(i)
if collision.get_collider().is_in_group("enemies"):
take_damage()
For physics-driven objects (balls, ragdolls, projectiles).
extends RigidBody2D
@export var launch_force: float = 500.0
func launch(direction: Vector2):
apply_central_impulse(direction * launch_force)
func _ready():
apply_central_impulse(Vector2(100, -200))
gravity_scale = 1.5
physics_material_override = PhysicsMaterial.new()
physics_material_override.bounce = 0.8
For static environment colliders (walls, floors, platforms).
# Moving platform with AnimatableBody2D
extends AnimatableBody2D
@export var move_distance: Vector2 = Vector2(0, -100)
@export var move_speed: float = 2.0
var start_position: Vector2
var target_position: Vector2
func _ready():
start_position = global_position
target_position = start_position + move_distance
func _physics_process(delta):
global_position = global_position.lerp(target_position, move_speed * delta)
if global_position.distance_to(target_position) < 1:
var temp = target_position
target_position = start_position
start_position = temp
For trigger zones (pickups, damage zones, detection areas).
extends Area2D
signal collected()
func _ready():
body_entered.connect(_on_body_entered)
area_entered.connect(_on_area_entered)
func _on_body_entered(body: Node2D):
if body.is_in_group("player"):
collected.emit()
queue_free()
func _on_area_entered(area: Area2D):
if area.is_in_group("damage_zone"):
take_damage()
Example setup:
collision_layer = 1 # Player layer
collision_mask = 5 # Interact with layers 1 and 3 (1 + 4 = 5)
Required for physics bodies. Common shapes:
extends Node2D
@onready var ray_cast = $RayCast2D
func _physics_process(delta):
ray_cast.target_position = Vector2(100, 0)
if ray_cast.is_colliding():
var collider = ray_cast.get_collider()
var point = ray_cast.get_collision_point()
var normal = ray_cast.get_collision_normal()
if collider.is_in_group("enemy"):
attack(collider)
extends Node3D
@onready var ray_cast = $RayCast3D
func _physics_process(delta):
ray_cast.target_position = Vector3(0, 0, -10)
if ray_cast.is_colliding():
var collider = ray_cast.get_collider()
if collider.has_method("take_damage"):
collider.take_damage(10)
func raycast_from_mouse():
var space_state = get_world_2d().direct_space_state
var mouse_pos = get_global_mouse_position()
var query = PhysicsRayQueryParameters2D.create(global_position, mouse_pos)
query.collision_mask = 2
var result = space_state.intersect_ray(query)
if result:
print("Hit: ", result.collider.name)
_physics_process() for all physics calculations — fixed timestep ensures consistent behaviorfreeze on RigidBody when not needed