Unity’de Gerçekçi Araç Kontrolü: Adım Adım Rehber

Unity'de gerçekçi araç kontrolü geliştirmek mi istiyorsunuz? Fizik tabanlı sistemlerin temellerinden ileri seviye uygulamalara kadar adım adım rehberimizi keşfedin ve oyunlarınıza dinamik bir sürüş deneyimi katın.

Unity’de Gerçekçi Araç Kontrolü: Adım Adım Rehber

Unity oyun motoru, geliştiricilere sadece görsel olarak değil, fiziksel olarak da tatmin edici deneyimler yaratma gücü sunar. Özellikle araç simülasyonları veya yarış oyunları geliştirenler için, fizik tabanlı araç kontrolü, oyuncuya gerçekçi bir sürüş hissi vermek adına kritik öneme sahiptir. Bu rehberde, Unity’nin güçlü fizik motorunu kullanarak sıfırdan, gerçekçi bir araç kontrol sistemi nasıl oluşturulacağını adım adım inceleyeceğiz.

Neden Fizik Tabanlı Araç Kontrolü?

Bir aracın hareketini programlarken iki temel yaklaşım vardır: animasyon veya fizik tabanlı kontrol. Animasyon tabanlı yaklaşımlar daha çok sabit yollar ve önceden belirlenmiş hareketler için uygunken, fizik tabanlı kontrol, aracın çevresel etkileşimlere (yol yüzeyi, çarpışmalar, ivmelenme, frenleme) dinamik olarak tepki vermesini sağlar. Bu, oyuncuya daha sürükleyici ve öngörülemez bir deneyim sunar. Unity’nin yerleşik fizik motoru ve özel olarak tasarlanmış Wheel Collider bileşeni, bu tür sistemleri oluşturmak için güçlü araçlar sunar.

Temel Bileşenler ve Kurulum

Fizik tabanlı bir araç oluşturmak için bazı temel Unity bileşenlerine ihtiyacımız var:

  • Rigidbody: Aracın ana gövdesini temsil eder ve fizik motoru tarafından yönetilmesini sağlar.
  • Wheel Collider: Her bir tekerleği temsil eder ve süspansiyon, sürtünme gibi tekerlek özelindeki fiziksel etkileşimleri simüle eder.
  • 3D Modeller: Aracın şasisi ve tekerlekleri için görsel modeller.

1. Araç Şasisini Oluşturma

Öncelikle, aracın ana gövdesini (şasi) oluşturarak başlayalım. Sahnenize bir 3D model (örneğin, basit bir küp veya özel bir araç modeli) ekleyin ve adını ‘CarChassis’ olarak değiştirin. Bu objeye bir Rigidbody bileşeni ekleyin. Rigidbody ayarlarında, kütleyi (Mass) gerçekçi bir değere (örneğin, 1500 kg) ayarlayın. Ayrıca, aracın denge noktası olan Center of Mass‘ı ayarlamak önemlidir. Genellikle, bu nokta aracın alt kısmında ve ortasında yer alır. Bunu manuel olarak bir Vector3 değeriyle ayarlayabilir veya boş bir GameObject oluşturup Rigidbody’nin ‘Center of Mass’ alanına sürükleyebilirsiniz.

2. Tekerlekleri Ekleme ve Wheel Collider Yapılandırması

Şimdi sıra tekerleklerde. Aracın şasisi altına dört adet boş GameObject oluşturun ve bunlara ‘WheelFrontRight’, ‘WheelFrontLeft’, ‘WheelRearRight’, ‘WheelRearLeft’ gibi isimler verin. Bu objeler, tekerleklerin görsel modellerini ve Wheel Collider bileşenlerini barındıracaktır.

Her bir tekerlek GameObject’ine bir Wheel Collider bileşeni ekleyin. Wheel Collider’ın konumunu, ilgili tekerleğin görsel modelinin merkezine gelecek şekilde ayarlayın. Ardından, her bir Wheel Collider için şu önemli ayarları yapılandırın:

  • Radius: Tekerleğin yarıçapı. Görsel modelinizle eşleşmeli.
  • Suspension Distance: Süspansiyonun maksimum sıkışma mesafesi.
  • Spring: Süspansiyon yayı sertliği.
  • Damper: Süspansiyonun sönümleme gücü.
  • Target Position: Süspansiyonun ideal konumu (genellikle 0).
  • Forward Friction & Sideways Friction: Tekerleğin ileri ve yan yönlerdeki sürtünme özelliklerini belirler. Bu ayarlar aracın yol tutuşunu ve drift yeteneğini doğrudan etkiler. Curve ayarlarıyla sürtünme eğrilerini özelleştirebilirsiniz.

Her Wheel Collider’ın altına, ilgili tekerleğin 3D modelini çocuk (child) olarak ekleyin. Böylece, Wheel Collider’ın hareketine görsel model de uyum sağlayacaktır.

Araç Kontrol Script’i (C#)

Şimdi, aracımızı hareket ettirecek C# script’ini yazmaya geçelim. Yeni bir C# scripti oluşturun (örneğin, ‘CarController’) ve CarChassis objesine ekleyin.

using UnityEngine;
using System.Collections.Generic;

public class CarController : MonoBehaviour
{
    [Header("Araç Ayarları")]
    public float motorForce = 1500f;
    public float brakeForce = 3000f;
    public float steerAngle = 30f;
    public float maxSpeed = 50f;

    [Header("Tekerlekler")]
    public List<AxleInfo> axleInfos; // Ön ve arka aks bilgileri

    private Rigidbody rb;
    private float currentMotorForce;
    private float currentBrakeForce;
    private float currentSteerAngle;

    [System.Serializable]
    public class AxleInfo
    {
        public WheelCollider leftWheel;
        public WheelCollider rightWheel;
        public bool motor; // Bu aks motorlu mu?
        public bool steering; // Bu aks yönlendirilebilir mi?
    }

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        // Çekim merkezini ayarlayarak aracın daha dengeli olmasını sağlayın
        rb.centerOfMass = new Vector3(0, -0.9f, 0);
    }

    void FixedUpdate()
    {
        GetInput();
        ApplyMotorForce();
        ApplySteering();
        ApplyBrakeForce();
        UpdateWheelVisuals();
    }

    void GetInput()
    {
        currentMotorForce = motorForce * Input.GetAxis("Vertical");
        currentSteerAngle = steerAngle * Input.GetAxis("Horizontal");

        if (Input.GetKey(KeyCode.Space))
        {
            currentBrakeForce = brakeForce;
        }
        else
        {
            currentBrakeForce = 0f;
        }
    }

    void ApplyMotorForce()
    {
        foreach (AxleInfo axleInfo in axleInfos)
        {
            if (axleInfo.motor)
            {
                // Hız kontrolü
                if (rb.velocity.magnitude * 3.6f < maxSpeed || currentMotorForce < 0) 
                {
                    axleInfo.leftWheel.motorTorque = currentMotorForce;
                    axleInfo.rightWheel.motorTorque = currentMotorForce;
                } 
                else 
                {
                    axleInfo.leftWheel.motorTorque = 0;
                    axleInfo.rightWheel.motorTorque = 0;
                }
            }
        }
    }

    void ApplySteering()
    {
        foreach (AxleInfo axleInfo in axleInfos)
        {
            if (axleInfo.steering)
            {
                axleInfo.leftWheel.steerAngle = currentSteerAngle;
                axleInfo.rightWheel.steerAngle = currentSteerAngle;
            }
        }
    }

    void ApplyBrakeForce()
    {
        foreach (AxleInfo axleInfo in axleInfos)
        {
            axleInfo.leftWheel.brakeTorque = currentBrakeForce;
            axleInfo.rightWheel.brakeTorque = currentBrakeForce;
        }
    }

    void UpdateWheelVisuals()
    {
        foreach (AxleInfo axleInfo in axleInfos)
        {
            UpdateSingleWheelVisual(axleInfo.leftWheel);
            UpdateSingleWheelVisual(axleInfo.rightWheel);
        }
    }

    void UpdateSingleWheelVisual(WheelCollider wheelCollider)
    {
        Vector3 pos;
        Quaternion rot;
        wheelCollider.GetWorldPose(out pos, out rot);

        // Tekerleğin görsel modelini WheelCollider'ın pozisyon ve rotasyonuna göre ayarla
        Transform visualWheel = wheelCollider.transform.GetChild(0);
        visualWheel.position = pos;
        visualWheel.rotation = rot;
    }
}

Script’i Açıklayalım:

  • AxleInfo Sınıfı: Bu, her aks (ön veya arka) için tekerlek bilgilerini (sol ve sağ Wheel Collider’lar), motorlu olup olmadığını ve yönlendirilebilir olup olmadığını tutan özel bir sınıftır. Bu sayede önden çekişli, arkadan itişli veya dört çeker sistemleri kolayca yapılandırabilirsiniz.
  • Start() Metodu: Rigidbody bileşenini alır ve aracın kütle merkezini (rb.centerOfMass) ayarlar. Bu, aracın devrilmesini engellemek ve daha dengeli bir sürüş sağlamak için kritik öneme sahiptir.
  • FixedUpdate() Metodu: Fizik güncellemeleri için kullanılır. Girişleri alır, motor kuvvetini, direksiyon açısını ve fren kuvvetini uygular, ardından tekerleklerin görsel pozisyonlarını günceller.
  • GetInput(): Oyuncudan dikey (ileri/geri ivme) ve yatay (direksiyon) girişleri alır. Boşluk tuşuna basıldığında fren kuvvetini etkinleştirir.
  • ApplyMotorForce(): ‘motor’ olarak işaretlenmiş akslardaki tekerleklere motor torku uygular. Hızın maxSpeed‘i geçmemesi için basit bir kontrol içerir.
  • ApplySteering(): ‘steering’ olarak işaretlenmiş akslardaki tekerleklere direksiyon açısını uygular. Genellikle ön tekerlekler için kullanılır.
  • ApplyBrakeForce(): Tüm tekerleklere fren torku uygular.
  • UpdateWheelVisuals(): Wheel Collider’ın pozisyon ve rotasyonunu alarak, tekerleklerin görsel modellerini fiziksel tekerleklerle senkronize eder. Bu sayede tekerlekler döner ve süspansiyon hareketlerini gösterir.

Unity Editöründe Ayarlar:

CarController script’ini CarChassis objesine ekledikten sonra, Inspector panelinde ‘Axle Infos’ listesini doldurmanız gerekecek. İki eleman ekleyin (biri ön aks, diğeri arka aks için). Her bir elemana ilgili Wheel Collider’ları sürükleyip bırakın ve ‘Motor’ ile ‘Steering’ kutucuklarını ihtiyacınıza göre işaretleyin:

  • Önden Çekişli (FWD): Ön aks için ‘Motor’ ve ‘Steering’ işaretli, arka aks için hiçbiri.
  • Arkadan İtişli (RWD): Arka aks için ‘Motor’ işaretli, ön aks için ‘Steering’ işaretli.
  • Dört Çeker (AWD): Her iki aks için ‘Motor’ işaretli, ön aks için ‘Steering’ işaretli.

motorForce, brakeForce, steerAngle ve maxSpeed gibi diğer ayarları da oyununuzun gereksinimlerine göre ayarlayın.

İleri Seviye Optimizasyonlar ve İpuçları

  • Anti-Roll Bar (Stabilizatör): Aracın virajlarda daha dengeli olmasını sağlamak için her aksa anti-roll bar ekleyebilirsiniz. Bu, bir taraftaki süspansiyon sıkıştığında diğer taraftaki süspansiyonu da etkileyen basit bir kuvvet uygulamasıyla yapılır.
  • Vites Sistemi: Motor torkunu, aracın hızına ve RPM’ine göre ayarlayan bir vites sistemi uygulayarak daha gerçekçi bir hızlanma eğrisi elde edebilirsiniz.
  • Traction Control (Çekiş Kontrolü): Tekerleklerin aşırı patinaj yapmasını önlemek için motor torkunu otomatik olarak ayarlayan bir sistem ekleyebilirsiniz.
  • ABS (Kilitlenme Karşıtı Fren Sistemi): Frenleme sırasında tekerleklerin tamamen kilitlenmesini engelleyerek direksiyon kontrolünü koruyan bir sistem geliştirebilirsiniz.
  • Farklı Yol Yüzeyleri: Farklı yol yüzeyleri (asfalt, toprak, kar vb.) için Wheel Collider’ın sürtünme değerlerini dinamik olarak değiştirmek, sürüş deneyimini zenginleştirir.
  • Kamera Takibi: Aracı takip eden ve sürüş deneyimini iyileştiren dinamik bir kamera sistemi entegre edin.

Sonuç

Unity’de fizik tabanlı araç kontrolü oluşturmak, oyunlarınıza derinlik ve gerçekçilik katan karmaşık ama ödüllendirici bir süreçtir. Bu rehberde öğrendiğiniz temel adımlar ve script sayesinde, kendi dinamik araçlarınızı tasarlayabilir ve oyuncularınıza unutulmaz sürüş deneyimleri sunabilirsiniz. Unutmayın, en iyi sonuçlar için Wheel Collider ayarları ve script değerleriyle denemeler yapmak ve oyununuzun türüne en uygun dengeyi bulmak önemlidir. İyi geliştirmeler!