Unity’de Basit Bir İp Simülasyonu


Unity’de İp Simülasyonu: Verlet Entegrasyonu ve Jakobsen Metodu

Bu yazıda, Unity’de basit bir ip simülasyonu nasıl oluşturabileceğinizi anlatacağım. Bu örnekte, fizik tabanlı bir simülasyon ile ip parçacıkları arasında kısıtlamalar uygulayarak gerçekçi bir ip hareketi elde etmeye çalışacağız. Bunun için Verlet entegrasyonu ve Jakobsen kısıtlama metodu kullanılacak. Bu yöntemler, yüksek kararlılık ve gerçekçi sonuçlar elde etmemizi sağlar.

1. Temel Yapı

İp simülasyonu, birkaç temel adımda gerçekleştiriliyor. Öncelikle, ip parçacıklarını (particles) simüle ediyoruz. Her bir parçacık, ip üzerinde bir noktayı temsil ediyor ve bu noktalar arasında kısıtlamalar uygulayarak ipi oluşturan segmentlerin sabit bir uzunluğa sahip olmasını sağlıyoruz.

Bu simülasyon için RopeSimulation adlı bir sınıf oluşturduk ve bu sınıf, ip parçacıklarının hareketini, kısıtlamalarını ve çarpışmalarını yönetiyor.

Matematiksel olarak, ip parçacıkları olarak tanımlanabilir ve her bir parçacığın iki temel durumu vardır:

  1. Mevcut pozisyonu .
  2. Önceki pozisyonu .

Her iki pozisyon arasındaki fark bize parçacığın hızını verir.

2. Verlet Entegrasyonu ile Hareket Simülasyonu

Fizik tabanlı simülasyonlarda parçacıkların hareketini hesaplamak için çeşitli yöntemler kullanılabilir. Bu projede, Verlet entegrasyonu tercih edilmiştir. Verlet entegrasyonu, parçacıkların yeni pozisyonunu hesaplamak için mevcut ve önceki pozisyonlarını kullanır. Bu yöntem, yüksek kararlılık ve hız sunar, bu nedenle fizik tabanlı simülasyonlar için yaygın olarak tercih edilir.

Verlet Entegrasyonu Formülü

Verlet entegrasyonu formülü şu şekildedir:

Burada:

  • : Parçacığın yeni pozisyonu.
  • : Parçacığın mevcut pozisyonu.
  • : Parçacığın önceki pozisyonu.
  • : Parçacığa etki eden toplam ivme (genellikle yerçekimi).
  • : Zaman adımı (frame time).

Bu formül, fiziksel dengeyi koruyarak ve enerjiyi dengeleyerek, parçacıkların yeni konumunu hesaplar.

private void SimulateVerlet()
{
    foreach (var particle in _particles)
    {
        if (particle.locked) continue; // Sabitlenmiş parçacıklar hareket etmez

        var currentPos = particle.position;
        var velocity = currentPos - particle.previousPosition; // Hız tahmini

        var friction = particle.friction * velocity.magnitude;
        velocity -= velocity.normalized * friction; // Hızı sürtünme miktarında azalt
        velocity = Mathf.Max(velocity.magnitude, 0) * velocity.normalized; // Negatif hızları sıfırla

        particle.previousPosition = currentPos; // Önceki pozisyonu güncelle
        particle.position += velocity + gravity * (Time.deltaTime * Time.deltaTime * weight); // Yeni pozisyonu hesapla
    }
}

Bu kod parçası, her bir parçacığın yeni pozisyonunu hesaplar. Sürtünme kuvveti, parçacıkların hareketlerini yavaşlatmak için eklenmiştir.

İvme Hesaplamaları

Parçacıklara uygulanan ivme, genellikle yerçekimi kuvveti olarak tanımlanır. Bu durumda, yerçekimi kuvveti ile gösterilir ve parçacığa etkisi şu şekilde hesaplanır:

Burada , parçacığın kütlesidir. Bu kuvvet, pozisyon güncellemelerinde doğrudan ivme terimi olarak kullanılır.

3. Jakobsen Metodu ile Kısıtlamalar

Parçacıklar arasında belirli bir mesafeyi korumak, ip gibi nesnelerin gerçekçi hareket etmesi için önemlidir. Jakobsen metodu, bu kısıtlamaları uygulamak için kullanılan etkili bir yöntemdir. Jakobsen metodunun temelinde, her iki parçacık arasındaki mesafenin, istenen uzunluktan sapması durumunda, bu sapmayı düzeltmek yer alır.

Jakobsen Kısıtlama Formülü

İki parçacık arasındaki kısıtlama şu şekilde formüle edilir:

Burada:

  • : Parçacıklar arasındaki kısıtlama fonksiyonu.
  • ve : Parçacıkların pozisyonları.
  • : İstenen uzunluk (segmentLength).

Eğer sıfırdan büyükse (mesafe uzunsa), pozisyonlar ayarlanır. Aksi takdirde pozisyonlar sabit kalır.

private void EnforceConstraints()
{
    for (var i = 0; i < _particles.Count - 1; i++)
    {
        var p1 = _particles[i];
        var p2 = _particles[i + 1];

        var delta = p2.position - p1.position;
        var distance = delta.magnitude;
        var difference = (distance - segmentLength) / distance;

        if (!p1.locked && !p2.locked)
        {
            p1.position += delta * (0.5f * difference);
            p2.position -= delta * (0.5f * difference);
        }
        else if (p1.locked && !p2.locked)
        {
            p2.position -= delta * difference;
        }
        else if (!p1.locked && p2.locked)
        {
            p1.position += delta * difference;
        }
    }
}

Bu kod, her iki parçacık arasındaki mesafenin istenen uzunlukta kalmasını sağlar. Eğer iki parçacık arasındaki mesafe fazla ise, bu fark her iki parçacığa da eşit olarak dağıtılır. Bu sayede ip, gerçekçi bir şekilde esner ve bükülür.

4. Çarpışma Algılama ve Sürtünme Uygulama

İp simülasyonunda, parçacıkların belirli nesnelerle (örneğin, duvarlar veya zemin) çarpışması önemlidir. Çarpışma algılama işlemi, basit bir çarpışma kontrolü ile gerçekleştirilir. Bir parçacık bir nesneyle temas ederse, o parçacığın pozisyonunu düzeltir ve sürtünme kuvveti uygularız.

Çarpışma sonrası pozisyon düzeltmesi şu şekilde yapılır:

Burada , çarpışma sonrası düzeltme yapılan pozisyondur.

for (var i = 0; i < _particles.Count; i++)
{
    _particles[i].friction = 0;

    var pos = _particles[i].position;
    if (_customCollider.CheckContact(pos, out var point))
    {
        _particles[i].position = point;
        _particles[i].friction = friction;
    }
}

Bu mekanizma, parçacıkların belirli bir yüzeyle çarpışmasını kontrol eder ve gerektiğinde parçacığın pozisyonunu düzeltir. Ayrıca sürtünme kuvveti, parçacığın hızını yavaşlatmak için kullanılır.

Sürtünme Hesaplamaları

Sürtünme kuvveti, parçacığın hızını azaltmak için kullanılır. Bu kuvvet şu şekilde hesaplanır:

Burada:

  • : Sürtünme katsayısı.
  • : Norm kuvveti (genellikle yüzeye dik kuvvet).

Bu kuvvet, parçacıkların hızını yavaşlatmak için hıza ters yönde uygulanır.

Sonuç

Bu örnekte, Unity’de basit bir ip simülasyonu oluşturdum. Verlet entegrasyonu, Jakobsen kısıtlamaları ve çarpışma algılama mekanizmasıyla birlikte, gerçekçi bir ip simülasyonu elde etmek mümkündür. Bu yapı, farklı simülasyon türlerine uygulanabilir ve daha karmaşık fizik sistemlerine entegre edilebilir.

Unity’de bu tarz fizik tabanlı simülasyonlar, özellikle dinamik ve gerçekçi oyun mekaniği oluşturmak için son derece etkili olabilir. Bu temelleri kullanarak daha karmaşık projeler geliştire