
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ı
- Mevcut pozisyonu
. - Ö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
Burada
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
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
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