1. Giriş
Godot 4, karakter hareketinde büyük değişiklikler getirdi. Eski KinematicBody2D ve KinematicBody3D düğümleri CharacterBody2D ve CharacterBody3D olarak yeniden adlandırıldı ve move_and_slide() API'si tamamen yeniden tasarlandı. İster Godot 3'ten geçiş yapıyor ister sıfırdan başlıyor olun — bu rehber bilmeniz gereken her şeyi kapsıyor.
CharacterBody2D ve CharacterBody3D, kodla kontrol edilen karakterler için tasarlanmış fizik gövdeleridir. RigidBody'nin aksine kuvvetlere otomatik olarak tepki vermezler — hareketlerini tamamen betikle kontrol edersiniz. Bu da onları oyuncu karakterleri, NPC'ler ve hassas, deterministik hareket gerektiren her şey için ideal kılar.
2. Godot 3'e Göre Neler Değişti
Godot 3 ile Godot 4 arasında karakter hareketiyle ilgili en önemli değişiklikler şunlardır:
-
KinematicBody2DartıkCharacterBody2Doldu -
KinematicBody3DartıkCharacterBody3Doldu -
velocityartık bir yerleşik özellik — onu artıkmove_and_slide()'a geçirmiyorsunuz -
move_and_slide()artık hiçbir argüman almıyor — doğrudanvelocityözelliğinden okuyor -
move_and_slide_with_snap()kaldırıldı — bunun yerinefloor_snap_lengthözelliğini kullanın -
is_on_floor(),is_on_wall(),is_on_ceiling()hâlâ aynı şekilde çalışıyor -
get_gravity(), projenin varsayılan yer çekimini bir Vector olarak okumak için Godot 4.4'te eklendi — çok kullanışlı
Godot 3'te move_and_slide() sonuçtaki hızı döndürüyordu. Godot 4'te bir bool (bir çarpışma olup olmadığını) döndürür ve hız doğrudan velocity özelliği üzerinde güncellenir.
3. Temel 2D Platform Oyunu Denetleyicisi
Bu, standart yan kaydırmalı (side-scrolling) platform oyunu denetleyicisidir. Karakter sola/sağa hareket edebilir ve zemindeyken zıplayabilir. Bu, yeni bir CharacterBody2D betiği oluşturduğunuzda Godot'un ürettiği şablondur.
extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _physics_process(delta: float) -> void:
# Apply gravity when not on floor
if not is_on_floor():
velocity += get_gravity() * delta
# Jump when on floor and jump pressed
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Horizontal movement
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
Satır Satır Açıklama
-
extends CharacterBody2D— Betik CharacterBody2D'den kalıtır ve bizevelocity,move_and_slide(),is_on_floor()vb. erişim sağlar. -
SPEED = 300.0— Saniyede piksel cinsinden yatay hareket hızı. -
JUMP_VELOCITY = -400.0— 2D'de Y ekseni aşağıyı gösterdiği için negatif. Negatif bir değer karakteri yukarı hareket ettirir. -
get_gravity() * delta— Her karede proje yer çekimini uygular.get_gravity()aşağıyı gösteren birVector2döndürür (örn.Vector2(0, 980)).deltaile çarpmak, sonucu kare hızından bağımsız kılar. -
Input.get_axis("ui_left", "ui_right")— Hangi yön tuşunun basılı olduğuna göre -1.0 ile 1.0 arasında bir float döndürür. Analog girişi destekler. -
move_toward(velocity.x, 0, SPEED)— Hiçbir giriş yapılmadığında sıfıra doğru yumuşakça yavaşlar. Üçüncü argüman, çağrı başına maksimum değişimdir. -
move_and_slide()— Gövdeyi mevcutvelocityile hareket ettirir, çarpışmaları işler, yüzeyler boyunca kaydırır vevelocity'yi otomatik olarak günceller.
CharacterBody2D'niz, bir şekil atanmış (örn. RectangleShape2D veya CapsuleShape2D) en az bir CollisionShape2D alt düğümüne ihtiyaç duyar. Bu olmadan move_and_slide() hiçbir çarpışmayı algılamaz.
4. Temel 2D Tepeden Bakış Denetleyicisi
Tepeden bakış oyunlarında (RPG'ler, twin-stick nişancı oyunları vb.) yer çekimi olmadan dört yönde hareket edersiniz. Kod, bir platform oyunundan daha basittir.
extends CharacterBody2D
const SPEED = 200.0
func _physics_process(delta: float) -> void:
var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = input_direction * SPEED
move_and_slide()
Nasıl Çalışır
-
Input.get_vector(), dört giriş eyleminden normalleştirilmiş birVector2döndürür. Bu, çapraz hareketi doğru şekilde işler — vektörün uzunluğu her zaman 1.0 veya 0.0'dır, dolayısıyla çapraz hareket eksenler boyunca hareketten daha hızlı değildir. -
Bu bir tepeden bakış görünümü olduğundan yer çekimi uygulanmaz.
velocity'yi doğrudan ayarladığımız için (atalet yok), giriş yapılmadığında karakter anında durur.
İvme ve Sürtünme Ekleme
İvmelenme ve yavaşlama ile daha yumuşak bir his için:
extends CharacterBody2D
const SPEED = 200.0
const ACCELERATION = 1200.0
const FRICTION = 1000.0
func _physics_process(delta: float) -> void:
var input_direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
if input_direction != Vector2.ZERO:
velocity = velocity.move_toward(input_direction * SPEED, ACCELERATION * delta)
else:
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
move_and_slide()
5. 3D Üçüncü Şahıs Denetleyicisi
3D sürümü aynı deseni izler. Temel fark, Vector3 ile çalışmak ve 2D girişi 3D dünya uzayındaki harekete dönüştürmek için transform.basis kullanmaktır.
extends CharacterBody3D
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
func _physics_process(delta: float) -> void:
# Apply gravity
if not is_on_floor():
velocity += get_gravity() * delta
# Jump
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get input and convert to 3D direction
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
2D'den Temel Farklar
-
Birimler: 3D'de 1 birim = 1 metre (kural gereği). Yani
SPEED = 5.0saniyede 5 metre anlamına gelir — 2D piksel değerlerinden çok daha küçük sayılar. -
Zıplama hızı pozitiftir: 3D'de Y ekseni yukarıyı gösterir (2D'nin aksine), bu yüzden
JUMP_VELOCITY = 4.5pozitiftir. -
Yön dönüşümü:
transform.basis * Vector3(input_dir.x, 0, input_dir.y), 2D girişi karakterin baktığı yöne göreli bir 3D yöne dönüştürür. Girişin Y'si Z eksenine (3D'de ileri/geri) eşlenir. -
Yalnızca X ve Z kontrol edilir:
velocity.xvevelocity.z'yi ayrı ayrı ayarlar,velocity.y'yi yer çekimi ve zıplama için bırakırız.
get_gravity() metodu Godot 4.4'te eklendi. Daha eski sürümlerde 2D için Vector2(0, ProjectSettings.get_setting("physics/2d/default_gravity")), 3D için Vector3(0, -ProjectSettings.get_setting("physics/3d/default_gravity"), 0) kullanın.
6. Temel Özellikler Referansı
Hem CharacterBody2D hem de CharacterBody3D bu önemli özellikleri paylaşır. Bunları Inspector'da veya kodla ayarlayın.
| Özellik | Tür | Varsayılan | Açıklama |
|---|---|---|---|
velocity |
Vector2 / Vector3 | Vector2.ZERO |
Karakterin hızı. move_and_slide()'ı çağırmadan önce ayarlayın. Çağrıdan sonra sonuçtaki hızla güncellenir.
|
floor_snap_length |
float | 1.0 |
move_and_slide_with_snap()'in yerini alır. Karakterin zemine yapıştırılacağı mesafe. Devre dışı bırakmak için 0'a ayarlayın. Eğimler ve merdivenler için kullanışlıdır.
|
up_direction |
Vector2 / Vector3 | Vector2.UP |
Hangi yönün "yukarı" olduğunu tanımlar. Bu, neyin zemin, duvar veya tavan sayılacağını belirler. Varsayılan 2D'de (0, -1), 3D'de (0, 1, 0)'dır.
|
floor_stop_on_slope |
bool | true |
true olduğunda karakter durgunken eğimlerden aşağı kaymaz. Platform oyunları için vazgeçilmezdir. |
floor_max_angle |
float | 0.785 (45°) |
Radyan cinsinden yürünebilir maksimum eğim açısı. Bundan daha dik yüzeyler duvar olarak ele alınır. 60 dereceyi ayarlamak için deg_to_rad(60) kullanın.
|
max_slides |
int | 6 |
move_and_slide() çağrısı başına maksimum çarpışma yineleme sayısı. Daha yüksek değerler daha doğru ama daha yavaştır.
|
wall_min_slide_angle |
float | 0.262 (15°) |
Duvar kayması için minimum açı. Karakterin neredeyse paralel duvarlara takılıp kalmasını önler. |
platform_on_leave |
PlatformOnLeave | ADD_VELOCITY |
Hareketli bir platformdan ayrılırken davranış. ADD_VELOCITY momentumu korur, ADD_UPWARD_VELOCITY yalnızca yukarı bileşeni ekler, DO_NOTHING platform hızını yok sayar.
|
slide_on_ceiling |
bool | true |
true olduğunda tavanlarda kaymaya izin verir. false olduğunda tavana temas edildiğinde yatay hızı durdurur. |
7. move_and_slide() Sonrası Çarpışma Algılama
move_and_slide()'ı çağırdıktan sonra meydana gelen çarpışmaları inceleyebilirsiniz. Bu, belirli çarpışıcı (collider) türlerine tepki vermek, iniş anında ses efektleri çalmak veya duvardan zıplama (wall-jump) mekanikleri uygulamak için kullanışlıdır.
func _physics_process(delta: float) -> void:
# ... set velocity here ...
move_and_slide()
# Check all collisions from this frame
for i in get_slide_collision_count():
var collision := get_slide_collision(i)
var collider := collision.get_collider()
print("Collided with: ", collider.name)
print("Normal: ", collision.get_normal())
print("Position: ", collision.get_position())
# Practical example: bounce off enemies
for i in get_slide_collision_count():
var collision := get_slide_collision(i)
if collision.get_collider().is_in_group("enemies"):
velocity = collision.get_normal() * 300
break
Kullanışlı KinematicCollision Metotları
get_collider()— Çarpılan nesne.get_normal()— Çarpışma yüzeyinin normali. Yüzeyden uzağı gösterir.get_position()— Çarpışmanın meydana geldiği dünya uzayındaki nokta.get_travel()— Gövdenin çarpışmadan önce ne kadar hareket ettiği.get_remainder()— Uygulanmayan kalan hareket.get_collider_velocity()— Çarpışıcının hızı (hareketli platformlar için kullanışlıdır).
8. Geçiş Kopya Kağıdı
Godot 3 kodunu Godot 4'e dönüştürmek için hızlı referans:
| Godot 3 | Godot 4 |
|---|---|
KinematicBody2D |
CharacterBody2D |
KinematicBody3D |
CharacterBody3D |
velocity = move_and_slide(velocity, Vector2.UP) |
velocity = ... |
move_and_slide_with_snap(vel, snap, up) |
floor_snap_length = 4.0 |
var vel = move_and_slide(...)velocity döndürür |
move_and_slide()velocity özelliği doğrudan güncellenir |
var gravity = ProjectSettings.get("physics/2d/default_gravity") |
get_gravity() (4.4+) |
move_and_slide(..., up_direction, ...) |
up_direction = Vector2.UP (özellik olarak ayarlanır) |
move_and_slide(..., stop_on_slope, ...) |
floor_stop_on_slope = true (özellik olarak ayarlanır) |
Godot 4'te bir Godot 3 projesi açtığınızda, motor projenizi dönüştürmeyi önerir. Düğümleri yeniden adlandırır ve betikleri güncellemeye çalışır, ancak move_and_slide() çağrılarını her zaman doğru şekilde dönüştüremez. Hareket kodunuzu büyük olasılıkla elle düzeltmeniz gerekir.
9. Sık Yapılan Hatalar
Hata 1: move_and_slide()'a argüman geçirmek
# ERROR: move_and_slide() takes no arguments in Godot 4
velocity = move_and_slide(velocity, Vector2.UP)
# Set velocity, then call move_and_slide() with no arguments
velocity.x = direction * SPEED
move_and_slide()
Hata 2: move_and_slide()'dan önce velocity'yi ayarlamayı unutmak
func _physics_process(delta: float) -> void:
move_and_slide() # velocity is Vector2.ZERO — nothing happens
Hata 3: _physics_process() yerine _process() kullanmak
move_and_slide(), sabit bir hızda (varsayılan 60 Hz) çalışan _physics_process() içinde çağrılmalıdır. _process() kullanmak fiziği render kare hızına bağlar ve tutarsız davranışa yol açar.
Hata 4: CollisionShape kurmamak
CollisionShape alt düğümü olmayan bir CharacterBody2D/CharacterBody3D her şeyin içinden geçer. Çarpışma şekli eksikse Godot, editörde bir uyarı simgesi gösterir.
Hata 5: velocity.y'yi her karede yer çekimiyle üzerine yazmak
# This overwrites any jump velocity!
velocity.y = gravity * delta # should be +=, not =
# Gravity accumulates over time
velocity += get_gravity() * delta
Hata 6: Zemindeyken yer çekimi uygulamak
Yer çekimini her zaman if not is_on_floor() ile sarın. Bu kontrol olmadan yer çekimi zemindeyken birikmeye devam eder. Karakter bir kenardan yürüyüp düştüğünde, doğal bir şekilde düşmek yerine aşırı bir hızla aşağı dalar.