Godot ist eine kostenlose Open Source Game Engine unter MIT Lizenz.
In Godot gibt es verschiedene Arten von Körpern (Bodies), die verwendet werden können, um die physikalischen Eigenschaften von Objekten in einer Spielwelt zu simulieren. Hier sind die wichtigsten Körperarten in Godot:
extends Node func _ready(): _ready1() func _ready1(): var myMesh = MeshInstance3D.new() myMesh.mesh = PlaneMesh.new() var size = Vector3(15.0, 1, 15.0) myMesh.scale = size myMesh.create_convex_collision(true, true) add_child(myMesh) var camera = Camera3D.new() camera.position = Vector3(0, 2, 2) add_child(camera) func _ready2(): var myMesh = MeshInstance3D.new() var custom_plane = create_custom_plane(Vector3(15, 1, 15), 2, 2) # Größe 5x5, 2x2 Segmente myMesh.mesh = custom_plane myMesh.scale = Vector3(15, 1, 15) myMesh.rotation_degrees = Vector3(180, 0, 0) add_child(myMesh) var camera = Camera3D.new() camera.position = Vector3(0, 2, 2) add_child(camera) func create_custom_plane(size: Vector3, seg_x: int, seg_y: int) -> ArrayMesh: var array_mesh = ArrayMesh.new() var vertices = PackedVector3Array() var indices = PackedInt32Array() var uvs = PackedVector2Array() var half_width = size.x / 2 var half_height = size.z / 2 # Vertices und UVs erstellen for y in range(seg_y + 1): for x in range(seg_x + 1): var vx = lerp(-half_width, half_width, x / seg_x) var vy = 0 var vz = lerp(-half_height, half_height, y / seg_y) vertices.append(Vector3(vx, vy, vz)) uvs.append(Vector2(x / seg_x, y / seg_y)) # Indices für die Dreiecke erstellen for y in range(seg_y): for x in range(seg_x): var i = y * (seg_x + 1) + x indices.append(i) indices.append(i + seg_x + 1) indices.append(i + seg_x + 2) indices.append(i) indices.append(i + seg_x + 2) indices.append(i + 1) # Mesh-Daten vorbereiten var arrays = [] arrays.resize(Mesh.ARRAY_MAX) arrays[Mesh.ARRAY_VERTEX] = vertices arrays[Mesh.ARRAY_INDEX] = indices arrays[Mesh.ARRAY_TEX_UV] = uvs # ArrayMesh hinzufügen array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays) return array_mesh
# Lade die Szene
var scene = preload("res://capsule.tscn")
# Instanziere die Szene
var instance = scene.instantiate()
# Füge die instanziierte Szene als Kind zum aktuellen Node hinzu
add_child(instance)
Move/rotate a Node3D
extends Node3D # Geschwindigkeit, mit der das Objekt bewegt wird var speed = 5.0 func _process(delta): # Bewegung auf der X-Achse # position.x += speed * delta # oder translate(Vector3(speed * delta, 0, 0)) # Bewegung auf der Z-Achse # position.z += speed * delta # oder translate(Vector3(0, 0, speed * delta)) # Rotation um die X-Achse # rotation.x += 10 * deltaTime # oder rotate(Vector3(1, 0, 0), deg_to_rad(abs(speed) * 10 * delta)) # Rotation um die Z-Achse #rotation.z += 10 * deltaTime # oder rotate(Vector3(0, 0, 1), deg_to_rad(abs(speed) * 10 * delta)) # Umkehrung der Bewegungsrichtung, wenn die X-Position eine bestimmte Grenze erreicht if position.x > 5.0 or position.x < -5.0: speed = -speed
Move/rotate a MeshInstance3D
extends MeshInstance3D # Geschwindigkeit, mit der das Objekt bewegt wird var speed = 5.0 func _process(delta): # Bewegung auf der X-Achse # position.x += speed * delta # oder translate(Vector3(speed * delta, 0, 0)) # Bewegung auf der Z-Achse # position.z += speed * delta # oder translate(Vector3(0, 0, speed * delta)) # Rotation um die X-Achse # rotation.x += 10 * deltaTime # oder rotate(Vector3(1, 0, 0), deg_to_rad(abs(speed) * 10 * delta)) # Rotation um die Z-Achse #rotation.z += 10 * deltaTime # oder rotate(Vector3(0, 0, 1), deg_to_rad(abs(speed) * 10 * delta)) # Umkehrung der Bewegungsrichtung, wenn die X-Position eine bestimmte Grenze erreicht if position.x > 5.0 or position.x < -5.0: speed = -speed
extends Raycast2D
var raycast_length = 10.0
func _ready():
raycast.target_position = Vector2(0, raycast_length)
raycast.enabled = true
func _physics_process(delta):
if is_colliding():
print("Der Raycast kollidiert.")
else:
print("Der Raycast kollidiert nicht.")
extends CharacterBody2D
var raycast_length = 10.0
var raycast: RayCast2D
func _ready():
raycast = RayCast2D.new()
raycast.target_position = Vector2(0, raycast_length)
raycast.enabled = true
add_child(raycast)
func _process(delta):
if raycast.is_colliding():
print("Der Raycast kollidiert.")
else:
print("Der Raycast kollidiert nicht.")
Der Raycast3D-Node muss zuerst im Scenetree hinzugrfügt werden. Z.B als Child der Camera.
extends RayCast3D
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# get_collision_point()
# get_collider()
if is_colliding():
var length = (get_parent().global_position - get_collider().global_position).length()
print("colliding with ", get_collider(), " at position ", get_collider().global_position, " at a dist of ", length)
func shoot():
var space = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(
global_position,
global_position - global_transform.basis.z * 2
)
var collision = space.intersect_ray(query)
if collision:
print(collision.collider.name)
func _on_body_entered(body):
print("on_body_entered:", body.name)
func _on_body_exited(body):
print("on_body_exited:", body.name)
Um Funktionen im Script mit Signalen aus der Engine zu verknüpfen, Doppelklick auf das entsprechende Signal.
3D Kolissionen
func _process(delta):
var space_state = get_world_3d().direct_space_state
var transform = global_transform
var query = PhysicsShapeQueryParameters3D.new()
query.shape = collision_shape.shape
query.transform = transform
var results = space_state.intersect_shape(query)
for result in results:
if result.collider:
print("Kollision mit:", result.collider.name)
Signale setzen!
extends Area2D
# or
# extends Area3D
# Wenn 2 Areas überlappen
func _on_area_entered(area):
print("on_area_entered:", area.name)
# Wenn 2 Areas nicht mehr überlappen
func _on_area_exited(area):
print("on_area_exited:", area.name)
# Wenn eine Area und ein Node überlappen
func _on_body_entered(body):
print("on_body_entered:", body.name)
# Wenn eine Area und ein Node nicht mehr überlappen
func _on_body_exited(body):
print("on_body_exited:", body.name)
# Teste ob ein Player in der Box ist
func is_player_in_box():
var bodies = get_overlapping_bodies()
for body in bodies:
if body.name == "CharacterBody3D":
return true
return false
func _process(delta):
if is_player_in_box():
print("player is in the box")
extends Camera3D
@export var move_speed: float = 10.0
@export var mouse_sensitivity: float = 0.1
var rotation_x: float = 0.0
var rotation_y: float = 0.0
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(delta: float):
handle_movement(delta)
func _input(event: InputEvent):
if event is InputEventMouseMotion:
handle_mouse_rotation(event.relative)
if Input.is_action_just_pressed("Escape"):
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func handle_movement(delta: float):
var velocity = Vector3.ZERO
if Input.is_action_pressed("move_forward"):
velocity -= transform.basis.z
if Input.is_action_pressed("move_backward"):
velocity += transform.basis.z
if Input.is_action_pressed("move_left"):
velocity -= transform.basis.x
if Input.is_action_pressed("move_right"):
velocity += transform.basis.x
if velocity != Vector3.ZERO:
velocity = velocity.normalized() * move_speed * delta
global_transform.origin += velocity
func handle_mouse_rotation(mouse_motion: Vector2):
rotation_y -= mouse_motion.x * mouse_sensitivity
rotation_x -= mouse_motion.y * mouse_sensitivity
rotation_x = clamp(rotation_x, -90.0, 90.0)
rotation_degrees = Vector3(rotation_x, rotation_y, 0.0)
extends Node3D
@export var move_speed: float = 10.0
@export var mouse_sensitivity: float = 0.1
var rotation_x: float = 0.0
var rotation_y: float = 0.0
var camera: Camera3D = null
func _ready():
camera = Camera3D.new()
camera.current = true
add_child(camera)
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(delta: float):
if camera:
handle_movement(delta)
func _input(event: InputEvent):
if event is InputEventMouseMotion:
handle_mouse_rotation(event.relative)
if Input.is_action_just_pressed("Escape"):
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func handle_movement(delta: float):
var velocity = Vector3.ZERO
if Input.is_action_pressed("move_forward"):
velocity -= camera.transform.basis.z
if Input.is_action_pressed("move_backward"):
velocity += camera.transform.basis.z
if Input.is_action_pressed("move_left"):
velocity -= camera.transform.basis.x
if Input.is_action_pressed("move_right"):
velocity += camera.transform.basis.x
if velocity != Vector3.ZERO:
velocity = velocity.normalized() * move_speed * delta
camera.global_transform.origin += velocity
func handle_mouse_rotation(mouse_motion: Vector2):
if not camera:
return
rotation_y -= mouse_motion.x * mouse_sensitivity
rotation_x -= mouse_motion.y * mouse_sensitivity
rotation_x = clamp(rotation_x, -90.0, 90.0)
camera.rotation_degrees = Vector3(rotation_x, rotation_y, 0.0)
extends CharacterBody2D
@onready var collision_shape = $CollisionShape2D
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var speed = 50
func _physics_process(delta):
var direction = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if direction:
velocity = direction * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.y = move_toward(velocity.y, 0, speed)
velocity.y += gravity * delta
move_and_slide()
#move_and_collide(velocity)
#check_collision()
var collisions = get_slide_collision_count()
if collisions:
for collision in collisions:
print(get_slide_collision(collision))
if $RayCast2D.is_colliding():
print("[CharacterBody2D:raycast] Raycast colliding");
func check_collision():
var space_state = get_world_2d().direct_space_state
var transform = global_transform
var query = PhysicsShapeQueryParameters2D.new()
query.shape = collision_shape.shape
query.transform = transform
var results = space_state.intersect_shape(query)
for result in results:
if result.collider and result.collider.name != "CharacterBody2D":
print("[CharacterBody2D:intersect_shape] Kollision mit:", result.collider.name)
Player Controller
extends CharacterBody3D
@onready var head = $SpringArm3D/Head
@onready var collision_shape = $CollisionShape3D
@onready var camera = $SpringArm3D/Head
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var speed = 4.0
var jump_speed = 6.0
var mouse_sensitivity = 0.002
var vertical_angle = 0.0
var is_crouching = false
var crouch_height = 0.5
var standing_height = 1.8
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func shoot():
var space = get_world_3d().direct_space_state
var query = PhysicsRayQueryParameters3D.create(
head.global_position,
head.global_position - head.global_transform.basis.z * 2
)
var collision = space.intersect_ray(query)
if collision:
print(collision.collider.name)
func get_input():
shoot()
var input = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
var movement_dir = transform.basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed
velocity.z = movement_dir.z * speed
if Input.is_action_just_pressed("crouch") and is_on_floor():
toggle_crouch()
if Input.is_action_just_pressed("Escape"):
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
if Input.is_action_pressed("jump") and is_on_floor():
velocity.y = jump_speed
func _process(delta):
pass #check_collision()
func check_collision():
var space_state = get_world_3d().direct_space_state
var transform = global_transform
var query = PhysicsShapeQueryParameters3D.new()
query.shape = collision_shape.shape
query.transform = transform
#query.collide_with_areas = true # Nur Areas berücksichtigen
var results = space_state.intersect_shape(query)
for result in results:
if result.collider:
print("Kollision mit:", result.collider.name)
func _physics_process(delta):
velocity.y += -gravity * delta
get_input()
move_and_slide()
func toggle_crouch():
if is_crouching:
is_crouching = false
collision_shape.shape.height = standing_height
head.position.y = standing_height # Kamera anpassen
else:
is_crouching = true
collision_shape.shape.height = crouch_height
head.position.y = crouch_height # Kamera anpassen
func _unhandled_input(event):
if event is InputEventMouseMotion:
# Horizontale Charakterrotation (um die y-Achse)
rotate_y(-event.relative.x * mouse_sensitivity)
# Vertikale Kamerarotation (um die x-Achse des SpringArm3D)
vertical_angle -= event.relative.y * mouse_sensitivity
vertical_angle = clamp(vertical_angle, -PI / 2, PI / 2) # Begrenzung der vertikalen Rotation auf +-90°
head.rotation.x = vertical_angle
Plane Controller
extends CharacterBody3D
@export var maxSpeed :float = 1.0
@export var turnRate :float = 0.1
@onready var Gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var Speed = 0.0
func _physics_process(delta):
_rotate()
if Input.is_action_just_pressed("move_forward") and (Speed <= maxSpeed):
Speed += 1.0
if Input.is_action_just_pressed("move_backward"):
if (Speed >= 1.0):
Speed -= 1.0
else:
Speed = 0.0
if (Speed > 0.0):
global_translate(transform.basis.z)
move_and_slide()
func _rotate():
var yaw = Input.get_axis("move_right", "move_left") # Y Axis
var roll = Input.get_axis("ui_left", "ui_right") # Z Axis
var pitch = Input.get_axis("ui_down", "ui_up") # X Axis
var direction = Vector3(pitch, yaw, roll) * turnRate
if direction:
var a = Quaternion(transform.basis.from_euler(rotation))
var b = Quaternion(transform.basis.from_euler(direction))
transform.basis = Basis(a * b)
extends VehicleBody3D
var steering_smoothness : float = 5.0 # Steuerungsdämpfung
func _physics_process(delta: float) -> void:
var target_steering = Input.get_axis("move_right", "move_left") * 0.5
var target_engine_force = Input.get_axis("move_backward", "move_forward") * 80
# Steuerung anwenden (sanft interpolieren)
steering = lerp(steering, target_steering, steering_smoothness * delta)
engine_force = target_engine_force
for child in get_children():
if child is VehicleWheel3D:
if child.steering:
child.set_steering(steering)
else:
child.engine_force = engine_force
func _process():
rpc("rpc_function") # will transfer reliable
rpc_unreliable("rpc_function") # will transfer unreliable
rpc_function.rpc()
rpc_function.rpc_id(peer_id) # call it on a specified peer
@rpc(mode, sync, transfer, channel)
func rpc_function():
var sender = multiplayer.get_remote_sender_id()
if sender == get_multiplayer_authority():
do_stuff()
Von wem kann die Funktion ausgeführt werden. Default ist „authority“. Man kann die Multiplayer Authority mit der Funktion
Node.set_multiplayer_authority()
auf einer per-Peer-Basis konfigurieren.
Wo wird die Funktion ausgeführt. Nur remote oder auch lokal.
Muss immer das letzte Argument sein.