Ana Sayfa Blog Sayfa 3

DOTween Doküman Türkçeleştirmesi

Merhabalar dostlar, bu yazıda halihazırda ingilizce halde bulunan DOTween Doküman Türkçeleştirmesi işlemini gerçekleştirip, yerli oyun geliştiricilerimiz için kullanmını daha kolay hale ve anlaşılır hale getireceğiz. Bilmeyenler için DoTween eklentisi  hakkında konuşmak gerekirse, Unity içerisinde bulunan, özel bileşenlerden tutun, float,int gibi temel tipteki değişkenlerdeki değerleri, istediğimiz değerlere istediğimiz sürede eşitliyor diye özetlemek sanırım yeterli olacaktır. Video olarak anlatımı sevenleriniz için de yaptığımız örnek videoların bırakıyorum. Ayrıca isterseniz şuradan orjinal dilde doküman incelemeniz de mümkün.

Öncelikle, tamamında Türkçe çeviri yapmayacağım için, bazı özel anahtar kelimeleri anlamanızı istiyorum. Başta bunları belirtip daha sonrasında yola devam etmek daha mantıklı olacak. Tween kelimesi, ingilizce derslerinden bildiğimiz “between” kelimesinden de aşina olacağınız şekilde “ara, arada” anlamlarına geliyor. Temel olarak değerlerimize belirli bir “aralık” vererek bunları değiştirmemize yardımcı olan bir yapı olarak karşımıza çıkıyor bu eklenti içerisinde. 

Tween kelimesi aslında eklenti içerisinde kullanabileceğimiz yapılara verebileceğimiz genel bir isim. Eklenti içerisinde yaratabileceğimi Tween tipleri ise Tweener, Sequence olarak ikiye ayırabiliriz. Bir de Nested Tween dediğimiz bir yapı var ki, bu da aslında bir Sequence içerisinde bulunan bir tweeni adlandırmak için kullandığımız bir şey.

DOTween Ön-Ekler

Ayrıca, kodlama kısmında da bazı şeylerden bahsetmek istiyorum. Prefixes olarak geçen kelimeler, DOTween ön-ekler olarak da adlandırabiliriz, kodlama konusunda bize rahatlık sağlayacak şeyler. 3 Adet bulunuyor, bunlar DO, Set, On kelimeleridir.

  • DO : Bütün temel değişken değeri değiştirme komutlarımız bu ön eke sahip. Örnek vermek gerekirse, DOMove() veya DOColor() fonksiyonları bu ön eke sahip. Bunlarlar konum ve renk değişimleri yapabiliyoruz. 
  • Set : Tween objelerimiz, yani değer değiştirme işlemlerimizin ayarları için kullanılan ön ek. Örneğin SetLoops() fonksiyonu ile, bu değişimin kaç defa tekrar edeceğini belirleyebiliriz.
  • On : On ön ekini callback dediğimiz etkileşimler için kullanıyoruz. Örneğin OnComplete() fonksiyonu sayesinde bir tween objemizdeki değiştirme işlemi tamamlandığında istediğimiz kodları çağırabiliriz. 

DOTween Başlatma

Normal şartlarda, DOTween Başlatma işlemini eklentinin kendisi otomatik olarak gerçekleştiriyor. Ancak temel ayarlardan memnun olmayabilirsiniz. Bu aşamada DOTween.Init() fonksiyonunu kullarak istediğiniz ayarları değiştirebilirsiniz. Bu Fonksiyonun alacağı 3 değişken bulunuyor.

  • recycleAllByDefault : Yarattığımız tween nesnelerinin tamamen yok edilip edilmediğini belirttiğimiz değişken. True değeri verirseniz, tween nesneleri yapacakları işlemleri tamamladıklarında, tamamen yok olmak yerine Object-Pooling mantığında olduğu gibi, bir havuzda toplayıp, gerektiğinde sıfırdan yaratmak yerine buradan erişmemizi sağlar. Ayrıca isterseniz istediğiniz zaman DOTween.defaultRecyclable seçeneğiyle bu ayarı değiştirebilirsiniz. Veya her bir tween nesneniz için ayrı olarak SetRecyclable() fonksiyonunu kullanabilirsiniz. Böylece belirli nesnelerin bu özelliği kullanmasını sağlayabilirsiniz.
  • useSafeMode : Verdiğimiz komutlar arkaplanda çok fazla ağır işlem gerektiriyor olabilir. Bu gibi durumların önüne geçmek için bu değişkene True değeri vermekte fayda var. Duruma göre daha yavaş çalışmalara sebep olabilir, ancak hata alma durumlarını da otomatik olarak algılayıp sorunu giderir. Bu hata alma durumlarından kasıt, a objesi b objesine doğru gidiyorken, b objesinin yok olması. Yani gidilecek konum için için null değer dönmesi buna bir örnek. 
  • logBehaviour :  Tamamen debug ekranında verilecek uyarılar için kullandığımız bir değişken. Sadece uyarıları, hataları veya bütün bildirimleri log ekranına yazdırmayı buradan seçebiliriz.
//Örnek başlatma komutu.
DOTween.Init(true, true, LogBehaviour.Verbose);

DOTween Tweener

Şimdi öncelikle Tweener yapısından bahsedelim. Tweener, tek başına sadece 1 değişken kontrol ettiğimiz değişken tipi. Dokümanın devamında görebileceğiniz gibi, istediğimiz değişikliği aslında bir değişken gibi tutup, sonrasında tekrar tekrar bu değişkeni kullanarak değişiklikleri yapabileceğiz. 

// 2,2,2 pozisyona 2 saniyede gitmemizi sağlayan
//bir tweener nesnesi yaratıyoruz ve bunu değişkene atıyoruz.
Tween myTween = transform.DOMove(new Vector3(2,2,2), 2);

Tweener Fonksiyonları

Tweener Fonksiyonlarını 3 başlığa ayırabiliriz. Bunlar Genel, Kısayol Fonksiyonlar ve Ekstra Genel fonksiyonlardır. 

Genel Fonksiyon: static DOTween.To(getter, setter , verilecekDeger, float sure). Bu fonksiyan, içerisine verdiğini herhangi bir değişkenin değerini verdiğini süre içerisinde istediğiniz değere getirir. Ayrıca sonunda From() eklerseniz, verdiğiniz değeri başlangıç değeri olarak alıp, şu anda sahip olduğu değere gelmesini sağlar. Bir nevi işlemi tersten yapar.

  • getter: Değiştirelecek özelliğin değerini sağlayan delegate. Lambda olarak yazılabilir. ()=> degiskenAdi: Buradaki degiskenAdi değiştirmek istenilen değişkendir.
  • setter: Verilmiş özelliğin değerini değiştiren delegate. Lambda olarak yazılabilir. Örneğin: x=> degiskenAdi = x
  • to : Özelliğin erişmesini istediğiniz değer.
  • sure : Değişimin süresi.
// vektorDegiskeni isimli değişken değerini        
 DOTween.To (() => vectorDegiskeni, x => vectorDegiskeni = x, new Vector3 (3, 4, 8), 3);
//From ekleyerek işlemi geri doğru yaptırıyoruz.
 DOTween.To (() => vectorDegiskeni, x => vectorDegiskeni = x, new Vector3 (3, 4, 8), 3).From ();

Kısayol Fonksiyonları: Bu fonksiyonlar, Unity özel bileşenlerine DOTWeen eklentisi aracılığıyla eklenen ekstra fonksiyonlardır. Bu sayede direkt bileşen ya da değişken üzerinden değişiklik yapabilirsiniz.

// Transform Bileşeni Örnek kullanım
transform.DOMove (new Vector3 (15, 0, 3), 3);
//Sprite Renderer Örnek kullanımı
spriteRenderer.DOColor (Color.green, 3);

Örnek kullanımlardan göreceğiniz üzere, aşağıda listeleyeceğimiz bileşen tiplerindeki değişkenlerinizde, sonuna “.” koyup yazarak çağırabilirsiniz.

Ses Karıştırıcı (AudioMixer):

  • DoSetFloat( string degiskenIsmi, float istenenDeger, float sure): AudioMixer nesnesi içerisinde erişime açık haldeki değişkenlerin istenilen değere istenilen sürede erişmesini sağlayan fonksiyon. Değişkenlerin el ile erişilebilir hale getirilmesi gerekir.

Ses Kaynağı (AudioSource):

  • DOFade(float istenenDeger, float sure): AudioSource nesnesini volume değerinin verilen sürede verilen değere çekilmesini sağlar.
  • DOPitch(float istenenDeger, float sure) :AudioSource nesnesinin pitch değerinin verilen sürede verilen değere çekilmesini sağlar. 

Kamera(Camera):

  • DOAspect(float istenenDeger, float sure) : Kamera objesinin aspect değerinin istenilen sürede istenilen değere çekilmesi sağlanır.
  • DOColor(Color istenenDeger, float sure) : Kameranın arkaplan rengini istenilen sürede verilen değer getirir.
  • DOFarClipPlane(float istenenDeger, float sure) : Kameranın farClipPlane değişkenini istenilen sürede istenilen değere getirir.
  • DOFieldOfView(float istenenDeger, float sure) : Kameranın Field of View değerini istenilen sürede istenilen değere getirir.
  • DONearClipPlane(float istenenDeger, float sure) : Kameranın nearClipPlane değerini istenilen sürede istenilen değere getirir.
  • DOOrthoSize(float istenenDeger, float sure) : Kameranın orthographicSize değerini istenilen sürede istenilen değere getirir.
  • DOPixelRect(Rect istenenDeger, float sure) : Kameranın pixelRect değerini istenilen sürede istenilen değere getirir.
  • DORect(Rect istenenDeger, float sure) : Kameranın rect değerini istenilen sürede istenilen değere getirir.
  • DOShakePosition(float sure, float/vector3 strength, int vibrato, float randomness, bool fadeOut) : Kamerayı lokal x-y ekseninde sallar.
    • From seçeneği yoktur.
    • strength : Sallamanın kuvveti. Float yerine Vector 3 kullanılırsa her eksende farklı bir kuvvet uygulanabilir.
    • vibrato : Kameranın sallanma titreşimi. 
    • randomness : Sallamanın rastgeleliği. 0-180 arası. 90 üzeri değerler kötüdür, bilginiz olsun. 0 değeri vermek sadece tek yönde sallama yapacaktır.
    • fadeOut  : (varolan:True) Eğer true değere sahipse tween’ler arası yumuşakça geçiş yapacaktır. 
  • DoShakeRotation(float sure, float/vector3 strength, int vibrato, float randomness, bool fadeOut) : Kameranın açısını lokal eksene göre sallar, silkeler.
    • From seçeneği yoktur.
    • strength : Sallama şiddeti. Float yerine Vector3 kullanmak her bir eksendeki şiddeti seçmenizi sağlar.
    • vibrato : Kamera sallama titreşimi.
    • randomness : allamanın rastgeleliği. 0-180 arası. 90 üzeri değerler kötüdür, bilginiz olsun. 0 değeri vermek sadece tek yönde sallama yapacaktır.
    • (varolan:True) Eğer true değere sahipse tween’ler arası yumuşakça geçiş yapacaktır. 

Işık(Light):

  • DOColor(Color istenenDeger, float sure) : Işığn rengini  verilen sürede istenen değere getirir.
  • DOIntensity(float istenenDeger, float sure) : Işığın yoğunluğunu verilen sürede istenen değere getirir.
  • DOShadowStrength(float istenenDeger, float sure) : Işığın gölge kuvvetini verilen sürede istenen değere getirir.
  • DOBleandableColor(Color istenenDeger, float sure) : Hedef ışığın rengini verilen sürede verilen değere getirir. DOColor fonksiyonundan farklı olarak aynı objeye bu fonksiyondan birden fazla şekilde uygulanabilir ve birbirlerine uyumlu olarak bir değişim sağlarlar.

LineRenderer: 

  • DOColor(Color2 baslangicDegeri, Color2 bitisDegeri, float sure) : Hedef bileşenin verilen sürede verilen değere(bitisDegeri) erişmesini sağlar. Burada  dikkat edilmesi gereken şey bu fonksiyonda ayrıca başlangıç değeri verildiğidir. Color2 iki farklı rengi tek bir değişkende bulundurmamızı sağlayan özel bir DOTween yapısıdır.
myLineRenderer.DOColor(new Color2(Color.white,Color.white), new Color2(Color.green, Color.black),1);

Materyal (Material):

  • DOColor(Color istenenDeger, float sure) : Hedef materyalin rengini istenen değerle değiştirir.
  • DOColor(Color istenenDeger, string ozellikAdi, float sure) :Materyalde belirtilen isimdeki alanın rengini istenen değerle değiştirir.
    //Materyalin specular değerini değiştirir: materyal.DOColor(Color.green,”_SpecColor”, 1);
    //burada bahsedilen alan materyal shader’ında geçen değerlerdir. Shader özelliklerinden değişkenlerin isimleri görülebilir.
  • DOColor(Color istenenDeger, int ozellikID, float sure) : Hedefte id’si verilen özelliğin değerini değiştirir.
  • DOFade(float istenenDeger, float sure) : Hedef materyaldeki alfa değeri üzerinde değişiklik yapar. Çalışması için kullanılan materyalin alfa özelliğini desteklemesi gerekir.
  • DOFade(float istenenDeger, string ozellikAdi, float sure) : Materyalde  verilen özelliğin alfa değerini değiştirir.
  • DOFade(float istenen deger, int ozellikID, float sure) : Materyalde id’si verilen özelliğin değerini değiştirir.
  • DOGradientColor(Gradient istenenDeger, float sure) :Materyalin rengini verilen gradient değeri ile değiştirir. Notlar: Sadece renkleri kullanır, alfa değerlerini kullanmaz.Tweener değil Sequence oluşturur.
  • DOGradientColor(Gradient istenenDeger, string ozellikAdi, float sure) :İsmi verilen özelliğin rengini verilen gradient ile değiştirir.Bir önceki notlar aynı şekilde geçerlidir.
  • DOGradientColor(Gradient istenenDeger, int ozellikID, float sure) :ID’si verilen özelliğin rengini verilen gradient değeri ile değiştirir. Bir önceki notlar aynı şekilde geçerlidir.
  • DOOffset( Vector2 istenenDeger, float sure) :Materyalin resim konumunu(textureOffset) verilen değerle değiştirir.
  • DOOffset(Vector2 istenenDeger, string ozellikAdi, float sure) : Materyalin adı verilen özelliğininin resim konumunu (textureOffset) verilen değerle değiştirir.
  • DOOffset(Vector2 istenenDeger, int  ozellikID, float sure) : Materyali id’si verilen özelliğinin resim konumun (textureOffset) verilen değerle değiştirir.
  • DOTiling(Vector2 istenenDeger, float sure) :Verilen materyalin resim büyüklüğünü (textureScale) verilen değerle değiştirir.
  • DOTiling(Vector2 istenenDeger, string ozellikAdi, float sure) :Materyalin ismi verilen özelliğinin resim büyüklüğünü (textureScale) verilen değerle değiştirir.
  • DOTiling( Vector2 istenenDeger, int ozellikID, float sure) : Materyalin id’si verilen özelliğinin resim büyüklüğünü (textureScale) verilen değerle değiştirir.
  • DOVector( Vector4 istenenDeger, string ozellikAdi, float sure) : Materyalin ismi verilen Vector özelliğinin değerini verilen değerle değiştirir.
  • DOVector( Vector4 istenenDeger, id ozellikID, float sure) : Materyalin id’si verilen Vector özelliğinin değerini verilen değerle değiştirir.
  • DOBlendableColor( Color istenenDeger, float sure) :Materyalin rengini, birden fazla DOBlendableColor fonksiyonun beraber uyumlu şekilde çalışmasına müsaade edecek şekilde yumuşatır.
  • DOBlendableColor( Color istenenDeger, string ozellikAdi, float sure) : Materyalin adı verilen özelliğin rengini, birden fazla DOBlendableColor fonksiyonun beraber uyumlu şekilde çalışmasına müsaade edecek şekilde yumuşatır.
  • DOBlendableColor( Color istenenDeger, int ozellikID, float sure) : Materyalin id’si verilen özelliğin rengini, birden fazla DOBlendableColor fonksiyonun beraber uyumlu şekilde çalışmasına müsaade edecek şekilde yumuşatır.

Rigidbody: Bu kısayollar rigidbody bileşenin MovePosition ve MoveRotation metotlarını arkaplanda kullanarak fizik objeleriyle bağlantılı nesneleri doğru şekilde hareket ettirirler.

  • DOMove(Vector3 istenenKonum, float sure, bool yuvarla): Nesneyi istenen konuma hareket ettirir.Eğer yuvarla true değere sahipse tween verilen değerleri int tipine yumuşakça yaslar.
  • DOMoveX/DOMoveY/DOMoveZ(float istenenDeger, float sure, bool yuvarla) : Nesneyi yalnızca seçilen eksende verilen değer konumuna hareket ettirir. Yalnız bilmeniz gerekir, bir eksene dair hareket yaptığınızda, diğer eksenlerdeki hareket kitlenecektir. Yuvarla isimli değişken bir önceki nottaki gibi çalışmaktadır.
  • DOJump(Vector3 istenenDeger, float ziplamaKuvveti, int ziplamaSayisi, float sure, bool yuvarlama) : Objeyi y eksenin zıplama efekti uygularken objeyi istenen konuma getirir. Not: Tweener objesi değil Sequence objesi döndürür.
    • istenenDeger: ulaşılacak konum.
    • ziplamaKuvveti: Zıplamanın kuvveti ( Zıplamanın maksimum yükseklik değeri)
    • ziplamaSayisi: Toplam zıplama sayısı.
    • yuvarlama: Eğer true değer verilirse bütün değerleri yumuşatarak tam sayı tipine yuvarlar.
  • DORotate(Vector3 istenenDeger, float sure, RotateMode mod) : Objeyi istenen değere döndürür.Quaternion değil Vector3 tipinde değer gerektirir. (Eğer Quaternion verisi kullanmak istiyorsanız, quaternion değişkeninizi degisken.eulerAngles şeklinde kullanabilirsiniz.) 
    • Modlar (RotateMode):
      • Fast (geçerli değer): Dönüş işlemi en kısa yoldan yapılır ve 360 dereceden daha fazla dönüş yapmaz.
      • FastBeyond360: Dönüş 360 dereceden daha fazla açı ile yapılır.
      • WorldAxisAdd: Verilen değeri world axis( oyundaki eksen) ve gelişmiş kesinlik modu ile transform değerlerine ekler. 
      • LocalAxisAdd: Verilen değeri local axis( obje ekseni ) değerine ekler.
  • DOLookAt(Vector3 hedef, float sure, AxisConstraint eksenSiniri, Vector3 up) : Objeyi verilen hedefe doğru çevirir.
    • eksenSiniri: Rotasyon için geçerli eksen sınırlaması. Varolan hali: AxisConstraits.None.
    • Up: Hangi yönün yukarı olduğunu gösteren değişken. Varolan hali: Vector3.up.
  • PRO ÖZELLİĞİ – DOSpiral(float sure, Vector3 eksen, SpiralMode mod, float hiz, float frekans, float derinlik, bool yuvarlama)
    • Objenin rigidbody pozisyonunu spiral şeklinde hareket ettirir.
    • sure: Hareket süresi.
    • eksen: Spiral dönüşün yapılacağı eksen. Varolan değer: null.  
    • mod:Spiral hareketin tipi. Varolan değer: SpiralMode.Expand.
    • hiz:  Dönüş hızı. Varolan değer: 1
    • frekans: Dönüş frekansı. Düşük değerler daha geniş spiraller oluşturur. Varolan değer: 10.
    • derinlik: Hareketin dönüş ekseninde ne kadar olacağını belirtir. Varolan değer: 0.
    • yuvarlama: True değeri verilirse bütün değerleri yumuşak bir şekilde tam sayı tipine yuvarlar.

Rigidbody2d: Bu kısayollar fizik objelerini düzgün şekilde hareket ettirmek için arkaplanda rigidbody2d bileşeninin MovePosition/MoveRotation methodlarını kullanır.

  • DoMove(Vector2 istenendeger, float sure, bool yuvarlama) :Objeyi istenen değere hareket ettirir. Yuvarlama degiskenine True değer verilirse bütün değerleri yumuşak bir şekilde tam sayı değerlere yuvarlar.
  • DOMoveX/DOMoveY(float istenenDeger, float sure, bool yuvarlama) : Objeyi seçilen eksendeki pozisyonunu istenen değere getirir. Seçilen eksen dışındaki değerler sabit kalacaktır. Yuvarlama degiskenine True değer verilirse bütün değerleri yumuşak bir şekilde tam sayı değerlere yuvarlar.
  • DOJump( Vector2 istenenDeger, float ziplamaKuvveti, int ziplamaSayisi, float sure, bool yuvarlama) : Objenin konumunu verilen konuma götürürken Y ekseninde zıplama efekti uygular. Not: Tweener değil Sequence nesnesi döndürür.
    • istenenDeger: Ulaşılacak konum.
    • ziplamaKuvveti: Zıplama kuvveti. 
    • ziplamaSayisi: Toplam zıplama sayısı.
    • yuvarlama:True değer verilirse bütün değerleri yumuşak bir şekilde tam sayı değerlere yuvarlar.
  • DORotate(float istenenAci, float sure) : Objeyi istenen açıya döndürür. (Dönüş Z ekseninde olacaktır.)

SpriteRenderer:

  • DOColor(Color istenenDeger, float sure) : Objenin rengini verilen sürede istenen değere getirir.
  • DOFade( float istenenDeger, float sure) : Obje renginin alfa değerini verilen sürede istenen değere getirir. 
  •  DOGradientColor(Gradient istenenDeger, float sure) : Objenin rengini verilen sürede istenen gradient değeri ile değiştirir.
  • DOBlendableColor(Color istenenDeger, float sure) : Objenin rengini verilen sürede verilen değere getirir. DOColor fonksiyonundan farklı olarak aynı objeye bu fonksiyondan birden fazla şekilde uygulanabilir ve birbirlerine uyumlu olarak bir değişim sağlarlar.

TrailRenderer: 

  • DOResize( float baslangicGenisligi, float bitisGenisligi, float sure) : Trailrenderer objesinin başlangıç ve bitiş genişliklerini verilen değerlerle değiştirir.
  • DOTime(float istenenDeger, float sure) : Objenin time değişkenini istenen değerle değiştirir.

Transform:

  • DOMove(Vector3 gidilecekKonum, float sure, bool yuvarlama): Verilen transform bileşenini kullanarak objeyi gidilecekKonuma istenilen sürede götürür. Eğer yuvarlama True değerinde olursa, atanacak değerleri tam sayıya yuvarlayıp atar. 
  • DOMoveX/DOMoveY/DOMoveZ(float gidilecekKonum, float sure, bool yuvarlama) : Seçtiğiniz konumun değerini, verdiğiniz süre içerisinde değiştirir. 
  • DOLocalMove(Vector3 gidilecekKonum, float sure, bool yuvarlama) : Seçili nesneyi Local Eksende hareket ettirir. 
  • DOLocalMoveX/DOLocalMoveY/DOLocalMoveZ(float gidilecekKonum, float sure, bool yuvarlama) : Seçilen lokal eksendeki konumu verilen zaman içerisinde değiştirir. 
  • DOJump(Vector3 gidilecekKonum, float ziplamaKuvveti, int ziplamaSayisi, float sure, bool yuvarlama) : Objenin zıplama hareketi yapmasını sağlar. ziplamaKuvveti ile yükseklik belirtilirken, ziplamaSayisi ile verilen konuma gidene kadar kaç defa zıplama hareketi yapacağı belirtilir. Tweener değil, Sequence tipinde değişken döndürür. 
  • DOLocalJump(Vector3 endValue, float jumpPower, int numJumps, float sure, bool snapping) : DOJump ile aynı çalışır, sadece lokal pozisyon değerlerini kullanır. 
  • DORotate(Vector3 istenenAci, float sure, RotateMode mode) : Nesnenin yönünü istenenAci değişkenine eşitler. RotateMode sayesinde farklı modlar denenebilir. Standart olarak RotateMode.Fast seçilidir. 
  • DORotateQuaternion(Quaternion istenilenYon, float sure) : Quaternion tipinde değişken vererek nesne yönünü değiştirmemizi sağlar. Ancak Vector3 tipinde değişken alan DoRotate önerilir. 
  • DOLocalRotate(Vector3 istenenAci, float sure, RotateMode mode) : Nesne lokal yönünü verilen sürede değiştirmemizi sağlar. 
  • DOLocalRotateQuaternion(Quaternion istenilenYon, float sure): Nesne lokal yönünü Quaternion tipinde değişkenler değiştirmemizi sağlayan fonksiyondur. DOLocalRotate() kullanılması önerilir.
  • DOLookAt(Vector3 konum, float sure, AxisConstraint eksenLimiti= AxisConstraint.None, Vector3 yukariYon= Vector3.up): İstenilen konuma bakılması sağlanır. eksenLimiti ile belirli eksenlerdeki hareketleri önleyebilirsiniz. Ayrıca hesaplamada yukarı yönü de ne olacağını belirtebilirsiniz. 
  • DOScale(float/Vector3 boyut, float sure): Objenin boyutlarını değiştirmenizi sağlar. Eğer float tipinde boyut verirseniz, bütün eksenlerde aynı büyüklüğe sahip olur. Vector3 kullanarak her eksende ayrı boyutlar verebilirsiniz.
  • DOScaleX/DOScaleY/DOScaleZ(float boyut, float sure) : Nesneyi seçtiğiniz eksende istediğiniz sürede boyutlandırmanızı sağlar. Bu sayede sadece tek bir eksende nesneyi büyültüp küçültebilirsiniz.
  • DOPunchPosition(Vector3 kuvvet, float sure, int sallantı, float esneklik, bool yuvarlama ): Objeyi, sanki bir yumruğa, darbeye maruz kalmış gibi belirtilen yönde ileri geri hareket ettirir, sallar ve eski konumuna döndürür. 
  • DOPunchRotation(Vector3 kuvvet, float sure, int sallantı, float esneklik) :DOPunchPosition ile aynı mantıkta çalışır, ancak pozisyon yerine rotasyon, açı değerlerine müdahale eder.
  • DOPunchScale(Vector3 kuvvet, float sure, int sallantı, float esneklik) : Objenin ani şekilde büyüyüp küçülmesini sağlayacak bir fonksiyondur. 
  • DOShakePosition(float sure, float/Vector3 kuvvet, int sallantı, float rastgelelik, bool yuvarla, bool yumuşat): Nesnenin pozisyon değerleriyle oynayarak, bir sallantı efekti oluşturur. 
  • DOShakeRotation(float sure, float/Vector3 kuvvet, int sallantı, float rastgelelik, bool yuvarla, bool yumuşat) : Objenin rotasyonune, açısına sallama etkisi oluşturur.
  • DOShakeScale(float sure, float/Vector3 kuvvet, int sallantı, float rastgelelik, bool yuvarla, bool yumuşat) : Nesnenin boyutlarıyla oynayarak rastgele büyüyüp küçülmeler sağlar. Görsel olarak bir kuvvet uygulanmış jöleyi düşünebilirsiniz. 
  • DOPath(Vector3[] waypoints, float sure, PathType yolTipi = Linear, PathMode yolModu= Full3D, int hassaslik= 10, Color gizmoColor = null) : Nesnenin Vector3 cinsinde bir dizi olarak verdiğimiz yolu izlemesini sağlar. Verilen konumlar arasında PathType değişkenine göre hareket eder. 3 çeşit yol tipi bulunmaktadır, bunlar Linear (Düz), CatmullRom ( Eğimli), CubicBezier(Eğimli) şeklindedir. hassaslik isimli değişken sayesinde, eğimli tipli yolların ne kadar hassas şekilde hesaplanacağını belirtiyoruz. Yüksek değerler daha yumuşatılmış bir eğim verecektir, ancak standart ayarı çoğu zaman işinizi görecektir. 
  • DOLocalPath(Vector3[] waypoints, float sure, PathType pathType = Linear , PathMode pathMode = Full3D, int resolution = 10, Color gizmoColor = null) : DOPath fonksiyonuyla aynı şekilde çalışır ancak lokal pozisyon değerlerini kullanarak işlem yapar. 
  • DOBlendableMoveBy(Vector3 by, float sure, bool yuvarla) : Blendable fonksiyon tipleri sayesinde aynı tipteki fonksiyonları birbiriyle çakışmadan aynı anda çalıştırabiliriz. Bu fonksiyonla da aynı anda birden fazla pozisyon değişikliği sağlayabiliyoruz. 
  • DOBlendableLocalMoveBy(Vector3 by, float sure, bool yuvarla) : Hareketi lokal pozisyonda yapmamızı sağlıyor.
  • DOBlendableRotateBy(Vector3 by, float sure, RotateMode mode) : Birden fazla açı, rotasyon işlemlerini birbirine uyumlu şekilde yapabilmemizi sağlar.
  • DOBlendableLocalRotateBy(Vector3 by, float sure, RotateMode mode) : Lokal açı, rotasyon işlemi yapmamızı sağlar. 
  • DOBlendableScaleBy(Vector3 by, float sure) : Nesnenin boyutlarını, büyüklüğü değiştirmek için kullanabildiğimiz fonksiyon. 

Tween : Evet, tween objelerini de tween ettirebiliyoruz. Açıkçası dokümanı okuyup çevirirken ben beklemiyordum haha. Sadece tek bir fonksiyon kullanabiliyoruz.

  • DoTimeScale(float yeniZamanSabiti, float sure): Tween objesinin hesaplarda kullandığı zaman sabitini değiştirmemizi sağlar. Normalde Unity’de de yaptığımız Time.timeScale değerini düşünün, aynı şekilde ancak sadece o atama yaptığınız tween için geçerli. Ve bunu aniden değil, yavaşça değiştirerek yapıyor tabii ki.

DOTween Sequence ve Fonksiyonları

Sequence tipi de aslında Tweener objesine benzer şekilde, ancak içerisinde bir sürü tweener bulunuyor. Yani istediğimiz değişiklikleri grup halinde tutup, ister arka arkaya ister eş zamanlı olarak değiştirebiliyoruz.

// Boş halde bir Sequence nesnesi yaratıyoruz
Sequence mySequence = DOTween.Sequence();
//X ekseninde 45 konumuna 1 saniyede gitmesi için bir tween ekliyoruz.
mySequence.Append(transform.DOMoveX(45, 1));
//Y ekseninde 180 dereceyi 1 saniyede dönmesi için bir tween ekliyoruz.
mySequence.Append(transform.DORotate(new Vector3(0,180,0), 1));
// Şu anki haliyle eklediğimiz tween nesneleri sırayla çalışacaktır. İstersek aynı anda çalışmalarını da sağlayabiliriz. 

Sequence Fonksiyonları

  • Append(Tween tween): Verilen tween objesini sekansın sonuna ekler.
    • mySequence.Append(transform.DoMoveX(45,1));
  • AppendCallback(TweenCallback callback): Sekansın sonuna bir callback fonksiyon eklemeyi sağlar.
    • mySequence.AppendCallback( fonksiyonAdi);
  • AppendInterval(float interval): Belirtilen süre kadar beklemeyi sekansa ekler. 
    • mySequence.AppendInterval(beklenilecekSure);
  • Insert(float atPosition, Tween tween) : Sekansa belirtilen süreye bir tween ekler.
    • mySequence.Insert(.5f,transform.DoMoveY(3,1));
  • InsertCallback(float atPosition, TweenCallback callback) : Sekansta belirtilen zaman bir callback fonksiyonu eklememizi sağlar.
    • mySequence.InsertCallback( 1.5f, fonksiyonAdi);
  • Join(Tween tween) : Verilen tween objesini sekans içerisinde o an en son bulunan elemanla aynı anda çalışacak şekilde sekansa ekler. Aynı anda birden fazla değişim için kullanabilirsiniz.
    • mySequence.Join(transform.DORotate(new Vector3(0,180,0), 1));
  • Prepend(Tween tween) : Verilen tween objesini sekansın başına ekler.
    • mySequence.Prepend(transform.DOMoveX(45, 1));
  • PrependCallback(TweenCallback callback) : Verilen callback fonksiyonu listenin başına ekler.
    • mySequence.PrependCallback(MyCallback);
  • PrependInterval(float interval) : Sekansın başlangıcına, listenin başına bir bekleme süresi eklemeyi sağlar.
    • mySequence.PrependInterval(interval);

Evet, böylece DOTween Doküman Türkçeleştirmesi işinin çoğunluğunu halletmiş olduk. Bazı kısımlar hâlâ eksik farkındayım ama çok uzun bir yazı oldu bu. Onları da ayrı bir yazı içerisinde oluşturabilirim ya da bu yazıyı zamanla güncelleyip buraya ekleyebilirim. Açıkçası hiçbir fikrim yok göreceğiz.

Unity Vector3 Nedir?

Merhaba dostlar, bu yazımızda Unity Vector3 Nedir ? sorusunu cevaplayıp, Vector3 adlı değişken tipinden, kullanım alanlarından ve yararlanabileceğimiz fonksiyonlardan bahsedeceğim. Vector3 Unity programı üzerinde kullanabileceğimiz, içerisinde 3 boyuttaki eksenlere denk gelen x,y,z adlı 3 float tipli değişken bulunduran, yani vektörel bir büyüklüğü belirtmek için kullandığımız değişken tipidir. Bu veri tipini Transform ile konumlandırmada, yön değiştirmede, boyut değişimlerinde ve özellikle Rigidbody bileşeni ile fizik işlemleri gerçekleştirirken sık sık kullanıyoruz. Benzer isimli olan Vector2 tipiyle fazlasıyla ortak özelliğe ve fonksiyona sahip ancak Vector2 sadece x ve y eksenleri için bileşenleri barındırıyor. Onun detaylarına farklı bir yazıda gireceğiz.

3 boyutlu uzayı ve eksenlerini düşündüğümüz, sağ yön ekseni (x), yukarı yön ekseni (y) ve ileri yön ekseni (z) bizim 3 boyut dediğimiz yapıyı oluşturuyor. İlkokuldan hatırlarsınız, sayı doğrusunu kullanarak bir noktanın konumunu belirtiyorduk. Sayı doğrusu tek başına aslında 1 ekseni belirtmekte, bir boyutlu bir dünyadaki hareketi göstermekte. Daha sonra ilerleyen aşamalarda çeşitli derslerden hatırlayacağınız üzere bir de yukarı yönlü bir sayı doğrusu eklendi buna. Yatay olana x, dikey olana y isimlerini vererek ilerledik. 3 boyutluyu okulda görmemiş olabilirsiniz ancak Unity ile biraz haşır neşir olduysanız o 3. eksenin, z ekseninin nasıl çalışacağını da tahmin edebilirsiniz. İşte Vector3 değeri, basitçe her bir eksenin değerini kendi içerisinde bir değişkende tutmamızı sağlayan ve kolaylıkla vektörel işlemleri uygulayabilmemizi sağlayan bir yapı.

Unity Vector3 Nedir Eksen
Unity Vector3 Nedir Eksen

Şimdi bu bahsettiğim 3 değişkenin ayrı ayrı eksenleri temsil ettiğini anlamışsınız, umuyorum ki. Bunu kavradıktan sonra artık Vector3 tipi için matematiksel işlemlerden bahsedeyim. Öncelikle şunu belirtmem gerekiyor, Vector3 tipindeki değişkenler birbiriyle yalnızca toplama ve çıkarma işlemi yapabilir. Çarpma ve bölme işlemlerinde ise int, float gibi diğer tipler kullanabiliriz. Unity’nin sağladığı farklı fonksiyonlar bulunuyor ancak temel matematik kullanmından bahsedeceğim için, yazının devamına bırakıyorum o konuyu. 

Vector3 cinsinde toplama ve çıkarma işlemi gayet basit. Her bir sayı doğrusu, eksen değerini, diğer vektörün eksen değeriyle işleme sokuyoru. Yani a=(1,5,3) ve b=(3,5,2) şeklinde iki değişken tanımlayalım, kodlamada böyle tanımlanmıyor bu arada sadece anlatım amacıyla böyle yazıyorum. Şayet a-b işlemi gerçekleştirirsek çıkacak sonuç (-2,0,1) olacaktır. X ekseninde 1-3, y ekseninde 5-5 ve son olarak z ekseninde 3-2 işlemini gerçekleştirerek bu sonuca erişmiş olduk. Ancak dikkatinizini çekmiş olabilir, şayet b-a işlemi yaparsak sonuç aynı olmayacak. b-a işlemini kafanızda yapmanızı istiyorum şimdi. Sakin sakin sabredin, cevap geliyor. Evet, b-a=(2,0,-1) çıktı. İncelediğimizde bu durum elde ettiğimiz vektörün büyüklük, uzunluk (magnitude) değerini farklılaştırmayacaktır. Ancak vektörler büyüklük dışında aynı zamanda yön de belirttiği için çok farklı bir yöne kuvvet uygulamamıza, hareket etmemize sebep olabilir. Tabii ki bu işlem çıkarma işlemlerinde geçerli, a+b ve b+a her zaman birbirine eşit olacaktır. 

Sıra çarpma ve bölmede, bu konuda gayet basit aslında. Yine yazının öncesinde belirtmiş olduğumuz a değişkenini kullanalım. Bir vektörle çarpma işlemi gerçekleştirdiğinizde çarpan olarak ancak int, float tipi değişkenler kullanabilirsiniz demiştim. Hemen uygulayalım, örneğin a*1.5f diyelim. Bu aşamada az çok tahmin edeceğinizi umuyorum. Sonuç (1.5, 7.5, 3) şeklinde olacak. Evet, çarpan olarak verdiğimiz değişkeni her bir eksen değeriyle ayrı ayrı çarpıp yeni eksen değerlerini elde ediyoruz. Şimdi bölme işlemi için de aynısını yapalım, hatta biraz pratik olması için size bırakıyorum. a değişkenini ilk başta tanımladığımız değerlere geri döndürmenizi istiyorum. Sakin sakin düşünün yine, biraz matematik pratiği olsun. Özellikle oyun programlamada bol bol ihtiyacımız olan bir şey matematik. Cevap : 1,5f .

Unity Vector3 İle Kullanılabilecek Kodlar

Unity Vector3 ile kullanılabilecek kodlar konusunu 3 başlık altında anlatacağım. Bu başlıklar özellikler-değişkenler, public metodlar ve static metodlar şeklinde ayrılır. Bu başlıklara geçmeden önce Vector3 sınıfını, tipinin kurucu fonksiyonundan bahsedeyim. Bu sayede öncelikle bir vektör değişkeni nasıl oluşturulur öğrenmiş olalım.

//yeni bir vektör oluşturur
//ve x =1, y=3,z=5 değer atamalarını yapar.
Vector3 ilkVector=new Vector(1,3,5);

Böylece bir vektör değişkeni elde etmiş olduk. Şimdi alt başlıklara geçmeden bazı statik özelliklerden, değişkenlerden bahsedeceğim. Bunlar daha çok uzun uzun vektör değerleri yazmaktan bizi kurtarmak için olan değişkenler aslında. Önce toplu halde açıklayıp sonrasında tek bir kod blogunda kullanımını göstereceğim.

  • back : Vector3(0,0,-1) yazmanın kısayolu.
  • down : Vector3(0, -1, 0) yazmanın kısayolu
  • forward : Vector3(0, 0, 1) yazmanın kısayolu
  • left : Vector3(-1, 0, 0) yazmanın kısayolu.
  • negativeInfinity : Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity) yazmanın kısayolu
  • one: Vector3(1, 1, 1) yazmanın kısayolu
  • positiveInfinity : Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity) yazmanın kısayolu
  • right : Vector3(1, 0, 0) yazmanın kısayolu
  • up : Vector3(0, 1, 0) yazmanın kısayolu
  • zero : Vector3(0,0,0) yazmanın kısayolu

Özellikler – Erişilebilir Değişkenler

Bu özellikler, değişkenler daha önce belirttiğimizin aksine her bir Vector3 değişkeni için farklı olan özelliklerdir.

magnitude: Vector3 değişkeninin büyüklük, uzunluk değerini float cinsinden döndürür.

normalized: Vector3 değişkenini alıp, x,y,z bileşen değerlerini vektörün boyutu 1 birim olacak şekilde hesaplar. Vectorün sadece büyüklüğünü değiştirir, yönünde bir değişiklik olmaz.

sqrMagnitude : Değişkenin uzunluğunun karesini elde etmemizi sağlar. magnitude özelliğinden daha hızlı çalışır. Çünkü bu uzunluğun hesaplanması adımlarında önce karesi elde edilir, ardından bunun karekökünü almak ve uzunluk değerine ulaşmak daha fazla işlem gerektirir. 

this[int] : değişkenin x,y,z değerine aynı dizilerde olduğu gibi index değerleriyle erişmemizi sağlar. x : 0, y : 1 ve z : 2 index değerine sahiptir.

x : Vektörün x eksenindeki değerini elde etmemizi sağlar.
y : Vektörün y eksenindeki değerini elde etmemizi sağlar
z : Vektörün z eksenindeki değerini elde etmemizi sağlar

    void Start () {
        Vector3 yeniVektor = new Vector3 (3, 4, 5);
        Debug.Log ("Vektör uzunluğu: " + yeniVektor.magnitude);
        Debug.Log ("Vektör normelleştirilmiş hali: " + yeniVektor.normalized);
        Debug.Log ("Vektör uzunluğunun karesi: " + yeniVektor.sqrMagnitude);
        Debug.Log ("İndex ile vektör değerleri : x=" + yeniVektor[0] + " y=" + yeniVektor[1] + " z=" + yeniVektor[2]);
        Debug.Log ("Vektör x değeri: " + yeniVektor.x);
        Debug.Log ("Vektör y değeri: " + yeniVektor.y);
        Debug.Log ("Vektör z değeri: " + yeniVektor.z);
    }
;

Public Metodlar

Angle () : Verilen iki vector değişkeni arasındaki açıyı float tipinde elde etmemizi sağlar. Bu açının alabileceği maksimum değer 180 derecedir olacaktır.

    void Start () {
        Vector3 ileri = new Vector3 (0, 0, 1);
        Vector3 sag = new Vector3 (1, 0, 0);
        Debug.Log ("ileri ve sağ yön vektörleri arasındaki açı :" + Vector3.Angle (ileri, sag));
    }

ClampMagnitude (): Vector değişkeninin yönünü aynı tutarak verilen uzunluğa göre kopyasını oluşturur ve bu kopya vector3 değerini bize döndürür. Bu sayede yönü koruyup daha kısa bir vektörel büyüklüğü sahip halde elde edebiliriz. Eğer verdiğimiz uzunluk değeri varolan vektör büyüklüğünden büyük ise, varolan değeri değiştirmeyecektir. Ayrıca, tam tersi yönde bir vektör elde etmek için büyüklük için negatif değer verebilirsiniz.

    void Start () {
        Vector3 vektor = new Vector3 (3, 4, 5);
        Vector3 birimVektor = Vector3.ClampMagnitude (vektor, 1);
        Vector3 zitYondekiVektor = Vector3.ClampMagnitude (vektor, -vektor.magnitude);
        //Log ekranında değerleri görelim
        Debug.Log ("Orjinal Vektor :" + vektor + " uzunluğu: " + vektor.magnitude);
        Debug.Log ("1 birim haline getirilmiş Vektor :" + birimVektor + " uzunluğu: " + birimVektor.magnitude);
        Debug.Log ("Zıt yöndeki Vektor :" + zitYondekiVektor + " uzunluğu: " + zitYondekiVektor.magnitude);
        //DrawRay ile Scene panelinde görselleştirelim
        Debug.DrawLine (Vector3.zero, vektor, Color.red, Mathf.Infinity);
        //birimvektor için çizeceğimiz çizgi daha kısa olacağı için göremeyebilrsiniz. Bunun için üst satırdaki DrawLine komutunu yorum satırı haline getirip tekrar gözlemleyin
        Debug.DrawLine (Vector3.zero, birimVektor, Color.blue, Mathf.Infinity);
        Debug.DrawLine (Vector3.zero, zitYondekiVektor, Color.green, Mathf.Infinity);
    }

Cross (): Verilen iki vektörün cross product isimli, bu iki vektöre de dik olan bir vektör elde etmemizi sağlar. Değişkenlerin sırası önemlidir, sıraları değiştiğinde elde edilecek sonuç birbirinin zıttı yönde olacaktır. Unity Vektörel işlemlerde, hesaplamalarda sol el kuralını kullanmaktadır.

    void Start () {
        //rastgele vektörler oluşturuyoruz
        Vector3 ilkVektor = new Vector3 (3, 4, 5);
        Vector3 ikinciVektor = new Vector3 (-3, 3, 1);
        Vector3 crossProduct = Vector3.Cross (ilkVektor, ikinciVektor);
        Vector3 tersCrossProduct = Vector3.Cross (ikinciVektor, ilkVektor);
        //DrawRay ile Scene panelinde görselleştirelim
        Debug.DrawLine (Vector3.zero, ilkVektor, Color.red, Mathf.Infinity);
        Debug.DrawLine (Vector3.zero, ikinciVektor, Color.blue, Mathf.Infinity);
        Debug.DrawLine (Vector3.zero, crossProduct, Color.green, Mathf.Infinity);
        Debug.DrawLine (Vector3.zero, tersCrossProduct, Color.yellow, Mathf.Infinity);
    }

Distance (): Verilen iki Vector3 değişkeni arasındaki mesafeyi elde etmemizi sağlar. 

    //düşman objesi yaratıp inspector üzerinde atamayı unutmayın
    [SerializeField]
    Transform dusman;

    void Update () {
        //yarattığımız bir düşman objesi ile aramızdaki mesafeyi belirliyoruz.
        Debug.Log ("Düşman ile aradaki mesafe : " + Vector3.Distance (dusman.position, transform.position));
    }

Dot (): İki vektörün aynı yöne doğru bakıp bakmadığını anlamakta da kullanabileceğimiz, vektörlerin büyüklüklerini aralarındaki açının kosinüsü ile çarparak elde edilen bir sayı döndüren fonksiyondur. Baya karmaşık gelmiş olabilir, farkındayım. Ancak örneği incelemek biraz daha anlamanızı sağlayacaktır. -1 ve 1 arasında değerler döndürür. 1 değeri veriyorsa vektörler aynı yöne bakıyordur, -1 değeri veriyorsa zıt yöne. Eğer 0 değeri veriyorsa iki vektör birbirine dik, aralarında 90 derece var demektir.

    //Düşman objesi oluşturup atamayı unutmayın
    [SerializeField]
    Transform dusman;

    void Update () {
        //eğer düşman objesi tanımlandıysa
        if (dusman) {
            //düşman ile aramızdaki yön değerini vector3 olarak elde ediyoruz
            Vector3 dusmanYonu = dusman.position - transform.position;

            Color isinRengi;
            //Eğer düşman yönü ile bizim ileri yönümüzü kullanarak
            //elde ettiğimiz Dot değeri pozitif ise düşman önümüzde
            //negatif ise düşman arkamızda olacaktır. 
            //önce veya arkada olma durumuna göre ışın için renk ayarı yapıyoruz
            if (Vector3.Dot (transform.forward, dusmanYonu) < 0) {
                Debug.Log ("Düşman Arkamda");
                isinRengi = Color.red;
            } else {
                isinRengi = Color.green;
            }
            //Işın çizdirerek görselleştirelim
            Debug.DrawRay (transform.position, dusmanYonu, isinRengi);

            //bizim ileri yönümüz
            Debug.DrawRay (transform.position, transform.forward, Color.blue);
        }
    }

Lerp (): Lerp fonksiyonu farklı matematiksel değişkenlerde de karşımıza çıkan, iki değer arasında belirli bir orana göre değer almamızı sağlayan fonksiyondur. Örneğin bu fonksiyon sayesinde bir objeyi başlangıç ve bitiş noktaları arasında hareket ettirebiliriz. Verdiğimiz oranın değeri 0-1 arasındadır ve 0 verirsek ilk değeri, 1 verirsek 2.değeri elde ederiz.

    Vector3 baslangicPozisyonu, bitisPozisyonu;

    float oran = 0.5f;

    void Start () {
        //başlangç pozisyonunu x ekseninde -5 konumuna koyuyoruz
        baslangicPozisyonu = Vector3.left * 5;
        //bitis pozisyonunu x ekseninde +5 konumuna koyuyoruz
        bitisPozisyonu = Vector3.right * 5;
        //objeyi başlangıçta 0,0,0 noktasına yerleştiriyoruz
        transform.position = Vector3.zero;
    }

    void Update () {
        //a ve d tuşları ile oranı ne kadar arttıracağımızı belirliyoruz
        float oranArtisi = Input.GetAxis ("Horizontal") * .1f;
        oran += oranArtisi;
        //oran değerinin 0-1 arasında olduğundan emin oluyoruz
        if (oran > 1f) {
            oran = 1;
        } else if (oran < 0) {
            oran = 0;
        }

        //a ve tuşlarına basarak hareket ettirirken, belirlenen iki pozisyon arasında hareketi kısıtlamış oluyoruz böylece
        transform.position = Vector3.Lerp (baslangicPozisyonu, bitisPozisyonu, oran);

    }

LerpUnclamped (): Lerp gibi çalışır, ancak alabileceği oran değeri 1’den büyük veya 0’dan küçük olabilir. Bu sayede ikinci değişkenin ötesine geçebiliriz. iki değer arasındaki oran korunarak ilerler. Yukarıdaki örneğe benzer şekilde bir örnek oluşturduğumu farkedeceksiniz. Bu kısımda 5 değeri yerine 1 kullanmayı tercih ettim, bu değeri değiştirerek sizde harekete nasıl etki ettiğini görebilirsiniz.

    Vector3 baslangicPozisyonu, bitisPozisyonu;

    float oran = 0.5f;

    void Start () {
        //başlangç pozisyonunu x ekseninde -1 konumuna koyuyoruz
        baslangicPozisyonu = Vector3.left * 1;
        //bitis pozisyonunu x ekseninde +1 konumuna koyuyoruz
        bitisPozisyonu = Vector3.right * 1;
        //objeyi başlangıçta 0,0,0 noktasına yerleştiriyoruz
        transform.position = Vector3.zero;
    }

    void Update () {
        //a ve d tuşları ile oranı ne kadar arttıracağımızı belirliyoruz
        float oranArtisi = Input.GetAxis ("Horizontal") * .1f;
        oran += oranArtisi;
        //a ve tuşlarına basarak hareket ettirirken, belirlenen iki pozisyon arasında hareketi kısıtlamış oluyoruz böylece
        transform.position = Vector3.LerpUnclamped (baslangicPozisyonu, bitisPozisyonu, oran);
    }

Max (): Verdiğimiz iki vektörün x,y,z bileşenlerinden en büyük değerleri alarak bize yeni bir Vector3 değişkeni oluşturur.

    //Verilen iki vektör değişkenin en büyük bileşenlerini alarak
    //yeni bir vektor oluşturur;
    void Start () {
        Vector3 vektor1 = new Vector3 (15, -3, 5);
        Vector3 vektor2 = new Vector3 (3, -1, 7);
        Vector3 enBuyukDegerler = Vector3.Max (vektor1, vektor2);
        Debug.Log (enBuyukDegerler);
    }

Min ():V erdiğimiz iki vektörün x,y,z bileşenlerinden en küçük değerleri alarak bize yeni bir Vector3 değişkeni oluşturur.

    //Verilen iki vektör değişkenin en küçük bileşen değerlerini alarak
    //yeni bir vektor oluşturur;
    void Start () {
        Vector3 vektor1 = new Vector3 (15, -3, 5);
        Vector3 vektor2 = new Vector3 (3, -1, 7);
        Vector3 enKucukDegerler = Vector3.Min (vektor1, vektor2);
        Debug.Log (enKucukDegerler);
    }

MoveTowards (): Başlangıç ve bitiş noktalarını verdiğimiz ve adım adım başlangıçtan bitişe hareket etmemizi sağlayan fonksiyondur. Daha yumuşak ve kontrollü bir hareket elde etmemizi sağlar.

    //basit bir nöbet sistemi olarak kullanabilirsiniz
    //obje belirtilen nöbet noktaları arasında sürekli olarak sırayla dolaşacaktır 
    float hiz = 5f;
    int nobetNoktasiID = 0;
    //4 nöbet noktası ekler
    //ayrıca inspector üzerinde değiştirip yenilerini ekleyebilirsiniz
    [SerializeField]
    Vector3[] nobekNoktalari = new Vector3[] {
        new Vector3 (0, 15, 15),
        new Vector3 (0, -15, 15),
        new Vector3 (0, -15, -15),
        new Vector3 (0, 15, -15),
    };
    void Start () {
        //objeyi ilk nöbet noktasında başlatır
        transform.position = nobekNoktalari[0];
        nobetNoktasiID = 1;
    }
    //iki konum arasında obje hareketini tekrar etmesini sağlayabiliriz
    void Update () {
        float adım = hiz * Time.deltaTime;
        // seçili olan nöbet noktasına adım adım ilerlememizi sağlar
        transform.position = Vector3.MoveTowards (transform.position, nobekNoktalari[nobetNoktasiID], adım);
        //eğer nöbet noktasını yaklaştıysak zıt yönde olacak şekilde tekrar güncelliyoruz
        if (Vector3.Distance (transform.position, nobekNoktalari[nobetNoktasiID]) < .1f) {
            //bölümden kalan sayesiyle sürekli döngü halinde hareket etmesini sağlayabiliriz
            nobetNoktasiID = (nobetNoktasiID + 1) % nobekNoktalari.Length;
            Debug.Log ("Yeni nöbet noktası id: " + nobetNoktasiID + " konum: " + nobekNoktalari[nobetNoktasiID]);
        }
    }

Normalize (): Vektör değişkenini 1 birimlik uzunluğa sahip olacak şekilde x,y,z bileşenlerini değiştirir. normalized özelliğinden farklı olarak bu değişken üzerinde değişiklik yapmaktadır. Eğer değişken değerinin aynı kalmasını istiyorsanız ve normalleştirilmiş haline ihtiyacınız varsa normalized özelliğini kullanmak daha doğru olacaktır.

    void Start () {
        Vector3 vektor = new Vector3 (3, 4, 5);
        Debug.Log ("Asıl Vektor Uzunluğu: " + vektor.magnitude);
        Vector3.Normalize (vektor);
        Debug.Log ("Normalize Fonksiyonu Ardından Uzunluk:" + vektor.normalized);
    }

OrthoNormalize (): Verilen vektörleri normalleştirir ve birbirine dik hale getirir.

    void Start () {
        ilkVector = new Vector3 (15, 3, 0);
        ikinciVektor = new Vector3 (3, 4, 5);
        ucuncuVektor = new Vector3 (4, 5, 6);

        ilkVectorOrj = ilkVector;
        ikinciVektorOrj = ikinciVektor;
        ucuncuVektorOrj = ucuncuVektor;
        Vector3.OrthoNormalize (ref ilkVector, ref ikinciVektor, ref ucuncuVektor);
    }

    void Update () {
        //saniyede 1 sırayla kullanılan vektörlerin orjinallerini
        // ve OrthoNormalize ray çizerek gözlemleyebilirsiniz
        if (Time.time % 2 < 1) {
            Debug.DrawRay (Vector3.zero, ilkVector, Color.red);
            Debug.DrawRay (Vector3.zero, ikinciVektor, Color.blue);
            Debug.DrawRay (Vector3.zero, ucuncuVektor, Color.green);
        } else {
            Debug.DrawRay (Vector3.zero, ilkVectorOrj, Color.black);
            Debug.DrawRay (Vector3.zero, ikinciVektorOrj, Color.white);
            Debug.DrawRay (Vector3.zero, ucuncuVektorOrj, Color.gray);
        }
    }

Project (): Bir vektörün başka bir vektör üzerine izdüşümünü elde etmemizi sağlar. Bunu bir nesnenin yere düşen gölgesini elde etmek olarak da düşünebiliriz. İki değişken alır, gölge örneğini düşünürsek ilk değişken gölgeye sahip olacak nesne, ikinci değişken zemin, bize döndürdüğü değer de ilk vektör değişkeninin ikinci vektör değişkeni üzerindeki gölgesi, izdüşümü olacaktır.

    void Start () {
        Vector3 vektor = new Vector3 (3, 14, 7);
        //Vektörün kendisi
        Debug.DrawRay (Vector3.zero, vektor, Color.white, Mathf.Infinity);

        //X eksenine izdüşümü
        Debug.DrawRay (Vector3.zero, Vector3.Project (vektor, Vector3.right), Color.red, Mathf.Infinity);
        //Y eksenine izdüşümü
        Debug.DrawRay (Vector3.zero, Vector3.Project (vektor, Vector3.up), Color.green, Mathf.Infinity);
        //Z eksenine izdüşümü
        Debug.DrawRay (Vector3.zero, Vector3.Project (vektor, Vector3.forward), Color.blue, Mathf.Infinity);

        // ya da eksenler dışında direkt bir örnek kullanalım
        // (1,1,1) güzel bir değer olabilir. Yorum satırlarını silmeyi unutmayın
        //Vector3 izdusumEkseni = new Vector3 (1, 1, 1);
        //izdüşümü
        //Debug.DrawRay (Vector3.zero, Vector3.Project (vektor, izdusumEkseni), Color.red, Mathf.Infinity);
    }

ProjectOnPlane (): Project gibi çalışır, ancak ikinci bir vektör yerine, bir normal vektör değeri alır. Burada kastedilen normal ise, bir yüzeye tam olarak dik olan vektör manasındadır. Yani tam olarak bir yüzeye izdüşümünü elde etmek için kullanabileceğimiz bir fonksiyondur.

    //0,0,0 noktaında bir plane objesi oluşturup bu alana atayın
    [SerializeField]
    Transform planeObjesi;
    //inspector ekranında vektör değerini değiştirebilirsiniz
    [SerializeField]
    Vector3 vektor = new Vector3 (3, 4, 5);

    Vector3 projectOnPlane;

    // Çalıştırdıktan sonra hem vektor değeriyle
    // hem de plane objesinin açısıyla oynayıp gözlemlemenizi öneririm 
    void Update () {
        //plane objesinde yüzeyin normali, yani yüzeye dik olan değeri transform.up özelliği ile kolayca elde edebiliriz
        //ilk değişken vektörün kendisi, ikinci değişken de normal vektör
        projectOnPlane = Vector3.ProjectOnPlane (vektor, planeObjesi.up);
        //plane üzerine iz düşüm 
        Debug.DrawRay (Vector3.zero, projectOnPlane, Color.green);
        //orjinal vektör
        Debug.DrawRay (Vector3.zero, vektor, Color.red);
    }

Reflect (): Bir Vector3 değişkenin, aynı herhangi bir nesnenin bir aynada sahip olduğu yansıması gibi, bir normal ekseni kullanılarak yansıması elde edilmesini sağlayan fonksiyondur. İlk değişkeni yanstılacak orijinal obje, diğer değişken de yansıtma için kullanılacak Vektor3 tipindeki değişkendir.

    public Transform ilkNesne;
    public Transform yansitilacakNesne;

    //çalıştırma esnasında ilkNesne'ye atadığınız değişkenin konumunu
    //inspector veya scene paneli üzerinden değiştirdiğinizde
    //yansitilacak nesne de hareket edecek, aynadaki bir yansıma gibi davranacaktır.
    void Update () {
        //Z eksenini kullanarak aynalama, yansıma efekti oluşturup
        //yansitilacak nesnenin pozisyonunu belirliyoruz.
        // ikinci değerde farklı vector3 değerleri vererek değişiklikler yapıp gözlemleyebilirsiniz
        yansitilacakNesne.position = Vector3.Reflect (ilkNesne.position, Vector3.right);
    }

RotateTowards ():Aynı MoveTowards fonksiyonunda olduğu gibi, bir vektörden diğerine yumuşak ve kontrollü şekilde geçiş yapmamızı sağlar ancak burada konum yerine yön değişimi yapılmaktadır.

Scale (): 2 Vector3 tipinde değişkeni çarpmamızı sağlar. Burada çarpma işlemi x,y,z bileşenlerinin birbiri arasında olmaktadır. Vector3 tipinde yeni bir değişken elde etmemizi sağlar.

    void Start () {
        Vector3 a = new Vector3 (3, 1, 6);
        Vector3 b = new Vector3 (3, 4, 2);
        Debug.Log (Vector3.Scale (a, b));
    }

SignedAngle (): Angle fonksiyonu gibi iki vektör arasındaki açıyı elde etmemizi sağlar. Ancak farklı olarak bu fonksiyon ile 0 ile 180 arasında değil -180 ile 180 arasındaki açı bilgisini elde edebiliriz.

    [SerializeField]
    Transform hedef;
    //verilen hedefin belilri bir offsete göre sağda veya solda olduğunu belirtir
    void Update () {
        Vector3 hedefYonu = hedef.position - transform.position;
        //Vector3.up kullanarak y eksenin temel alıp bu eksen üzerindeki açıyı elde ediyoruz
        float angle = Vector3.SignedAngle (hedefYonu, transform.forward, Vector3.up);
        if (angle > 5f) {
            Debug.Log ("Hedef Sağda");
        } else if (angle < -5f) {
            Debug.Log ("Hedef Solda");
        } else {
            Debug.Log ("Hedef Önünde");
        }
    }

Slerp (): Lerp fonksiyonu gibi çalışır ancak burada dümdüz bir hat üzerinde ilerlemek yerine izlenecek yol bir kürenin üzerinden ilerleniyormuş gibi olacaktır. Örnek vermek gerekirse, kuzey kutbundan güney kutbuna normal şartlarda dünyanın içinden geçip gidemeyiz, yüzeyinden dolanmamız gerekir. Bu fonksiyon sayesinde bu küresel hareketi sağlayabiliriz. Lerp fonksiyonunda olduğu gibi vereceğimiz oran değeri 0-1 arasında olmalıdır.

    //basit bir gün doğumu-batımı hareketi sağlıyoruz
    // iki tane boş obje oluşturup birini x eksenin -15 diğerini de 15 konumuna getirin ve bu alanlara atayın
    public Transform gunDogumu;
    public Transform gunBatimi;

    // Gün süresi saniye cinsinden
    public float gunSuresi = 15f;

    // başlangıç zamanı
    private float baslangic;

    Vector3 merkez;

    void Start () {
        // Başlangıç değerini atıyoruz
        baslangic = Time.time;
        // gundoğumu ve batımı arasındaki orta nokta
    }

    void Update () {
        Vector3 merkez = (gunDogumu.position + gunBatimi.position) * 0.5F;
        // merkezi y ekseninde azaltarak küresel hareketi dikey hale getiriyoruz
        //1'den daha büyük değerler vererek ulaşacağı en yüksek noktayı arttırabilirsiniz.
        merkez -= new Vector3 (0, 1, 0);

        // varolan merkezi
        Vector3 gunDogumMerkezi = gunDogumu.position - merkez;
        Vector3 gunBatimiMerkezi = gunBatimi.position - merkez;
        //geçen zaman ile gün süresinin bölümü ile oranı belirliyoruz
        float tamamlananZaman = (Time.time - baslangic) / gunSuresi;
        //günün kaçta kaçı geçtiyse, bu oranı kullanarak iki konum arasında küresel bir hareket sağlıyoruz
        transform.position = Vector3.Slerp (gunDogumMerkezi, gunBatimiMerkezi, tamamlananZaman);
        transform.position += merkez;
    }

SlerpUnclamped (): Slerp gibi çalışır ancak daha önce de LerpUnclamped değerinde gördüğümüz gibi, iki nokta arasındaki oran 0’dan küçük veya 1’den büyük olabilir. Verdiğimiz noktaların ilerisine ya da gerisine bu küresel hareketi koruyarak ulaşabiliriz. Bir önceki örnekte Slerp Yerine SlerpUnclamped kullanarak bu dairesel hareketi elde edebilirsiniz.

SmoothDamp (): Verilen vektor değerine aniden erişmek yerine, yumuşatarak erişmemizi sağlayan bir fonksiyondur. En basit kullanım örneği ise bir objenin başka bir objeyi yumuşatılmış, anında kendini ışınlamadan takip etmesi işlemidir.

    public Transform hedef;
    public float yumusatmaCarpani = 0.3F;
    private Vector3 velocity = Vector3.zero;

    void Update () {
        // Takip için araya belirli bir mesafe koyarak hedef konumumuzu belirliyoruz
        Vector3 hedefPozisyon = hedef.TransformPoint (new Vector3 (0, 5, -10));

        // Objenin pozisyonunu hedef pozisyona yumuşatarak erişerek güncelliyoruz.
        transform.position = Vector3.SmoothDamp (transform.position, hedefPozisyon, ref velocity, yumusatmaCarpani);
    }

Böylelikle Vector3 Nedir ve bu değişken tipiyle kullanabileceğimiz metodlar ve değişkenlere göz atmış olduk. Yanılmıyorsam 1-2 adet metoda değinmeden geçtim, bazılarınız farketmişsinizdir. Bu pas geçtiğim fonksiyonlar ciddi anlamda ileri seviye ve kullanımına dair bir örnek yapmak bile yazının tamamını çok fazla kaplayacağını düşünüyorum. Belki ileride onlara da dair de örnekler oluşturabiliriz. Şimdilik bu şekilde yazımızı tamamlayalım. Yeni yazılarda görüşmek dileğiyle, kendinize iyi bakın.

Unity Abstract Class ve Interface Kavramları

Selamlar dostlar, bu yazımızda Unity Abstract Class ve Interface Kavramları üzerine konuşup, örneklerle pekiştireceğiz. Bu iki yapıyı kullanarak hem daha okunaklı, performanslı kodlar yazabilir hem de daha organize halde çalışabiliriz. Abstract Class ve Interface kavramları aslında inheritance ( miras alma ) konusunu içerisindedir. Basitçe tanımlamak gerekirse, Abstact Class objenin en temel halini tanımladığımız, Interface ile ise objelerin yapabileceklerini belirttiğimiz durumlarda kullandığımız özelliklerdir.

Şimdi Abstract Class ile başlarsak, objenin en temel hali olarak bahsetmiştik. Örnek olması amacıyla, bir elma nesnesi yaratacağımızı düşünelim. Bu elma nesnesi aslında oyun içerisinde envanterimize alabileceğimiz bir objedir. Yani en genel kapsayıcı haliyle bir envanter itemidir. Bir kılıç da aynı şekilde  envantere alınabilir. Elma isimli nesneyi “meyveler” adlı bir sınıftan, kılıç nesnesini de “ekipman” isimli bir sınıftan üretebiliriz. Ancak bu iki sınıf da “envanterItemi” adlı abstract class üzerinden miras alacak ve ağırlık, envanter boyutu gibi değşikenlere veya kullanmak amacıyla fonksiyonlara sahip olacaktır. Bu ortak noktalardan dolayı abstract class kullanmak işinize yarayacaktır. Ayrıca belirtmekte fayda var, bir sınıf ancak 1 tane abstract sınıftan miras alabilir. 

Hangi durumlarda kullanacağınızdan emin olamamanız halinde, genel bir sorgulama yöntemi kullanabilirsiniz. İngilizce’de “is-a” şeklinde bir soru yapısı kullanılıyor. Örneğin “fruit is an inventory item” kelimesini ele alırsak, Türkçe olarak “elma envanter itemi midir?”  diye bir soru soruyoruz aslında. Bu soruyu sorarak kullanma konusundaki kararsızlığınızı giderebilirsiniz.

Interface kavramı ise, Abstract Class ile benzer yönlere sahip olsa da, en önemli farklarından biri, fonksiyonlar içerisinde komutlar yazamayız veya değişkenlere değer atayamayız. Interface içerisinde sadece bunların tanımlamalarını yapabiliyoruz. Daha sonrasında oluşturduğumuz inteface’i miras alan sınıflarda bu fonksiyonları ve değişken atamalarını yapabiliyoruz. Bu arada belirtmekte fayda var, değişken diyorum ama aslında properties-özellikler dediğimiz yapıları tanımlayabiliyoruz. Bunlar aracılığıyla da alt sınıflarda değişkenleri değiştirebiliyoruz. Ayrıca, abstract class kullanımından farklı olarak, bir sınıf birden fazla Interface üzerinden miras alma işlemini gerçekleştirebilir.

Kullanım konusuna geldiğimizde ise daha fazla kararsız kalmanıza sebep olabilecek bir yapı aslında bu. “Bu nesne ne yapabilir?” diye düşünmek biraz bizi kurtarıyor bu aşamada. Örneğin geometrik şekillerin alanını hesaplatmak, elde etmek için bir method kullanmak istediğimizde üreteceğimiz her şeklinde “AlanHesapla()” ismiyle bir fonksiyona sahip olmasını isteyebiliriz. Ancak, her sekilin alan hesabı için farklı işlemler yapılmakta. Kare’nin kenarları çarpılır, üçgenin yüksekliği ile tabanı çarpılıp ikiye bölünür. Ancak alan hesaplaması bunların ortak özelliğidir. Ya da az sonra yapacağımız örneği düşünürsek, kapıları açabilmemiz veya envanter itemlerini toplayabilmemiz bunlarla etkileşime girebileceğimiz manasında geliyor. Yani etkileşim kurulabilirler, ancak kurulan etkileşimin içeriği farklı olacaktır. 

Kavramsal olarak temel şeylerin oturduğunu düşünüyorum. Şimdi basit bir örnek ile bu kavramları pekiştirmek istiyorum. Görselde göreceğiniz gibi, nesnelere tıklandıkça etkileşime girebildiğimiz ve her nesnede farklı tepkiler alabildiğimiz bir yapı oluşturacağız. Bunun için bir adet ITiklanabilir adlı Interface bir tane de EnvanterItemi adlı abstract class oluşturacağız.Arayüz isminin başına I harfini ekleme sebebim Interface kelimesinin ilk harfi olmasından dolayı. Bu sayede dosyalarınız ya da miras aldığınz şeylerin bir arayüz olduğunu ayırt edebilirsiniz. Genel olarak bu kullanıma alışmanız faydanıza olacaktır.

Unity Abstract Class ve Interface Örneği

Abstract Class ve Interface Kavramları Örneği
Abstract Class ve Interface Kavramları Örneği

Yapacağım örnek için, boş bir GameObject oluşturup buna animator ekledim. Ardından alt obje olarak 2 tane küpten bir adet kapı oluşturdum ve bu küpleri animasyon penceresi üzerinden düzenleyip ile açılıp kapanma animasyonları yarattım. 4 adet animasyon var, açılırken, kapanırken, açılmış hali sabitken ve kapalı hali sabitken. Animator kısmında da bir adet “Acik” isimli bir adet bool değişken oluşturdum ve 4 animasyonu buna göre aralarında geçiş yapacak şekilde ayarladım. Şu an asıl odağımız animasyon ve animator olmadığı için, onları başka bir yazıya bırakıyorum.

Öncelikle ITiklanabilir isimli dosyamızı oluşturalım. İçerisinde tıkladığımız şeyin ismi olsun ve bir de “Etkilesim” isimli bir fonksiyon tanımlaması olsun istiyorum. İsim değişkeni sayesinde hangi nesneye tıkladığımız bilgisini de elde edebiliriz.

public interface ITiklanabilir {
    //isim değişkenini elde edebilmek için bir özellik tanımlıyoruz.
    string Isim {
        get;
        set;
    }
    //etkileşim için bir fonksiyon tanımlıyoruz
    //komutları miras alan sınıflarda yazacağız.
    void Etkilesim ();
}

Daha sonrasında da temel sınıf olarak kullanacağımız EnvanterItemi isimli abstract sınıfı oluşturacağız. Bunun içerisinde şu anlık sadece agirlik isimli bir değişken ve  EnvantereEkle isimli bir fonksiyon oluşturacağız. Örneğin basitliği adına gerçekten bir envantere eklemek yerine objeyi yok edeceğiz.

public abstract class EnvanterItemi : MonoBehaviour {
    public float agirlik;
    public virtual void EnvantereEkle () {
        Destroy (gameObject);
    }
}

Artık objelerimizi temsil edecek sınıfları oluşturabiliriz. Şimdi sırasıyla Kapi, Meyve, Ekipman isimli sınıfları oluşturacağım. Detaylar için yorum satırlarını inceleyebilirsiniz.

public class Kapi : MonoBehaviour, ITiklanabilir {

    [SerializeField]
    string isim;
    public string Isim {
        get =>
            isim;
        set =>
            isim = value;
    }

    Animator animator;
    //ilk olarak kapalı halde tanımlıyoruz
    bool acikMi = false;

    void Start () {
        //animator bileşenine erişiyoruz
        animator = GetComponent<Animator> ();
    }

    public void Etkilesim () {
        //! işareti kullanarak var olan değerinin tersini, yani
        //true ise false, false ise true değerini almasını sağlıyoruz.
        acikMi = !acikMi;
        //kapı animasyonunu oynatmak için animatordeki
        //bool değerini değiştiriyoruz.
        animator.SetBool ("Acik", acikMi);
        Debug.Log (Isim + " adlı kapı açıldı");
    }
}
public class Meyve : EnvanterItemi, ITiklanabilir {
    [SerializeField]
    string meyveIsmi = "Pippin'in Kafasına Çarpan Elma";

    public string Isim {
        get =>
            meyveIsmi;
        set =>
            meyveIsmi = value;
    }

    public void Etkilesim () {
        Debug.Log (Isim + " adlı obje ile etkileşime girildi");
        EnvantereEkle ();
    }

    public override void EnvantereEkle () {
        //örnek olması amacıyla bu sefer base komutu kullamayacağım
        // bu yüzden objemiz yok olmayacak

        Debug.Log (Isim + " adlı meyve envantere eklendi");
    }
}

Son olarak, tıklama kontrolü için “EtkilesimKontrol” isimli bir sınıf oluşturalım. Yorum satırlarında detaylarını bulabilirsini ama basitçe, farenin ekrandaki pozisyonunu kullanarak bir ray atıp herhangi bir objeye erişebiliyor muyuz bunu kontrol ediyoruz. Kodu oluşturduktan sonra kameraya atamayı unutmayın.

public class EtkilesimKontrol : MonoBehaviour {

    Camera kamera;

    void Start () {
        kamera = GetComponent<Camera> ();
    }
    void Update () {
        //eğer fare ile sol tık yapıldıysa
        if (Input.GetMouseButtonDown (0)) {
            //ScreenPointToRay fonksiyonu sayesinde
            //verdiğimiz ekran konumunu kullanarak
            //3 boyutlu sahnemiz içerisinde bir ray elde edebiliyoruz.
            //
            Ray etkilesimIsini = kamera.ScreenPointToRay (Input.mousePosition);

            RaycastHit etkilesimBilgisi;
            //Raycast fonksiyonu içerisine parametre olarak kullanmak istediğimiz ışını
            //ve bu raycast işlemi sonrasında sonucu kaydetmesi için
            //etkilesimBilgisi adlı değişkeni veriyoruz
            if (Physics.Raycast (etkilesimIsini, out etkilesimBilgisi)) {
                //eğer attığımız ışın bir objeye temas ettiyse
                //temas edilen objenin ITiklanabilir isimli bileşenine 
                //erişmeye çalışıyoruz.
                ITiklanabilir tiklananObje = etkilesimBilgisi.collider.GetComponentInParent<ITiklanabilir> ();

               //Eğer ITiklanabilir bileşenine sahip ise etkileşim fonksiyonun çağırıyoruz.
                if (tiklananObje != null) {
                    tiklananObje.Etkilesim ();
                }
            }
        }
    }
}

Böylece artık yazının önceki kısımlarında gördüğünüz gibi tıklamayla etkileşimleri gerçekleştirmiş olduk. Şayet hiçbir etki alamıyorsanız, objelerinizde Collider bileşeninin olduğundan emin olun. Raycast işleminin başarıyla çalışması için etkileşime girmek istediğiniz objelerde Collider olması gerekiyor. Ayrıca, scriptleri objelere atamayı unutmadığınızdan emin olun. Ufak şeyler gözden daha kolay kaçıyor.

Unity Abstract Class ve Interface Kavramları konusu da temel olarak tamamlanmış oldu. Elbette ki yapılabilecek bir sürü yapı, öğrenilecek bir sürü şey var. Umuyorum ki, basit ve doğru bir şekilde Unity üzerinden Abstract Class ve Interface kavramlarını size aktarabilmişimdir. Kullandığımı 3d modellerin linklerini yazının devamına ekliyorum. Bir dahaki yazımızda görüşmek dileğiyle.

Kullandığım Assetler:

Unity Patlamalı Rollerball

Merhaba dostlar, bu yazımızda daha önce youtube kanalımızda çektiğimiz Unity Patlamalı Rollerball adlı Rigidbody örneğini biraz daha güncelleyerek, nasıl oluşturacağınızı adım adım anlatacağız. Aşağıdaki görselde projenin nasıl gözükeceğini görebilirsiniz.

Unity Patlamalı Rollerball Oynanış
Unity Patlamalı Rollerball Oynanış

Şimdi gelelim hazırlıklara. Öncelikle boş bir proje açabilirsiniz veya varolan bir proje üzerinden devam edebilirsiniz, tercih sizin. Daha sonrasında ilk olarak yapacağımız iş, görselliği biraz arttırmak adına 2 paket yüklemek. İlki Unity Particle Pack, bu paket içerisinde çeşitli particle sistem prefablarını hazır halde kullanmamızı sağlıyor. Ufak bir uyarı, eğer hali hazırda farklı ayarlamalara sahip bir projenize ekleyecekseniz, import ederken “Projects Settings” adlı klasördeki tiki kaldırın. Ayrıca tamamını projeye eklemenize de gerek yok, ancak tamamını indirip incelemenizi öneririm.. Diğer paket ise Grid Box Prototype Materials, bu paket içerisinde daha çok prototip aşamasında kullanabileceğimiz bazı materyaller bulunduruyor. Genel proje başlangıçları için de kullanmanızı önereceğim bir paket.

Patlamalı RollerBall Sahne Tasarımı

Sahne tasarımı için yapacaklarımız aslında gayet basit olacak. Yazının öncesi görebileceğiniz gibi, birbirinden ayrı şekilde platformlar ve patlama efekti ile diğerine geçişi sağlamak için bu platformlar üzerinde kapsüller bulunuyor. Zemin olarak “Cube” objeleri kullanıp daha inceltenizi öneririm. Daha sonrasında indirdiğimiz materyal paketindeki materyalleri kullanarak istediğiniz gibi renklendirebilirsiniz. Ben zemin için mavi, zıplama kapsülleri için de kırmızı ve bitiş alanı için yeşil renkli kullandım. Kabaca hazırladığım sahneyi göstermek isterim, size de bir yol oluşturur. Bu arada dikkat etmeniz gereken şey, sahnemizin Z ekseninde ilerleyeceği.

Unity Patlamalı Rollerball Sahne Tasarımı
Unity Patlamalı Rollerball Sahne Tasarımı

Unutmadan, kapsüllerin Collider bileşenini isTrigger aktif halde ayarlanız gerekiyor. Karakterimiz hareket ederken bu nesnelerin fiziksel şeklinden etkilenmeyecek, onları sadece o alana girdiklerini anlamak için kullanacağız. Ayrıca kapsül objelerinin altobjesi olarak “Small Explosion” adlı prefab’ı eklememiz gerekiyor. Ve bu prefabı ekledikten sonra prefab ve altoblerini seçip hepsinde Inspector panelinde “Particle System” bileşeninin altında bulunan “Looping” ve “Play On Awake” adlı seçeneklerden tiki kaldırmamız gerek. Çünkü sadece patlama anında ve tek sefer çalışmasını istiyoruz. Eğer looping aktif olursa, tik atılmış halde olursa, particle system animasyonları sürekli çalışacaktır. Ve “Play On Awake” aktif olursa da oyun başlar başlamaz efekt çalışacaktır. Farklı efektleri kullanmak isterseniz de farklı prefabları kullanabilirsiniz. Ve son olarak, kapsülümüze “Ziplatici” adlı bir c# dosyası oluşturup ekliyoruz.

Platform kısmı tamam, şimdi yapmamız gereken şey karakterimizi eklemek. Basit bir küre (Sphere) işimizi görecektir. Bunu sahneye ekledikten sonra “Add Component” kısmından Rigidbody bileşenini ekledikten sonrası işlemlerimiz tamam. Hazır elinizi atmışken “KarakterKontrol” adlı bir script oluşturup onu da ekleyebilirsiniz, çünkü yazının devamında kodlama kısmına geçeceğiz.  Şayet bileşenleri nasıl ekleyeceğinizi bilmiyorsanız, “Unity GameObject Nedir?” adlı yazımızdan bileşen ekleme ve GameObject konusunda daha fazla bilgiyi elde edebilirsiniz.

Ve kamera ayarlarına gelirsek, kodlama kısmnda kameraya basit bir takip kodu ekleyeceğiz. Bu yüzden iyi konumlandırma yapıp oynanışta etrafı görmemizi olabildiğince mümkün kılmak gerekiyor. Ben karakterin baya bir üstüne ve hafif arka çaprazına alacağım. Ayrıca isterseniz “Camera“ bileşeni altında “Clear Flags” seçeneğini “Solid Background” yapıp, “Background” özelliğiyle bir renk atayabilirsiniz. Ardından da “BasitTakip” isimli bir c# dosyası oluşturup kamerama ekliyorum. Sahne tasarımı artık hazır, şimdi kodlamaya geçelim.

Unity Patlamalı RollerBall Kodlama Kısmı

Patlamalı RollerBall kodlama kısmı basit de olsa, daha organize şekilde çalışabileceğimiz şekilde düşünmemiz gereken bir konu. Bu oyun için bir sürü seviye hazırladığımızı düşünelim. Her seviyede platformlar birbirinden farklı uzaklıkta olacak, farklı yükseklikte olacaktır. Haliyle her ziplatici kapsülümüzün daha farklı kuvvet uygulayacak şekilde olması gerekir. Bu kadar basit bir konu olmasına rağmen scriptler arasında görev bölümünü iyi yapmamız gerekiyor. Şimdi adım adım ilerleyelim.

KarakterKontrol : Karakter kontrol kodumuzun temel işlevi kullanıcıdan kontrol almamız ve karakteri hareket ettirmemiz olacak. Ayrıca zıplatıcı kapsül objelerinin Rigidbody bileşenine rahatlıkla erişebilmesi için public halde bir property-özellik barındırmalı.

    Rigidbody rgb;
    //dışarıdan erişim için gerekli alan-özellik
    public Rigidbody KarakterRgb {
        get {
            return rgb;
        }
    }
    //kullanıcının kontrolünde kullanacağımız hız değişkeni
    [SerializeField]
    float hiz = 7f;
    void Start () {
        //başlangıça Rigidbody bileşenine erişiyoruz
        rgb = GetComponent<Rigidbody> ();
    }
    void Update () {
        //Horizontal(A-D tuşları) ve Vertical(W-S tuşları) ile
        //kullanıcıdan komutlar alıyoruz. Bu değerler -1 veya 1 olabiliyor
        float h = Input.GetAxis ("Horizontal");
        float v = Input.GetAxis ("Vertical");
        //eğer herhangi bir şekilde kullanıcı bize değer gönderiyorsa
        //yani kontrol ettiğimiz axis değerlerinden ikisi de 0 değilse 
        //objeye kuvvet uyguluyoruz
        if (h != 0 || v != 0) {
            Vector3 hareket = new Vector3 (h, 0, v) * hiz;
            rgb.AddForce (hareket);
        }
    }

Ziplatici :Zıplatıcı kodumuzda yapacağımız 2 şey var, karakterimizin bu obje ile teması bittiği anda karakterimizi Rigidbody bileşeni aracılığıyla kuvvet uygulayarak zıplatmak ve patlama görselini aktif hale getirmek. Ayrıca daha önce bahsettiğimiz gibi, her zıplatıcının farklı kuvvetler uygulamasını sağlamamız gerekiyor.

    //kod üzerinde atama yapmadığımız için 0 değerine sahip olacaktır
    //her kapsülden zıplamak istediğiniz platforma göre bu değerleri ayarlamanız gerekir
    //ziplamaCarpani ne kadar büyük kuvvet uygulanacağı
    //ziplamaYuksekligi de yukarı doğru ekstra uygulanacak kuvvet çarpanını belirtiyor
    [SerializeField]
    float ziplamaCarpani, ziplamaYuksekligi;
    ParticleSystem efekt;
    void Start () {
        //AltObjedeki ParticleSystem bileşenine erişiyoruz
        efekt = GetComponentInChildren<ParticleSystem> ();
    }
    //Obje ile diğer diğer objenin çakışması-içiçe geçmesi bittiği anda çalışacak
    void OnTriggerExit (Collider digerObje) {
        //diğer objenin içerisinde KarakterKontrol bileşenine erişmeye çalışıyoruz
        KarakterKontrol karakter = digerObje.GetComponent<KarakterKontrol> ();
        //eğer diğer objeden KarakterKontrol isimli bileşene erişebilirsek 
        //karaktere kuvvet uygulayıp, efekti aktif hale getiriyoruz
        if (karakter != null) {
            karakter.KarakterRgb.AddExplosionForce (ziplamaCarpani, transform.position, 3, ziplamaYuksekligi, ForceMode.Impulse);
            efekt.Play ();
        }
    }

BasitTakip : Bu kodun tek amacı karakteri belirli bir mesafeden takip etmek ve karaktere bakmak. Gayet basit ve işimizi görecek bir kod olacak.

     //takip edeceğimiz obje, inspector üzerinden atamayı unutmayın
    [SerializeField]
    Transform karakter;
    //aradaki mesafe için kullanacağımız değişken
    Vector3 mesafe;
    void Start () {
        //başlangıçta kamerayı nasıl konumlandırdıysak
        //o şekilde devam etmesi için başlangıçta 
        //aralarındaki farkı alıp mesafe değişkeninde tutuyoruz.
        mesafe = transform.position - karakter.position;
    }
    void Update () {
        //aradaki mesafe ile karakterin pozisyonunu topladığımızda 
        //başlangıçta ayarladığımız mesafeyi korumuş olacağız
        transform.position = karakter.position + mesafe;
        //transform.LookAt bir objenin diğerine doğru bakması
        //için kullandığımız bir fonksiyon. Karaktere bakmasını sağlıyoruz
        transform.LookAt (karakter);
    }

Böylece basit şekilde Unity3d – Patlamalı Rollerball örneğimizi tamamlamış olduk. Umarım temel konuları ve az çok görev bölümünü doğru yaparak kodlamaya dair kafanızda bir şeyler oturmuştur. Eğer Rigidbody hakkında daha fazla şey öğrenmek isterseniz Unity – Rigidbody Nedir ? adlı yazımıza göz atabilirsiniz. Yeni yazılarda görüşmek dileğiyle.

Unity 2019 LTS sürümü yayınlandı

0

Unity 2019 LTS sürümü 9 Haziran 2020 itibariyle yayınlandı. Takip edenlerin bildiği gibi, LTS açılımı Long-Term Support, her yıl içerisinde son kararlı sürüm olan ve  uzun süreli destek verilecek olan sürüm. Şu an itibariyle 2021 yılının ortasına kadar her 2 haftada 1 olacak şekilde bu sürüm için güncellemeler gelecek. Bu tarihten sonrasında ise 2022 Mayıs ayına kadar aylık güncellemelere yayınlanacak. Yayınlanacak bu güncellemeler yeni özellikler eklemeyecek, sadece kullanıcıların karşılaştığı sorunların çözümünü sağlayacak.

Bundan önceki LTS sürümü olan 2018.4 sürümü için destek ise 2021 bahar ayına kadar bahsettiğimiz düzeltme, hata çözme sürümlerine aylık olarak güncelleme almaya devam edecek.

Unity 2019 LTS Sürümü Yenilikler

Yenilikler konusunda Unity 2019 LTS Sürümü aslında önceki 3 sürümün üzerine yeni bir özellik eklemedi, ancak varolan hatalar giderilip daha stabil bir hale getirildi. Genel olarak 2019 sürümü ile gelen yeniliklere göz atacak olursak.

2D Tools :Geliştirilip güncellenen 2 boyutlu editor araçları sayesinde artık 2D oyunlarınız çok daha gerçekçi ve çok daha kolay istediğiniz görüntüyü elde edeceğiniz hale geliyor.

  • 2D Animation: Artık sprite objelerimiz ve karakterlerimizi de aynı 3 boyutlu modellerde olduğu gibi rigleyebiliyoruz. Bu sayede animasyon paneli altında karakterlerimiz için animasyon oluşturup projelerimizde kullanabiliriz.
  • 2D Lights : Evet, 2 boyutlu ışıklar geldi sonunda. Normalde kullandığımız ışık kaynakları ile sprite nesnelerimizin ışıktan etkilenmesini sağlayamıyorduk. Yalnızca gölge oluşturmak da değil kastettiğimiz. 2 boyuta özel şekilde düşünülmüş ışıklarımız var artık.
  • 2D Shader Graph : Aslında bu özellik shader graph yapısından tamamen bağımsız değil. Artık Shader Graph içerisinde de iki boyutlu sprite nesnelerimiz için shader oluşturabiliyoruz. Hatta bunun için bir ders videomuz bile bulunuyor : 2D Shader Graph Dersimiz
  • Tilemaps : Zemin veya duvar için oluşturduğunuz sprite dosyalarını tekrar tekrar sahnede çoğaltıp, hizalı mı değil mi diye kontrol ettirmek çok büyük vakit kaybı değil mi ? Şayet haberiniz yoksa, Unity Tilemaps paketi ile bu olaya bir çözüm getirdi sonunda. Editor ekranındayken bir grid yapısı kullanarak sahnemizi tasarlayabiliyoruz artık. Tıkladığımız kutucuk o an seçili olan sprite dosyamızın resmi ile doluyor. Tilemap ve Tile Palette dersimizi izleyerek fikir edinebilirsiniz.
  • Sprite Shape : Bu paket de aslında Tilemaps gibi sahne düzenlememizde çok çok işimizi kolaylaştıran bir paket. Ancak her zaman dümdüz halde, grid yapısı şeklinde bir çevre oluşturmak zorunda değiliz. Sprite Shape özellikle zemin, yükselti, girinti çıkıntı gibi doğal şartlarda bulunabilen yapılar üretmekte işimizi baya kolaylaştıran bir özellik.
  • Sprite Tools : Daha önce de sprite dosyalarımız için temel değişiklikler yapabildiğimiz araçlar artık daha gelişmiş halde. Özellikle 2D Lights özelliği ile kullanabileceğimiz normal map olarak kullanabileceğimi Secondary Textures özelliği de bu yeni özelliklerden biri.

Addressables: Addressables aslında oyun dosyalarımıza erişip kullanmak için bize büyük kolaylıklar sağlayan bir yapı. Örneğin bir materyalde kullandığınız texture dosyasını değiştirmek güncellemek istiyorsunuz, bunun için tekrar build almanıza bile gerek kalmıyor. Addressables sayesinde yayınladığınız programın kullanacağı dosyalar bir nevi güncelleniyor ve daha önce verdiğiniz adresi baz alarak dosyaları çağırdığı için, o adresteki dosya değiştirildiğinde kolaylıkla dosyayı kullanması gerektiğini biliyor.

UI Builder : Sonunda, o kötü kötü elle arayüz ayarlamalardan kurtuluyoruz diyebiliriz. En azından sanıyorum. Yeni getirilen bu paket sayesinde artık oyunlarımız için arayüz hazırlamak çok çok kolay hale geliyor bence. Şayet web geliştirme ile uğraştıysanız, artık css üzerinde olduğu gibi, arayüz elementlerimize sınıf ve id yapısı ile görsel özellikler atayabileceğiz. Aslında önceden UIElements adı altında benzer bir yapı vardı ancak burada gelen sürükle-bırak yapısı ile çok daha basit ve kullanışlı hale geldi diyebiliriz.

Unity As A Library : Bu özellik çok ilgi çekici bir özellik. Düşünün ki android veya ios için bir yazılım geliştiriyorsunuz, ama “keşke Unity’de yapabildiğim x şeyi burada da yapabilsem“ dediğiniz anlar oluyor. İşte tam olarak bu sorununuzu çözmeye yarayacak bir sistem bu. Unity projenizi bir kütüphane olarak XCode veya Android Studio üzerine ekleyip, native olarak yazdığınız projenize dahil etme şansınız var. Yalnızca Android veya Ios için değil, Windows için de bu özellikten yararlanabiliyorsunuz.

Yeni Unity sürümlerini ve yepyeni özelliklerini anlatacağımız gelecek yazılarda da görüşmek dileğiyle. Unity 2019 LTS sürümü yayınlandı gibi Unity ve oyun geliştirme hakkında haberleri, yeni bilgileri ve dersleri kaçırmamak için bizi takip etmeyi unutmayın.

Unity Learn Premium Artık Ücretsiz!

0

Pandemi dönemi hepimiz için sıkıntılı geçiyor biliyorum. İnsanların eve kapanmasıyla beraber evde yapacak, öğrenecek çok şey olduğunu tekrar hatırladık. Unity gibi bazı kurumlar da bu süreçte ücretli içerikleri kısa süreliğine de olsa herkese açık hale getirme kararı almıştı. İlk olarak 19 Mart 2020’de 3 aylık süreyle açılmıştı ancak 23 Haziran tarihinden itibaren Unity Learn Premium Artık Ücretsiz!

Bunun şerefine, özellikle tam olarak hangi kursları izlesem diye emin olamayan kişiler 

için 3 adet kurs seçtik. Bu 3 kursu seçerken de olabildiğince farklı konulardan olmasına dikkat ettik. Umarım kurslara göz atar ve siz de bunlardan yararlanmaya başlarsınız. Bu sistemin kullanılmaya devam edilmesi, geliştirilmesi için de teşvik edici olacaktır.

Unity C# Survival Guide

Unity C# Survival Guide kursu, özellikle C# başlangıç düzeyinde olan ve yeni başlayacaklar için içerik konusunda fazlasıyla dolu bir kurs diyebiliriz. Yaklaşık 22 saatlik içeriğe sahip olan bu kursta değişkenler, döngüler gibi basit konulardan başlanıp LINQ, Singletons ve Command pattern gibi daha ileri seviye konulara adım adım ilerleniyor. Eğer hiçbir C# temeline sahip değilseniz, basit bir örnek oluşturarak değişkenler ve fonksiyonlardan bahsettiğim “Unity C# Temel Dersi ve Fizik ile Basit Hareket” yazıma göz atabilirsiniz.

High Fidelity Game Visuals

High Fidelity Game Visuals özellikle görsel konularda kendini geliştirmek isteyenler için, orta seviye diyebileceğimiz bir kurs. Karakter, çevre tasarımı bu kurs ağırlıklı olarak modelleme üzerine olduğunu söyleyebiliriz. Eğer özellikle bir oyun projesinde modellemeci, 3D sanatçı olarak çalışmak gibi bir hedefiniz varsa bu kursun size faydası olacaktır.

Artificial Intelligence for Beginners

Artificial Intelligence for Beginners yapay zeka üzerine bir başlangıç kursu. Bu kurs içerisinde yapay zeka için gerekli matematik ve fizik konularından başlayıp hedef bazlı hareket gibi yapay zeka oluşturup eğitmek için gerekli konuları değiniyor. Yapay zeka konusu günümüzde çoğu sektöre kendine yer bulan bir alan. Haliyle oyunlarda da artık bunu görebiliyoruz. El ile kodlanmış standart hareketleri takip eden objeler yerine eğitilip daha doğal hareketler sergileyecek düşmanlarınızın oyunda olması projenize katkıda bulunacaktır.

Türkçe içeriklere sahip olmasa da Unity Learn Premium Artık Ücretsiz! haberi insanın içerisinde bir heyecan yaratıyor. Kendi belirledikleri eğitmenler aracılığıyla oluşturdukları bu kursların kesinlikle işinize yarayacağına eminim. Siteyi inceleyip kurslara göz atmayı ihmal etmeyin. Yeni yazılarda görüşmek dileğiyle, kendinize iyi bakın.

Unity Collider Nedir?

Selamlar dostlar, bu yazımızda Unity Collider Nedir ? sorusunu olabildiğince genel kapsamlı şekilde cevaplayacağız. Collider, en temeliyle Unity oyun motoru içerisinde kullandığımız objelerin (GameObject) birbirinin içerisinden geçmesini önleyen veya birbiri içinden geçip geçmediğini algılamamızı sağlayan, fizik motoruyla beraber kullandığımız bir yapıdır.. Collider bileşenlerini nesneleri bir katılık, bir çerçeve kazandıran bileşen olarak da değerlendirebiliriz.

Bahsettiğimiz şekilde, objelerin birbirine temasını engellemek için öncelikle belirli bir harekete sahip olmaları gerekiyor. Objeleri Transform bileşeniyle de hareket ettirebiliriz ancak fizik motoru kullanmadığımız için bu temasları ve birbirinin içinden geçmelerini algılayamayız. Bu işlemleri yapmak için hareket ettirmek istediğimiz objelerimizi fizik sistemine dahil etmeli, yani bu objelere Rigidbody bileşeni eklemeliyiz. Objemizi seçtikten sonra Inspector panelinde bulunan “Add Component” butonuna tıkladığımızda arama kısmına “Collider” yazarak ekleyebileceğimiz çeşitli bileşenleri görebiliriz. Bu noktada dikkat etmeniz gereken 3 boyutlu olanları seçmek, bu derste 3 boyutlu bileşenlerden bahsedeceğiz. Objelere bileşen ekleme ve daha fazla bilgi için “Unity GameObject Nedir?” yazımızı inceleyebilirsiniz. Hareket etmeyen objelerimizde collider bileşeni olması yeterli olacaktır.

Collider Türleri

Biraz da Collider türleri hakkında bahsetmek istiyorum. Genel olarak fizik işlemler için kullanabileceğimiz bu iskelet yapısı performans kaygısı nedeniyle fazlasıyla basit halde tutulmaktadır. Unity bize 3 adet temel şekle sahip collider türü sağlamaktadır, bunlar küre, küp ve kapsül şekillerindedir. Ayrıca istersek yüklediğimiz 3 boyutlu modelimizin şeklini de kullanabiliriz ancak bunu da biraz daha kaba hale getirmemiz gerekmekte çoğu durumda. 

Bu collider türleri hakkında detaylı bilgi vermeden önce şunu belirteyim, bu aşamada sadece bu türlere özel konulardan bahsedeceğim. Daha sonrasında da hepsinde ortak olarak kullanabildiğimiz kodlardan ve özelliklerden bahsedeceğim. Hazırsanız kullanabileceğim 4 türe geçelim ve onlara özel yapılardan bahsedelim.

Box Collider : Bu bileşen küp şeklinde bir çerçeve oluşturarak temas işlemlerini algılamamıza yardımcı olur. Unity içerisinde bir küp eklediğinizde bu bileşene sahip olduğunu görebilirsiniz. Center ve Size adında 2 değişkene sahiptir. Center değişkeni objenin local koordinat sistemine göre bu kübün merkezini belirtirken, Size değişkeni x,y ve z eksenlerindeki boyutunu ayarlamamızı sağlayan değişkendir.

Sphere Collider : Küre şeklinde olan bu tür 2 adet değişkene sahiptir. Sahneye bir Sphere objesi eklediğimizde temel olarak bu bileşene sahip olacaktır. Yine Center değişkeni ile objenin local sistemindeki konumunu ayarlarız. Radius değişkeni ise kürenin yarıçapını belirtmektedir, boyutunu bu değişkeni değiştirerek ayarlayabiliriz.

Capsule Collider : Kapsül şeklinde bir çerçeve elde ettiğimiz bir bileşendir, standart örneklerde gördüğümüz gibi FPS kontrollerde için eklediğimiz Capsule objesinin içerisinde bulunur. 4 adet değişkeni bulunur, bunlar; Center, Direction, Height, Radius değişkenleridir. Sırayla bahsedersek, Center bu bileşenin merkezinin obje koordinatlarına göre alacağı konumu belirtir. Direction değişkeni x, y veya z ekseni olarak seçebileceğimiz, collider yönünü belirten değişkendir. Height yükseklik değer, radius ise genişlik değerini belirtmektedir.

Mesh Collider : 3 boyutlu objelerimizin şeklini collider olarak belirtmemizi sağlayan yapılardır. 3 adet değişkene sahiptir. Convex değişkeni verilen meshi kullanarak oluşturduğumuz colllider yapısının daha basit, kaba hale indirgenip indirgenmeyeceğini belirtir. Cooking Options ile mesh objemizin fizik işlemlerine uyarlanması sırasında yapılacak işlemler için seçilebilecek ayarlardır. Ve son olarak Shared Mesh ise kullanacağımız 3 boyutlu model dosyasını belirttiğimiz değişkendir.

Unity Collider İle Kullanılabilecek Kodlar

Unity Collider Nedir? sorusunun cevabına kullabileceğiimiz kodlar ile devam etmek istiyorum. Unity Collider ile Kullanılabilecek Kodlar 3 ayrı başlıkta ayrılıyor. Bunlar özellikler/değişkenler, public metodlar, ve mesajlardır (temaslardan haberdar olmak için çağırılan kodlar). Bu başlıklar altında hepsini sırayla inceleyelim.

Özellikler – Erişilebilir Değişkenler

attachedRigidbody : Bu değişken sayesinde direkt olarak collider bileşenin bulunduğu objenin rigidbody bileşenine erişebiliriz.

    void Start()
    {
        // Rigidbody bileşenini bulup z ekseninde 5 birimlik kuvvet uygular
        GetComponent<Collider>().attachedRigidbody.AddForce(0, 0, 5);
    }

bounds: Bounds tipinde olan döndüren bu değişken sayesinde collider merkezini, genişliği, yüksekliği gibi verilere ulaşabiliriz. Dikkat etmeniz gereken konu, bounds objenin içerisine sığabileceği bir kutuyu temsil eder diyebiliriz.

    void Start()
    {
        // Collider büyüklüğünü log ekranına yazdırır
        float size= GetComponent<Collider>().bounds.size;
	Debug.Log(“Obje Boyutu= ” + size);
    }

contactOffset : Temas işlemleri hesaplanırken collider yüzeyinden ne kadar uzakta hesaplanacağını belirlediğimiz, bir nevi ekstra bir boşluk kattığmız değişkendir. Bu sayede görsel olarak objeler birbirine değmese bile bir temas varmış gibi işlem yapılabilir.

enabled : Collider bileşeninin aktif olup olmayacağını belirttiğimiz değişken. Eğer deaktif hale getirirsek, obje diğer objelerle temas durumunda bir işlem yapmayacak, haberdar olamayacaktır.

    Collider col;

    void Start()
    {
        //Collider bileşeni ataması yapar
        col= GetComponent<Collider>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //Space tuşuna her bastığımızda aktifliği tersine çevirir
	//örneğin aktif ise deaktif, deaktif ise aktif hale gelir
            col.enabled = !col.enabled;
        }
    }

isTrigger : En önemli özelliklerden biri isTrigger özelliğidir. Bu özelliği aktif hale getirdiğimiz, true değeri atadığımız taktirde objelerimiz artık içinden geçilebilir halde olacaktır. Aynı zamanda bu birbirinin içinden geçme durumlarından da bizi haberdar edecektir. Temas durumlarına dair fonksiyonlara yazının devamında detaylı şekilde ulaşabilirsiniz.

material : Collider’ın sahip olduğu fizik materyaline rerişmemizi sağlayan fonksiyondur. Bu sayede sürtünme, geri tepme gibi özelilklerin atamasını yapabiliriz. Eğer birden fazla objenin kullandığı bir materyale sahipse, çalışma anında materyalin bir kopyasını yaratır ve objeye bu kopya materyali atar.

    Collider col;
	// Fizik materyaline erişip dinamik sürtünme ve zıplama etkilerine değerler atar.
    void Start()
    {
        coll = GetComponent<Collider>();
        col.material.dynamicFriction = 2f;
        col.material.bounciness = .5f;
    }

sharedMaterial : Aynı material özelliğinde olduğu gibi collider’ın kullandığı materyali alır. Ancak bu komut sayesinde yaptığınız her işlem aynı materyale sahip diğer objeleri de etkileyecektir. Eğer değişikliği tek bir objede yapmak istiyorsanız sharedMaterial yerine material kullanmanız gerekir.

Public Metodlar

ClosestPoint : Verilen konuma en yakın olan obje noktasını verir. 

ClosestPointOnBounds: Collider’ın Bounds adlı değişkenini baz alarak, belirtilen konuma en yakın noktayı döndürür.

Raycast: Sadece bu objeyle etkileşime geçecek bir ışın yaratır. Bu sayede, sadece attığınız ışının ile objenizin arasında başka objeler bulunsa da, sadece bu objeyle temas gireceğinden dolayı, filtreleme işlemlerine ihtiyaç duymadan bir ışın oluşturmanız mümkündür. Aşağıdaki basit örnekte, objenin üzerine tıkladığınızda, objeyi kendi üstünde tıkladığınız konuma getirmeyi sağlayan yapıyı görebilirsiniz.

    Collider col;
    void Start()
    {
        col= GetComponent<Collider>();
    }

    void Update()
    {
        // Objeyi mouse ile ekranda tıkladığınız konuma götürür
        if (Input.GetMouseButtonDown(0))
        {
            Ray isin= Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit temas;

            if (col.Raycast(isin, out temas, 100.0f))
            {
                transform.position = temas.point;
            }
        }
    }

Mesajlar

Mesajlar kısmını aslında 2 farklı tipte toplam 6 metod içeriyor. Temas etme ve içerisinden geçme/üstüste binme işlemleri için. Daha toplu halde olması adını önce bu şekilde ikiye ayırıp önce Temas ardından da birbirinin içinden geçmeye dair işlemleri anlatıp örnek kodlarını toplu yazacağım.

OnCollisionEnter : Objenin başka bir objeye temas ettiği an yollanan mesaj sayesinde çalışan bir fonksiyondur. 

OnCollisionExit : Objenin teması bıraktığı, diğer objeden ayrıldığı an çağırılan fonksiyondur.

OnCollisionStay : Temas etme işlemi gerçekleştiği sürece aynı update gibi tekrar tekrar çalışan fonksiyondur. 

Önemli bir hatırlatma, bu fonksiyonların çalışabilmesi için temas edecek iki objenin de isTrigger değeri false olmalı. Eğer bir tanesi bile true değerine sahip olursa, yani trigger halde olursa yazının devamındaki OnTrigger şeklindeki fonksiyonlar çağırılacaktır.

//Örneklerde temel olarak yaptığımız şey aynı,
// temas gerçekleştirdiğimiz objenin adını alıp log ekranına yazdırıyoruz. 3 farklı durum için bunu gerçekleştiriyoruz böylece. 
 
void OnCollisionEnter(Collision temas)
    {
        Debug.Log(“Temasa başlanan obje: “+temas.transform.name”);
    }
void OnCollisionExit(Collision temas)
    {
        Debug.Log("Temas etme biten obje " + temas.transform.name);
    }

 void OnCollisionStay(Collision temas)
    {
       Debug.Log(“Temas halinde olunun obje” + temas.transform.name”);
}

OnTriggerEnter :Obje başka bir objenin içinden geçmeye başladığı an çalışan fonksiyondur. 

OnTriggerExit : Objenin başka bir objenin içinden geçmeyi bıraktığı, üstüste binme işleminin bitti an çağırılan, aktif olan fonksiyondur.

OnTriggerStay : Obje bir başka objeyle üstüste bindiği sürece, içinden geçmeye devam ettiği sürece, update gibi, sürekli çağırılan fonksiyondur.

Önemli bir hatırlatma yapayım,Bu fonksiyonların çalışabilmesi için temas edecek iki objeden en az birinin collider isTrigger değeri true olmalı. Trigger halde olmamaları halinde az önce bahsettiğimiz OnCollision şeklindeki fonksiyonlar aktif olacak ve çağırılacaktır.

//bu örneklerin genelinde de objelerin temas anından, temas süresince ve temas bitiminde birbirinden ne kadar uzakta olduklarını log ekranına yazdırıyoruz
 void OnTriggerExit(Collider digerObje)
    {
	Debug.Log(“Başlangıçta Aradaki mesafe:”+(transform.position-digerObje.transform.position));
 }
void OnTriggerExit(Collider digerObje)
    {
	Debug.Log(“Temas ederken aradaki mesafe:”+(transform.position-digerObje.transform.position));
 }

void OnTriggerStay(Collider digerObje)
    {
	Debug.Log(“Temas bittiğinde aradaki mesafe:”+(transform.position-digerObje.transform.position));
 }

Kullanılabilen kodlardan da bahsettiğimize göre, Unity Collider Nedir? sorusunu cevaplamış olduk böylece. 3D dışında, 2D için de collider tipleri bulunuyor ancak onlar farklı bir yazının konusu. Benzerliklerinin yanında farklılıkları da baya bol emin olun. Türkçe olarak erişebilseniz de, orjinal Unity Collider dökümanına erişmek için buraya tıklayabilirsiniz.

Unity Transform Nedir?

Merhaba dostlar, bu yazımızda Unity Transform Nedir? sorusunu cevaplayacağız. Unity programı içerisinde Transform, içerisinde konum, rotasyon (kullandığı açı) ve boyut değerlerini bulunduran ve bu değerleri çeşitli şekillerde kontrol etmemizi sağlayan fonksiyonları bize sunan bir bileşendir. Bilmeniz gerekir ki, bir sahnede kullanacağımız her oyun objesi (GameObject) Transform bileşenine sahip olmak zorundadır. Bu bileşen olmadan, obje bir konuma sahip olamaz, haliyle sahne içerisinde varolamaz. GameObject hakkında daha fazla bilgi almak isterseniz, Unity GameObject Nedir? yazımıza göz atabilirsiniz.

Belirttiğimiz bu değerleri ister kod üzerinden, istersek de Unity arayüzü üzerinden ayarlamamız mümkün. Bu bilgiyi düşündüğümüzde, bileşenin aslında hem sahne tasarımlarımızda hem de oyun içerisinde kullandığımız bir bileşen olduğunu söyleyebiliriz. Kod ile bu değişkenleri değiştirmenin nasıl yapıldığını yazının devamında bulabilirsiniz. Editor üzerinde yapmanız gereken tek şey ise gerekli alanlardaki verileri elle yazarak değiştirmek ya da Transform aracını kullanarak sürükleyerek objenin değerlerini değiştirmek. Daha önceleri editor üzerinde kullanabileceğimiz araçlar konum, rotasyon ve açı için ayrı ayrıydı. Ancak Unity 2019 sürümünde gelen yeni bir araç bu değişkenleri bünyesinde tutuyor ve bu sayede araçlar arasında geçiş yapmadan istediğimiz özelliği değiştirebiliyoruz.

Unity Transform Nedir Editor Araçları
Unity Transform Nedir Editor Araçları

Konum, rotasyon ve boyut değişkenleri dışında, Transfrom bileşeni içerisinde bir ebeveyn-çocuk sistemi bulunur. Bu sistem sayesinde objeleri birbirinin alt objesi haline getirebilir ve beraber hareket etmelerini sağlayabiliriz. Ayrıca bu yapı sayesinde sahnemizi, hiyerarşi panelimizi daha derli toplu halde tutup, geliştirme aşamasında daha rahat şekilde çalışabiliriz. Basit bir örnek düşünürsek, çevre isimli bir, bunun alt objeleri olarak, binalar ve araçlar, ve bunların altında da direkt kullanacağımız objeleri alt obje olarak belirtmek işimizi baya kolaylaştıracaktır. Örnek resimde hiyerarşi panelinde gruplandırma yapılmamış ve gruplandırılmış hallerini görebilirsiniz.

Unity – Transform İle Kullanılabilecek Kodlar

Unity – Transform ile kullanılabilecek kodlar konusunda alt başlıklara geçmeden önce, genel kullanıma sahip, yazının devamındanki başlıklar altına yerleştirilemeyecek birkaç koddan bahsetmek istiyorum. Bu kodlar aynı zamanda gameObject gibi sınıflarda da kullanılabilir ancak burada yer vermenin daha uygun olduğunu düşünüyorum.

gameObject : Transform bileşeninin ait olduğu nesnenin kendisine erişmemizi sağlar.

tag : Oyun objesine atamış olduğumuz etiket değerini elde etmemizi sağlar. Ayrıca bu değişkene erişip değiştirebiliriz.

//Log ekranına objenin tagını yazdırır.
Debug.Log(transform.tag);

name : Oyun objesinin ismine erişmemizi ve değiştirebilmemizi sağlar. Aynı name değişkeni gibi tag değişkeni de her oyun objesinde bulunan özelliklerdendir. Objeler hakkında daha fazla bilgi edinmek isterseniz “Unity – GameObject Nedir ?” adlı yazımızı okumanızı öneririz.

//Log ekranına objenin adını yazdırır.
Debug.Log(transform.name); 

Özellikler – Erişilebilir Değişkenler

Şimdi gelelim Transform bileşenin sahip olduğu değişkenlere erişmek için kullanabildiğimiz kodlar konusuna. Bu değişkenler sayesinde konum, rotasyon, boyut özellikleri dışında, şayet varsa objenin ebeveyn objesine, alt objelerine de erişebiliriz.

childCount : Objenin sahip olduğu altobje sayısını elde etmemizi sağlar. Dikkat etmeniz gereken şey, bütün altobje sayısını değil, yalnızca bir alt seviyedeki objeleri alır. Aile olarak düşünürsek, bireyin yalnızca çocuk sayısını alırız, torunları bu hesaba dahil olmaz.

    //başlangıçta objenin adını ve sahip olduğu alt obje sayısını log ekranına yazdırır
    void Start () {
        Debug.Log (transform.name + " adlı obje" + transform.childCount + " adet alt objeye sahip");
    }

eulerAngles : Objenin rotasyon değerini elde etmemizi sağlar. İstersek bu değeri kod ile değiştirebiliriz. Ancak dikkat etmek gereken bir konu var ki, eulerAngles Vector3 cinsinden verileri gösterse de, arkaplanda rotasyon için veriler Quaternion formatında tutulur. eulerAngles ile aldığımız değer de arkaplanda Quaternion değişkeninden Vector3 değişkenine dönüştürülerek bize döndürülür. Önemli bir hatırlatma, eulerAngles değerini kullanırken eksen değerlerini tek tek girmemek önerilir. Yani eulerAngles.z=1 şeklinde atamalar yapmaktan kaçının.

    //aşağıdaki örnek ile obje x,y,z eksenlerinde tuşlara basılınca
    // basılan eksende dönüşe başlayacak veya duracaktır.
    float donusHizi = 45;
    Vector3 varolanAci;
    float x;
    float y;
    float z;

    void Update () {
        //tuşlara basıldıkça değerler 0 veya 1 değerleri alacak
        //başlangıçta otomatik olarak 0 değeri alacakları için belirtilen eksende dönüş olmayacaktır
        if (Input.GetKeyDown (KeyCode.X)) x = 1 - x;
        if (Input.GetKeyDown (KeyCode.Y)) y = 1 - y;
        if (Input.GetKeyDown (KeyCode.Z)) z = 1 - z;

        //varolanAci değişkenini verilen değer, geçen zaman ve dönüş hiziyle çarpılarak değiştiriliyor.
        varolanAci += new Vector3 (x, y, z) * Time.deltaTime * donusHizi;

        //yaptığımız değişikliği eulerAngles kullanarak objeye aktarıyoruz.
        transform.eulerAngles = varolanAci;
    }

forward : Objenin z ekseninin (editorde mavi renkli ok olarak gösterilen yön) Vector3 değerini Genel (World) koordinat sistemine göre uyarlayıp normalleştirerek, 1 birim uzunluğa sahip hale getirerek bize geri döndürür.

    float donusHizi = 45f;
    void Update () {
        //space tuşuna basılı tutulduğunda z ekseninde
        //verilen donuzHizi değerine göredöndürme işlemi yapar
        if (Input.GetKey (KeyCode.Space))
            transform.eulerAngles += transform.forward * Time.deltaTime * donusHizi;

        //w tuşuna basıldığında objenin z eksenine göre 1 birim ileri ışınlar
        // objenin açısını değiştirerek deneyebilirsiniz.
        if (Input.GetKeyDown (KeyCode.W))
            transform.position += transform.forward;
    }

hasChanged : Transform değerlerine bir atama işlemi yapılıp yapılmadığını kontrol etmemizi sağlar.

    //objeye yeni bir posizyon değeri atadığımızda 
    //hasChanged true değeri alır
    void Update () {
        if (transform.hasChanged) {
            Debug.Log ("Transform değeri değişti");
            transform.hasChanged = false;
        }
        if (Input.GetKeyDown (KeyCode.W)) {
            transform.position += transform.forward;
        }
    }

hierarchyCapacity : Normalde Unity, standart olarak belirli bir sayıda hiyerarşi kapasitesine sahiptir. Duruma göre gerektiğinde otomatik olarak bu sayıyı kendisi arttırır. Ancak büyük projelerde sistem kaynakları tüketimini azaltıp performansı arttırmak adına bu değer, kullanmak istediğiniz obje sayısından birazcık daha fazla olacak şekilde belirlenebilir. Int tipinde bir değişkendir.

hierarchyCount : Hiyerarşide objenin kaç adet altobjeye sahip olduğunu elde etmemizi sağlar. childCount’tan farklı olarak bütün altobjeleri alır.

    //objenin bütün altobjelerini toplam sayısını 
    //log ekranına yazdıracaktır
    void Start () {
        Debug.Log (transform.name + " adlı obje " + transform.hierarchyCount + " objeyi altında bulundurmaktadır");
    }

localEulerAngles : Objenin rotasyonun ebeveyn objesinin rotasyon değerini baz alacak şekilde Vector3 tipinde elde etmemizi sağlar. Aynı zamanda bu değişkene değer atama işlemi de gerçekleştirebiliriz. Genel koordinat sistemine göre veya kendi yapısına göre değil de, ebeveyn objesini baz alarak sağa sola döndürmek bu değişken için kullanabileceğimiz basit bir örnek olabilir. Eğer obje bir ebeveyne sahip değilse genel kooardinat sistemine göre rotasyon işlemlerini gerçekleştirir.

    float donusHizi = 45;
    //A ve D tuşlarına basıldığı sürece
    //Ebeveyne göre sağa veya sola dönüş sağlar
    void Update () {
        if (Input.GetKey (KeyCode.D))
            transform.localEulerAngles += Vector3.up * Time.deltaTime * donusHizi;
        if (Input.GetKey (KeyCode.A))
            transform.localEulerAngles += Vector3.down * Time.deltaTime * donusHizi;
    }

localPosition : Objenin ebeveyninin pozisyonunu baz olarak sahip olduğunu pozisyondur. Eğer obje bir ebeveyne sahip değilse position değişkeni ile aynı değere sahiptir.

    void Start () {
        //local ve genel pozisyonlarını log ekranına yazdırın
        //obje ve ebeveynin pozisyonlarını değiştirerek tekrar tekrar farkı gözlemleyin
        Debug.Log ("Local pozisyon:" + transform.localPosition);
        Debug.Log ("Sahne pozisyonu:" + transform.position);
    }

localRotation : Objenin rotasyon değerini ebeveyninin rotasyonunu baz alarak ve Quaternion cinsinde döndürür. Bu değere direkt atama yapmak pek önerilmez. Quaternion konusuna hakimseniz deneyebiliriz. Onun dışında yazının devamında bulabileceğini metodları kullanarak döndürme işlemi gerçekleştirebilirsiniz.

    //objenin rotasyonunu başlangıçta sıfırlar
    void Start () {
        transform.localRotation = Quaternion.identity;
    }

localScale : Objenin ebeveynini baz alarak boyutlarını tutan değişkendir. Ebeveyn boyutları da altobjeleri etkilemektedir. Bu değişkene atamalar yaparak obje boyutlarını değiştirebiliriz. Vector3 cinsinden değer alır.

    void Start () {
        //local ve genel boyutları arasındaki farkı gösterir
        //obje ve ebeveyn boyutlarıyla oynayarak aradaki farkı gözlemleyebilirsiniz
        Debug.Log ("Local pozisyon:" + transform.localScale);
        Debug.Log ("Sahne-Genel pozisyonu:" + transform.lossyScale);
    }

    void Update () {
        //space tuşuna basıldıkça her eksende boyutlarını 1 birim arttırır
        if (Input.GetKeyDown (KeyCode.Space))
            transform.localScale += Vector3.one;
    }

localToWorldMatrix : Matrix4x4 tipinde olan bir değişkendir. Objenin konum, rotasyon, boyut gibi özelliklerini tutan, local halinden Genel (World) yapısına çevirilmiş bir değer tutar. Sadece okunabilir haldedir, direkt değişken ataması yapılamaz. Matrix4x4 tipinde değişkenler daha ileri seviye yapılardır ve Unity içerisinde kodlama kısmında çok fazla kullanmamıza gerek kalmamaktadır. Bunun yerine public metodlar kısmında bahsettiğimiz TransformPoint metodunu kullanabilirsiniz.

lossyScale : Objenin genel (global) boyutlarının tutulduğu değişkendir. Değer ataması yapılamaz sadece okunabilir moddadır. Değer ataması yapmak için localScale değişkenini kullanabilirsiniz. 

parent : Objenin ebeveynine erişmemizi veya değiştirmemizi sağlayan değişkendir. 

    //editorde sürükle bırak yapabileceğimiz
    //bir obje alanı yaratır
    [SerializeField]
    GameObject yeniEbeveyn;

    void Start () {
        //eğer obje ebeveyne sahipse
        //ebevyn objenin ismini log ekranına yazdırır
        if (transform.parent != null)
            Debug.Log ("Ebeveyn objenin ismi: " + transform.parent.name);

        //Eğer yeniEbeveyn değişkeni atanmışsa, boş değilse
        //objenin ebeveynini yeniEbeveyn değişkeni olarak atar
        if (yeniEbeveyn != null) {
            transform.parent = yeniEbeveyn.transform;
            Debug.Log ("Yeni Ebeveyn objenin ismi: " + transform.parent.name);
        }
    }

position : Objenin genel koordinat sistemine göre konum değerini tutan ve değiştrmemizi sağlayan değişkendir.

    void Update () {
        //W tuşuna basıldığında -1, S tuşuna basıldığında 1 değerini ileri değişkenine atar
        //hiçbirine basılmazsa 0 değeri alır
        float ileri = Input.GetAxis ("Vertical");
        //A tuşuna basıldığında -1, D tuşuna basıldığında 1 değerini sag değişkenine atar
        //hiçbirine basılmazsa 0 değeri alır
        float sag = Input.GetAxis ("Horizontal");

        //kullanıcıdan alınan değişkenlerle bir vector3 değişkeni oluşturup
        //bu değişkeni position değişkenine ekleyerek hareket sağlanır.
        transform.position += new Vector3 (sag, 0, ileri) * Time.deltaTime;
    }

right : Objenin local sağ yönü verisini, yani local x ekseninin genel koordinat sistemine göre elde etmemizi sağlar.

    float donusHizi = 45f;
    void Update () {
        //space tuşuna basılı tutulduğunda objenin x ekseninde
        //verilen donuzHizi değerine göredöndürme işlemi yapar
        if (Input.GetKey (KeyCode.Space))
            transform.eulerAngles += transform.right * Time.deltaTime * donusHizi;

        //D tuşuna basıldığında objenin x eksenine göre 1 birim ileri ışınlar
        // objenin açısını değiştirerek deneyebilirsiniz.
        if (Input.GetKeyDown (KeyCode.D))
            transform.position += transform.right;
    }

root : En üst seviyedeki parent objesine erişmemizi sağlayan değişkendir. Eğer obje herhangi bir parent objesine sahip değilse objenin kendisini döndürecektir.

    void Start () {
        //eğer transform root ile aynı değere sahip ise
        //objenin ebeveyni yoktur
        //eğer objenin ebeveyni var ise ebeveyn ismini log ekranına yazdırırız
        if (transform == transform.root)
            Debug.Log ("Ebeveyne sahip değil");
        else {
            Debug.Log ("En üst ebeveyn ismi: " + transform.root.name);
        }
    }

rotation: Objenin genel koordinat sistemindeki rotasyon değerini Quaternion tipinde tutan değişkendir.

    //hedef objeyi sürükleyip bırakabileceğimiz bir alan oluşturuyoruz
    [SerializeField]
    Transform hedefObje;

    Quaternion baslangic;
    bool dondur = false;
    float donmeOrani = 0;

    void Update () {
        //eğer dönme işlemi yapılmıyorsa ve space tuşuna basılırsa
        //dönme oranını sıfırlatıp dönmeyi başlatıyor
        if (Input.GetKeyDown (KeyCode.Space) && !dondur) {
            dondur = true;
            donmeOrani = 0;
            baslangic = transform.rotation;
        }

        if (dondur) {
            donmeOrani += Time.deltaTime;
            //donme orani sayesinde Quaternion.Slerp fonksiyonuyla başlangıc ve hedef rotasyonlar arasında
            //belirli bir oranda değişim sağlanabiliyor
            //örneğin 0 dersek rotasyon baslangic değerini alır
            //1 dersek de hedefObje.rotation değişkenini
            transform.rotation = Quaternion.Slerp (baslangic, hedefObje.rotation, donmeOrani);
            if (donmeOrani > 1) {
                dondur = false;
            }
        }
    }

up : Objenin yukarı yönünü, yani Y eksenini genel kooardinat sistemine uyarlanmış şekilde elde etmemizi sağlar.

    float donusHizi = 45f;
    void Update () {
        //space tuşuna basılı tutulduğunda objenin Y ekseninde
        //verilen donuzHizi değerine göre döndürme işlemi yapar
        if (Input.GetKey (KeyCode.Space))
            transform.eulerAngles += transform.up * Time.deltaTime * donusHizi;

        //D tuşuna basıldığında objenin Y eksenine göre 1 birim ileri ışınlar
        // objenin açısını değiştirerek deneyebilirsiniz.
        if (Input.GetKeyDown (KeyCode.E))
            transform.position += transform.up;
    }

worldToLocalMatrix : Genel koordinat sistemindeki bir transform verisini local, obje koordinatlarına göre uyarlayan Matrix4x4 tipinde bir değer döndüren değişkendir. İleri seviye konulardır. Bunun yerine yazının devamında bahsettiğimiz InverseTransformPoint komutunu kullanabilirsiniz.

Public Metodlar

DetachChildren : Objenin bütün altobjelerini ondan ayırır, altobje olmaktan çıkarır. Altobjeler de altobjelere sahipse bunların ebeveyn-çocuk yapısı bozulmaz. Objenin silip altobjelerini korumak istediğiniz ve benzeri durumlarda kullanabileceğiniz bir fonksiyondur.

    //Space tuşuna basıldığında altobjeleri bu objeden ayırır
    //ardından objenin kendisini yok eder
    void Update () {
        if (Input.GetKeyDown (KeyCode.Space)) {
            transform.DetachChildren ();
            Destroy (gameObject);
        }
    }

Find : Objenin altobjelerini ismine göre arayıp bulmamızı sağlayan fonksiyondur. Eğer o isimde bir obje bulamazsa null değer döndürür. Ayrıca “/” karakteri kullanarak altobjelerin de altına inebiliriz, yani hiyerarşik aramalar da yapabiliriz.

    void Start () {
        //kapı adlı altobjeyi arar
        //bulursa log ekranına pozisyon değerini bulamazsa bulunamadı yazısını yazdırır
        Transform solKapi = transform.Find ("Sol Kapı");
        if (solKapi != null) {
            Debug.Log ("Sol Kapı pozisyonu: " + solKapi.position);
        } else {
            Debug.Log ("Sol kapı bulunamadı");
        }

        //altobje olan sağ kapı adlı objenin altında bulunan sapı isimli
        //objeyi arar.Bulup bulamadığını log ekranında yazdırır
        Transform sağKapiSapi = transform.Find ("Sağ Kapı/Sapı");
        if (sağKapiSapi == null) {
            Debug.Log ("Sağ kapı sapı bulunamadı");
        } else {
            Debug.Log ("Sağ kapı sapı bulundu");
        }
    }

GetChild : Index değerine, sırasına göre altobjelere erişmemizi sağlar. Verilecek index değeri 0’dan küçük veya childCount değerinden büyük olursa hata verecektir.

    void Start () {
        //childCount değerine bakarak, objenin altobjeye sahip olup olmadığını anlayabiliriz
        if (transform.childCount > 0) {
            //ilk ve son altobjeyi bulup ismini log ekrana yazdırır
            //index değerleri 0'dan başlar bu yüzden 0 ve childCount-1 kullanıyoruz
            //örneğin 10 adet obje varsa indexleri 0'dan başlayıp 9'da son bulacaktır.
            Debug.Log ("İlk altobjenin ismi: " + transform.GetChild (0).name);
            Debug.Log ("Son altobjenin ismi: " + transform.GetChild (transform.childCount - 1).name);
        } else {
            Debug.Log (transform.name + " hiçbir altobjeye sahip değil");
        }
    }

GetSiblingIndex : Eğer obje bir ebeveyne sahip ise, bu ebeveyn altındaki index değerini elde etmemizi sağlar.

    void Start () {
        //transform değişkenini bu şekilde foreach döngüsüne sokarak da sırayla
        //altobjelere erişebiliriz
        //örnekte her bir altobjeye erişip ismini ve index değerini log ekranına yazdırıyoruz.
        foreach (Transform altobje in transform) {
            Debug.Log (altobje.name + " index değeri : " + altobje.GetSiblingIndex ());
        }
    }

InverseTransformDirection : Genel koordinat sistemindeki bir yön/rotasyon Vector3 verisini objenin rotasyonunu baz alarak, onu 0,0,0 değeri varsayarak hesaplar ve bize geri döndürür.

    //Objenin rotasyon değerini değiştirip o şekilde denemek tam işlevini görmenizi sağlayacaktır.

    void Start () {
        //Örnekte genel kooardinat sistemindeki yukarı yön değerini
        //objenin koordinatlarına göre şekillendirip log ekranın yazdırıyoruz.
        Vector3 objeyeGoreYon;
        objeyeGoreYon = transform.InverseTransformDirection (Vector3.up);
        Debug.Log (objeyeGoreYon);
    }

InverseTransformPoint : Genel koordinat sistemine göre verilen bir pozisyon, değerini objeye göre elde etmemizi sağlar. Objeyi merkez (0,0,0) noktası kabul ederek işlem yapıp yeni bir vector3 değeri elde etmemizi sağlar diyebiliriz. Objenin konumu, rotasyonu ve boyutları bu hesaplamada etkilir.

    //Objenin pozisyon değerini merkez (0,0,0) noktasından farklı bir değer alacak
    //şekilde değiştirirseniz tam olarak işlevini anlayabilirsiniz.
    //isterseniz scale değerleriyle oynayarak da etkilerini görebilirsiniz.

    void Start () {
        //3,0,5 konumunu obje koordinatlarına göre tekrar şekillendiriyoruz
        //objenin kendisini (0,0,0) sayacağı için, eğer
        //obje sahnenin merkezinde, global 0,0,0 konumunda olursa 
        //verdiğimiz değer aynı şekilde ekrana yazdırılır
        Vector3 objeyeGoreKonum;
        objeyeGoreKonum = transform.InverseTransformPoint (new Vector3 (3, 0, 5));
        Debug.Log (objeyeGoreKonum);
    }

InverseTransformVector :Genel koordinat sistemine göre verilen Vector3 değerlerini objenin boyutu ve rotasyon değerlerine göre hesaplar ve bize geri verir.

    //farkı daha iyi görebilmek için
    //objenin scale ve rotation değerleriyle oynayıp değiştirin
    void Start () {
        //3,0,5 değerlerine sahip vektörü objenin rotasyon ve büyüklüğüne göre
        //local koordinat sistemine uyarlar
        //log ekranına genel ve local değerleri yazdırır
        Vector3 objeyeGoreKonum;
        Vector3 konum = new Vector3 (3, 0, 5);
        objeyeGoreKonum = transform.InverseTransformVector (konum);
        Debug.Log ("Genel Koordinat Sistemi => Konum :" + konum + "vektör büyüklüğü" + konum.magnitude);
        Debug.Log ("Obje Koordinat Sistemi => Konum :" + objeyeGoreKonum + "vektör büyüklüğü" + objeyeGoreKonum.magnitude);
    }

IsChildOf : Verilen Transform değişkeni objenin ebeveyni mi, yani bu obje verilen objenin altobjesi mi bunu true veya false değerleri olarak bize döndürür.

    [SerializeField]
    Transform obje;

    void Start () {
        //Bu scripte sahip objenin, verilen objenin altobjesi,çocuğu olup olmadığını log ekranına yazdırır.
        if (transform.IsChildOf (obje)) {
            Debug.Log (obje.name + "isimli obje" + transform.name + "isimli objenin ebeveyni");
        } else {
            Debug.Log (obje.name + "isimli obje" + transform.name + "isimli objenin ebeveyni değil");
        }
    }

LookAt : Objenin Vector3 cinsinden verilen konuma bakmasını, önünü ona doğru çevirmesi sağlanır.

    void Update () {
        //D tuşuna basılınca obje kendi sağ yukarısına döner
        if (Input.GetKeyDown (KeyCode.D)) {
            transform.LookAt (transform.right + transform.up);
        }
    }

Rotate : Vector3 cinsinden değerler vererek objeyi döndürmemizi, rotasyon değerini değiştirmemizi sağlar. Objeyi ister kendi (local) ekseninde istersek de genel dünya eksenlerinde döndürebiliriz.

    Vector3 xDonus = new Vector3 (15, 0, 0);

    void Update () {
        //D tuşuna basılınca objeyi
        //kendi y ekseninde 15 derece döndürür
        if (Input.GetKeyDown (KeyCode.D)) {
            transform.Rotate (0, 15, 0);
            //transform.Rotate(new Vector3(0,15,0)); şeklinde de yazılabilir
        }
        //objeyi genel x ekseninde 15 derece döndürür;
        if (Input.GetKeyDown (KeyCode.W)) {
            transform.Rotate (xDonus, Space.World);
        }
        //farklı değerler kullanarak siz de deneyin
    }

RotateAround : Objeyi belirli bir noktanın etrafında döndürmemizi sağlayan fonksiyondur. Merkez noktası dışında, dönüş işleminin ekseni ve kaç derecelik açı ile dönüş yapılacağını da belirtmemiz gerekir.

    //inspector ekranında merkez olarak kullanacağınız
    //objeyi atamayı unutmayın
    [SerializeField]
    Transform merkezObje;

    void Update () {
        //objeyi merkezObjesinin etrafında y ekseninde 30 derecelik açıyla döndürür
        transform.RotateAround (merkezObje.position, Vector3.up, 30 * Time.deltaTime);
    }

SetAsFirstSibling : Objeyi ebeveyninin ilk altobjesi haline getirir. Bu sıralama değişimi hiyerarşik olarak yapılır.

    void Start () {
        //bu scriptin altobjelerinde en son sırada bulunanını
        //ilk sıraya yerleştirir. Diğer objelere sıralamada 1 birim aşağı kayar.
        Transform sonAltobje = transform.GetChild (transform.childCount - 1);
        sonAltobje.SetAsFirstSibling ();
    }

SetAsLastSibling : Objeyi ebeveyninin hiyerarşik olarak en sonuncu altobjesi haline getirir.

void Start () {
        //bu scriptin bulunduğu objenin altobjelerinde ilk sırada olanı
        //son sıraya yerleştirir. Diğer objelere sıralamada 1 birim yukarıya doğru kayar.
        Transform sonAltobje = transform.GetChild (0);
        sonAltobje.SetAsLastSibling ();
    }

SetParent : Objeye bir ebeveyn vermemizi, haliyle verdiğimiz objenin altobjesi haline getirmemizi sağlar. Transform cinsinden bir değişken alır.

[SerializeField]
    Transform yeniEbeveyn;
    void Start () {
        //verilen yeniEbeveyn objesini ebeveyn olarak atar
        transform.SetParent (yeniEbeveyn);
    }

SetPositionAndRotation : Vector3 ve Quaternion cinsinden iki değişken alır, ve objenin konumunu ve rotasyonunu bu verilen değişkenler olarak belirler.

    //objenin belirli bir konuma ve açıya gitmesi için kullanabilirsiniz
    void Start () {
        //objenin pozisyonunu sıfırlar, rotasyonunu aynı bırakır;
        transform.SetPositionAndRotation (Vector3.zero, transform.rotation);
        //objenin pozisyonunu korurken rotasyonunu sıfırlar;
        transform.SetPositionAndRotation (transform.position, Quaternion.identity);
        //objenin pozisyonunu ve rotasyonunu sıfırlar
        transform.SetPositionAndRotation (Vector3.zero, Quaternion.identity);
    }

SetSiblingIndex : Obje bir ebeveyne sahipse, altobje olarak sırasını değiştirmemizi sağlar. Int tipinde verdiğimiz index değerine göre objenin hiyerarşik konumunu değiştirir.

    //objeyi sırasını 2.index olarak atar
    //yani 3.altobje haline gelir
    void Start () {
        transform.SetSiblingIndex (2);
    }

TransformDirection : Obje local koordinatlarında elde ettiğimiz Vector3 cinsinden olan yön verisini genel (global) koordinatlara göre elde etmemizi sağlar. Objenin rotasyon değerleri hesaplamada etkilidir.

    [SerializeField]
    GameObject yeniObje;
    void Start () {
        // objeye göre 45,0,45 vector3 değerien sahip rotasyonu
        // sahip yeni bir obje yaratır
        Vector3 yeniobjeRotasyonu = transform.TransformDirection (45, 0, 45);
        Instantiate (yeniObje, transform.position, Quaternion.Euler (yeniobjeRotasyonu));
    }

TransformPoint : Obje local değerlerine göre elde edilen Vector3 pozisyon değerini genel, global sisteme çevirmemizi sağlar. Objenin pozisyonu, rotasyonu ve boyutları hesaplamaya etki eder.

    [SerializeField]
    GameObject yeniObje;
    void Start () {
        // objenin 3 birim yukarısında yeni bir obje yaratır
        Vector3 yeniObjePozisyonu = transform.TransformPoint (0, 3, 0);
        Instantiate (yeniObje, yeniObjePozisyonu, yeniObje.transform.rotation);
    }

TransformVector : Objenin local yapısına göre elde ettiğimiz Vector3 cinsinden vektör değerlerini genel koordinat sistemine uyarlamamızı sağlar. Objenin rotasyonu ve boyutları hesaplamada etkilidir.

Translate : Objeyi transform bileşenini kullanarak adım adım hareket ettirmemizi sağlar. Vector3 cinsinden hareket büyüklüğünü değişken olarak alır. Ayrıca local veya genel koordinat sistemini kullanmayı seçebiliriz. Eğer local seçersek verilen vector3 değişkeni local olarak değerlendirilir. Yani Vector3.up verirsek, objenin yukarı yönü neresi ise oraya hareket eder. Ancak genel, global ekseni seçersek verdiğimi Vector3 değeri direkt uygulanır. Örnekte ikisi arasındaki farkı gösterdim.

    //objenin rotasyon değerleriyle oynamayı unutmayın
    void Update () {
        //objeyi kendi yukarı, y ekseninde 1 birim ilerletir.
        if (Input.GetKeyDown (KeyCode.W)) {
            transform.Translate (Vector3.up);
        }
        //objeyi genel yukarı, y ekseninde 1 birim ilerletir.
        if (Input.GetKeyDown (KeyCode.Space)) {
            transform.Translate (Vector3.up, Space.World);
        }
    }

Kodları da tamamladığımıza göre, az çok Unity Transform Nedir? sorusunun cevabı iyice kafanıza yerleşmiştir diye umuyorum. Kaynağı türkçeleştirmeye çalışsam da, orjinal dökuman üzerinden de inceleme yapmak isterseniz Unity Transform üzerinden erişebilirsiniz.

Unity Rigidbody Nedir?

Hepinize merhaba dostlar, bu yazımızda Unity Rigidbody Nedir ? sorusunu olabildiğince geniş çaplı şekilde cevaplayacağız. Rigidbody bileşeni nasıl kullanabiliriz, hangi fonksiyonlarla hangi işlemleri gerçekleştirebiliriz ve rigidbody sayesinde fizik motorundan nasıl yararlanabiliriz bunları adım adım anlatarak Unity Rigidbody için bir nevi döküman oluşturmuş olacağız.

Öncelikle Rigidbody nedir bundan bahsedelim. Rigidbody bileşeni, Unity fizik motorunu kullanarak gerçek dünyada olduğu gibi fiziksel hareketlerin taklit edilmesini sağlar. Yerçekimi yüzünden nesnelerin aşağı düşmesi, yuvarlak objelerin yuvarlanırken köşeli objelerin sabit kalması gibi hareketleri düşünebilirsiniz en basit haliyle. Ve bu bileşen sayesinde objelere gerçekçi şekilde hareket yeteneği de verebiliriz. Örneğin bir araba modelinde, tekerlere döndürme kuvveti (tork) uygulayarak arabanın ilerlemesini sağlayabilir ve tekerlerin rotasyonunu değiştirerek sağa sola hareket ettirebiliriz. Gördüğünüz gibi fizik motorunun gücü azımsanmayacak seviyede kolaylıklar sağlıyor bize. Şimdi biraz da Rigidbody bileşenin ne gibi özellikleri var, inspectorda nasıl gözüküyor bunlara bakalım.

Öncelikle sahneye 1 adet plane ve 1 adet küre (sphere) eklemenizi istiyorum. Ayrıca küreyi plane objesinin biraz daha yukarısına yerleştirin. Bu iki objede fiziksel işlemleri gerçekleştirmek için ihtiyaç duyacağımız Collider tipindeki bileşene sahip oyun objeleridir. Daha sonrasında küre objemize Rigidbody bileşenini  Eğer bilmiyorsanız, her GameObject’e bir bileşen (component) ekleyebiliriz. GameObject ve bileşen eklemeyi ve daha detaylı bilgileri Unity – GameObject Nedir ? yazımızda bulabilirsiniz.. Yapmanız gereken şey, objeyi seçtikten sonra inspector kısmında “Add Component” butonuna tıklamak, ardında da arama kısmına “Rigidbody” yazmak. Karşınıza gerekli bileşen çıkacaktır, tıkladığınızda da artık objeye eklenmiş olacaktır. Şimdi ufak bir test sürüşü için oyunu başlatıp kürenin nasıl aşağı hareket ettiğini izleyebilirsiniz. Söylediğim gibi, plane üstünde olmasına dikkat edin.

Ufak bir bilgi vermekte de yarar olduğunu düşünüyorum, Rigidbody ile ilgili bütün genel ayarlamaları “Edit>Project Settings>Physics” altından yapabilirsiniz. Az sonra vereceğimiz özelliklerin bir kısmı nesneye özel ayarlanması gerekirken bir kısmı da bütün objelerin kullandığı ortak özelliklerdir. Örneğin oyundaki yer çekimini veya katmanlar (layer) arasında hangilerinin birbiriyle etkileşime girebileceğini bu kısımdan ayarlayabilirsiniz.

Rigidbody Özellikleri

Şimdi de özelliklere gelelim. Inspector panelinde bileşen alanına baktığınızda bazı alanlar olduğunu farketmişsindiz. Bunlar isterseniz panel üzerinden isterseniz de kod üzerinden değiştirebileceğiniz özelliklerdir. Bu özellikler sayesinde yaratmaya çalıştığınız fizik simülasyonlarını tam olarak istediğiniz hale getirebilirsiniz. Gerçek dünyada olduğu gibi burada da fizik formüllerinden yararlanıldığı için, biraz fizik ve matematik bilgisinin size kesinlikle faydası olacaktır. Şimdi özellikleri tek tek inceleyelim ve ne işe yaradıklarını ele alalım.

Mass : Objenin kilogram cinsinden ağırlığını temsil eder. Uygulayacağınız fiziksel kuvvetler açısından önemlidir. Örneğin aynı büyüklüğe sahip demir topa vurduğunuzdaki gideceği uzaklıkla, futbol topuna vurduğunuzda gideceği uzaklık farklıdır. Bu farkı belirleyen en temel şeylerden biri ağırlıktır.

Drag : Objenin bir kuvvet uygulandığında ne kadar hava direncine / sürtünmesine sahip olacağı değeridir. Bu değer kuvvetten daha az etkilenilmesini sağlar, yani daha yavaş bir hareket oluşturur. Eğer 0 değeri verilirse harekette hiç azalma olmazken “infinity” değeri verilirse obje anında duracaktır.

Angular Drag : Objenin kuvvete karşı göstereceği başka bir hava direnci tipi. Burada farklı olarak hareket yerine rotasyon değişimi, dönme üzerinde ne kadar direnç olacağını belirtiyoruz. Yine 0 değeri verdiğimizde hiçbir dirence sahip olmayacaktır, ancak infinity değerinin kullanımı burada rotasyonu, dönüşü tamamen durdurmayacaktır.

Use Gravity : True veya false değeri alan bu değer objemizin yerçekiminden etkilenip etkilenmeyeceğini belirtir. Uzay gibi bir yerçekimsiz bir ortam yaratmak istiyorsanız fazlasıyla işinize yarayabilir. Veya objelerin havada rahatlıkla süzülmesini istediğiniz durumlarda. Olasılıklar sonsuz, değil mi ?

Is Kinematic : Yine true veya false değeri alan bu değişken ise objenin bütün fizik etkileşimlerinden muaf tutulmasını sağlar. Eğer true değerine sahipse, ister kod ile ister oyun içinde objelerin çarpmasıyla olsun, hiçbir kuvvet harekete sebep olmayacaktır. Ragdoll veya HingeJoint gibi yapılar kullanırken işinizi kolaylaştıracak bir özelliktir.

Interpolate:  Fiziksel işlemler ile objenin hareketini hesaplarken bir yumuşatmaya tabii tutulup tutulmayacağını belirlediğimi özellik. Eğer rigidbody ile hareketi sağlarken titremeler yaşıyorsanız bu ayarı kurcalamak sorununuzu çözecektir. Alabileceği 3 değer vardır. Bunlar ;

  1. None : Hiçbir yumuşatma işlemi gerçekleşmez.
  2. Interpolate : Objenin bir önceki karede sahip olduğu Transform değerlerine göre yumuşatma işlemi yapılır.
  3. Extrapolate : Objenin gelecek karede tahminen olması gereken yer baz alınarak yumuşatma işlemi gerçekleşir.

Collision Detection: Obje temaslarının tespitiyle alakalı bir ayardır. Bazı objeleriniz çok hızlı olduğundan dolayı fiziksel temaslar çalışmayabilir. Bu ayar sayesinde temas kontrolünün, algılanmasını ne kadar hassas olacağını belirleyebiliriz. 3 tane seçeneğe sahiptir. Bunlar;

  1. Discrete : Standart olarak seçili olan ayardır. 
  2. Continuous : Daha yüksek hassasiyete sahip bir ayardır. Farklı algılama değerine sahip objelere farklı şekilde tepki verir. Hızlı objelerle bir sorun yoksa Discrete kullanılması önerilir.
  3. Continuous Dynamic : Hızlı harekete sahip objelerde kullanılabilecek bir seçenektir. 
  4. Continuous Speculative : Bu seçenek performans açısından bakıldığında diğer 2 Continuous seçeneğinden daha performanslıdır. Ayrıca kinematic haldeki bileşenlere atanabilecek tek Continuous tipindeki seçenektir.

Constraints : Objemizin hareketini ve rotasyon değişimini kısıtlamamızı sağlar. Belirli eksenlerdeki hareketi Freeze Position seçenekleriyle, dönüşleri ise Freeze Rotation seçenekleriyle engelleyebilirsiniz.

Gördüğünüz bu özellikleri biraz kurcalayarak az önce oluşturduğumuz basit sahnede büyük değişiklikler yapabilirsiniz. Örneğin, Drag ve Angular Drag değerleriyle oynamayı deneyin, arttırın ve azaltın. Deneyimleyerek öğrenmek en güzel yöntemlerden biridir.

Unity Rigidbody İle Kullanılabilecek Kodlar

Unity Rigidbody Nedir? sorusunu cevaplamaya kullanabileceğimiz kodlar ile devam edelim şimdi. Ayrı başlıklar halinde anlatıma geçmeden önce, biraz daha genel kullanıma sahip olan ve Rigidbody İle Kullanılabilecek Kodlar arasında bulunan belirli başlı komutlardan bahsetmek istiyorum. Bunlar genellikle diğer bileşenlerle de kullanabileceğimiz komutlar, aklınızda bulunsun.

Ayrı başlıklar halinde anlatıma geçmeden önce, biraz daha genel kullanıma sahip olan ve Rigidbody İle Kullanılabilecek Kodlar arasında bulunan belirli başlı komutlardan bahsetmek istiyorum. Bunlar genellikle diğer bileşenlerle de kullanabileceğimiz komutlar, aklınızda bulunsun.

Destroy () : Bu method içerisine değişken olarak verdiğin obje yok olacaktır, eğer Rigidbody gibi bir bileşen verirseniz bileşeni o objeden kaldıracaktır.

//Rigidbody bileşenine ulaşıp objeden kaldırır.
	//Buradaki “gameObject” özel bir değişkendir ve MonoBehaviour kodlarında, atandığı objeyi verir.
	Rigidbody rgb=gameObject.GetComponent<Rigidbody>();
	Destroy(rgb);

Instantiate () : Bir GameObject yaratmanızı sağlar. Eğer GameObject yerine bir bileşen tipi verirseniz o bileşene sahip bir GameObject yaratır. Prefab kullanımında belirli tipe sahip objeleri kullanmak için kullanabilirsiniz. Aşağıdaki kodu denerseniz içerisine top alanına sadece Rigidbody’e sahip objeler seçebileceğinizi görebilrsiniz.

	//Space tuşuna basıldığında Rigidbody tipine sahip objeyi çoğaltır.
public Rigidbody top;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Bu koda sahip objenin konumunda ve açısında yeni bir top oluşturur
// yenitop değişkeni ile yaratılan objeye fizik komutları verebilirsiniz.
            Rigidbody yeniTop;
            yeniTop= Instantiate(top, transform.position, transform.rotation);
        }
    }

Özellikler – Erişilebilir Değişkenler

angularDrag : Dönüş hareketine etki eden değerdir. Sıfır verilirse dönüşe hiçbir etki olmaz.

    public Rigidbody rgb;
    void Start () {
        rgb = GetComponent<Rigidbody> ();
    }

    // Space tuşuna basılı tutulduğu sürece angularDrag değerini 15 yapar
    // ve dönüş hareketi yavaşlatır.
    void Update () {
        if (Input.GetKey (KeyCode.Space))
            rgb.angularDrag = 15;
        else
            rgb.angularDrag = 0;
    }

angularVelocity :Dönüşsel hareketin değeridir. Radyan/Saniye olarak belirtilir. Bu değeri direkt değiştirmek gerçekçi olmayan hareketlere sebep olabilir. 

    public Rigidbody rgb;
    public MeshRenderer renderer;

    void Start () {
        rgb = GetComponent<Rigidbody> ();
        renderer = GetComponent<MeshRenderer> ();
    }

    //Eğer angularVelocity büyüklüğü 7.5f değerinden küçük ise 
    // objeyi yeşil renge, büyük veya eşit ise kırmızı renge boyar 
    void Update () {
        if (rgb.angularVelocity.magnitude < 7.5f)
            renderer.sharedMaterial.color = Color.green;
        else
            renderer.sharedMaterial.color = Color.red;
    }

centerOfMass : Objenin ağırlık merkezi değeridir. Vector3 cinsinden değer alır ve objenin merkezine göre ağırlık merkezini belirler.

public Rigidbody rgb;

    //Ağırlık merkezini objenin 1 birim yukarısı olarak ayarlar.
    void Start () {
        rgb = GetComponent<Rigidbody> ();
        rgb.centerOfMass = new Vector3 (0, 1, 0);
    }

collisionDetectionMode : Objenin temas işlemleri için kullanılacak moddur. CollisionDetectionMode tipinde değişken alır.

constraints : Objenin hareket ve dönüş işlemlerinde kısıtlanması için kullanılan değişkendir. RigidbodyConstraits tipinde değişken alır.

 public Rigidbody rgb;

    //İstersek kısıtlmaları değişken olarak tutabiliriz.
    RigidbodyConstraints yEkseniKisitla = RigidbodyConstraints.FreezePositionY | RigidbodyConstraints.FreezeRotationY;

    void Start () {
        rgb = GetComponent<Rigidbody> ();

        //Objenin X eksenindeki hareketini engeller
        rgb.constraints = RigidbodyConstraints.FreezePositionX;

        //Objenin y ve z eksenindeki dönüşü engeller
        // '|' işaretini kullanarak birden fazla kısıtlama ekleyebiliriz.
        rgb.constraints = RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;

        //oluşturduğumuz kısıtlama değişkenini atayabiliriz.
        rgb.constraints = yEkseniKisitla;
    }

detectCollisions : Fiziksel işlemlerde temas, dokunma algılama işlemlerinin çalışıp çalışmamasını belirlediğimiz değişken. Standart olarak açık haldedir.

public Rigidbody rgb;

void Start () {
        rgb = GetComponent<Rigidbody> ();
    }
    void Update () {
        //Space tuşuna basıldığında algılama açık ise kapalı
        //kapalı ise açık hale getirir. ! işareti ile durumu
        // tersine çeviririz.
        if (Input.GetKeyDown (KeyCode.Space))
            rgb.detectCollisions = !rgb.detectCollisions;
    }

drag : Sürtünme, direnç kuvveti değişkenidir. Ne kadar yüksek olursa obje temaslarında hareket o kadar azalacak, yavaşlayacaktır.

public Rigidbody rgb;

    void Start () {
        rgb = GetComponent<Rigidbody> ();
    }
    void Update () {
        //Drag değeri Space tuşuna basılınca 20
        //Space basılmayı bırakınca 0 değerini alarak
        // yerçekimi gibi fiziksel etkilerden daha farklı şekilde etkilenir.
        if (Input.GetKeyDown (KeyCode.Space))
            rgb.drag = 20;
        else if (Input.GetKeyUp (KeyCode.Space))
            rgb.drag = 0;
    }

freezeRotation : Objenin fiziksel etkiler yüzünden dönüş hareketi yapıp yapmayağını belirlediğimiz değişkendir. False değeri verilirse hiçbir fiziksel etki objeyi döndüremeyecektir.

interpolation : Fizik hareketlerinde yumuşatma tipini belirlediğimiz değişkendir. Standart olarak “None” seçeneği ile gelir. RigidbodyInterpolation tipinde değişken alır.

public Rigidbody rgb;

    void Start () {
        rgb = GetComponent<Rigidbody> ();
        rgb.interpolation=RigidbodyInterpolation.Interpolate;
    }

isKinematic : Objenin fiziksel kuvvetlerden etkilenip etkilenmediğini belirlediğimiz değişkendir. True veya false değeri alır.

mass : Objenin ağırlığıdır. Float tipinden değişken alır ve fiziksel hareket hesaplarında önemli bir değişkendir.

maxAngularVelocity :Objenin saniyede yapabileceği maksimum dönüş hareketini belirlediğimiz, bir nevi sınır koymamızı sağlayan değişkendir. Standart olarak 7 değerine sahiptir. Radyan olarak kabul edilir, yani standart olarak bir obje 1 saniyede 7 radyanlık dönüş gerçekleştirebiliriz.

position : Objenin o anki pozisyonu değeridir. Vector3 cinsindedir.

public Rigidbody rgb;

    void Start () {
        rgb = GetComponent<Rigidbody> ();
    }
    void Update () {
        //Space tuşuna basıldığında objeyi 0,5,0 noktasına götürür
        //Vector3.up 0,1,0 değerine eşittir. 
        //Çarpma işlemi yaptığımızda 7 değeri çarptığımız sayı değerini almış olur
        if (Input.GetKeyDown (KeyCode.Space))
            rgb.position = Vector3.up * 5;
        //Objenin pozisyonunu ekrana yazdırır
        Debug.Log (rgb.position);
    }

rotation : Objenin yön bilgisini tutar. Quaternion cinsindedir.

public Rigidbody rgb;
    //Objenin yön bilgisini sıfırlar
    void Start () {
        rgb = GetComponent<Rigidbody> ();
        rgb.rotation = Quaternion.identity;
    }

sleepThreshold : Objenin fizik işlemlerini askıya alma, bir nevi uykuya dalması için gerekli olan enerji aralığıdır. 

solverIterations : Rigidbody objelerinde Joint ve Collision temaslarının ne kadar sık/kararlı şekilde hesaplandığını belirtir. Birbirine bağlı Rigidbody bileşenlerinde sallanma veya menteşe gibi işlemler yaparken istediğiniz sekilde, sağlıklı çalışmadığını düşünüyorsanız bu değeri arttırarak daha kararlı, sık şekilde çalışmasını sağlayabilirsiniz. Daha yüksek değerler daha iyi simülasyon oluşturur ancak performansa da etki eder. Standart olarak sahip olduğu değer 6’dır.

solverVelocityIterations : Joint ve Collision temasları sonrasında simulasyonun ne kadar yüksek hassasiyetle çalıştırıldığı ile alakalıdır. Örnek vermek gerekirse, bu değeri arttırdıktan sonra fizik motorundan yararlanan objeniz zıplamanın ardından daha yüksek hassasiyetle simule edilecektir. Standart değeri 1’dir. 

useGravity :Objenin yerçekiminden etkilenip etkilenmeyeceğini belirttiğimiz değişkendir. True veya false değeri alır.

velocity : Objenin anlık hareketinin Vector3 cinsinden değeridir. Direkt atanmaması önerilir. Velocity değerini daha sağlıklı olarak değiştirmek için aşağıda bahsettiğimiz AddForce gibi fonksiyonları inceleyebilirsiniz.

worldCenterOfMass : Obje ağırlık merkezinin genel koordinat sistemindeki pozisyonunu Vector3 cinsinden verir. Sadece okunabilir bir değişkendir, değiştirilemez.

Public Methodlar

AddExplosionForce () : Belirtilen pozisyonda bir patlama efekti simule eder. Patlama alanı bir küre olarak hesaplanır. Patlamanın merkez noktasında belirtilen kuvvet tamamen uygulanırken bu küre halindeki alanın dışına ulaştıkça değer sıfıra yaklaşır. Ayrıca ForceMode tipinde değişken belirtilerek kuvvetin nasıl etki edeceği belirtilebilir. Standart olarak verilmiş değer ForceMode.Force idir.

    public float yaricap= 3f;
    public float patlamaSiddeti= 15f;

    void Start()
    {
        Vector3 patlamaMerkezi= transform.position;
        //Belirtilen yarıçap kullanılarak patlama alanı içerisinde kalan objeleri buluyoruz
        Collider[] objeler= Physics.OverlapSphere(patlamaMerkezi, yaricap);
        foreach (Collider obje in colliders)
        {
            Rigidbody rb = obje.GetComponent<Rigidbody>();
	//eğer bulunan obje rigidbody bileşenine sahipse patlama efekti uyguluyoruz.
	//buradaki 3 değeri objeye yukarı yönde ne kadar kuvvet uygulanacağını gösterir.
            if (rb != null)
                rb.AddExplosionForce(patlamaSiddeti, patlamaMerkezi, yaricap, 3.0F);
        }
    }

AddForce (): Objeye direkt olarak Vector3 cinsinde verilen miktarda kuvvet uygular. 2. parametre olarak ForceMode tipinde bir değişken verilebilir, bu değişken verilmezse standart olarak ForceMode.Force kullanılacaktır.

//bu örnekte karaktere 5 birimlik yukarı yönlü kuvvet uygulanıyor.
//zıplama, havaya fırlama gibi 
public float ziplamaKuvveti = 5.0f;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        rb.AddForce(transform.up * ziplamaKuvveti);
    	//Değişkeni vector3 halinde yazarsak çarpma işleminin sonucunda şu şekilde olacaktır. Parantez içerisinde aşadğıdaki değişkeni kullanabilirsiniz ve siz de değerleri değiştirebilirsiniz.
//new Vector3(0,ziplamaKuvveti,0);
    }

AddForceAtPosition () : AddForce fonksiyonunda olduğu gibi objeye bir kuvvet uygulamamızı sağlar, ancak bu fonksiyonda objenin belirli bir noktasına kuvvet uygulayabiliriz. Örneğin bir kübü düşünürsek, kenar veya köşe noktalarını seçerek kuvvet uygulayabiliriz, bu sayede tahmin edeceğiniz gibi bu işlem kübü sadece hareket ettirmek yerine belirli bir tork, dönme hareketi de sağlayacaktır.

AddRelativeForce (): Bu fonksiyonda verilen kuvvet değeri diğerlerinden farklı olarak Global, genel koordinat sistemine göre değil, local , yani objenin koordinat sistemine göre değerlendirilir. Aynı AddForce gibi çalışmaktadır. Yalnız, hareketin yönü objeye göre değerlendirilecektir bunu unutmayın.

//ileri yönlü 5 birimlik kuvvet uygular. Karakterin z eksenine göre kuvvet uygulayacaktır
public float ileriHareket= 3.0f;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        rb.AddForce(new Vector3(0,0,ileriHareketi);
    }

AddRelativeTorque (): AddRelativeForce gibi  local koordinat sistemini kullanan, bir tork, dönme kuvveti uygulamamızı sağlayan fonksiyondur.

public float tork;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
// A ve D tuşlarına(Horizontal Axis Değerini değiştirmediyseniz) basıldıında objeyi Z ekseninde döndürmeye başlayacaktır.
        float donmeDegeri= Input.GetAxis("Horizontal");
        rb.AddRelativeTorque(Vector3.forward * tork* donmeDegeri);
    }

AddTorque (): AddRelativeTorque gibi obje tork, dönme hareketi oluşturmamızı sağlar. Local yerine Global koordinat sistemine göre hareket eder.

ClosestPointOnBounds (): Belirtilen pozisyona en yakın objenin collider noktasını/konumunu bulur ve Vector3 olarak döndürür.

void EnYakinNoktayiIsaretle(){
	//Objenin 1,0,1 noktasına en yakın kısmını bulup o konumda bir küre objesi yaratarak işaretleme yapar. Değerlerle oynayarak ya da objeyi hareket ettirerek değişimi görebilirsiniz.
//işaret küresinin boyutunu .1 değerine düşürür.
	 Vector3 enYakinNokta= rb.ClosestPointOnBounds(new Vector3(1,0,1);
	GamObject isaretKuresi=GameObject.CreatePrimitive(PrimitiveType.Sphere);
	isaretKuresi.transform.scale=Vector.one*.1f;
}

IsSleeping (): Rigidbody bileşenin uyku moduna geçip geçmediğini bool tpinde döndüren fonksiyondur.

MovePosition (): Kinematic haldeki rigidbody bileşenine sahip objeleri belirtilen pozisyona hareket ettirmeyi sağlar.  Eğer kinematic özelliği kapalıysa yavaşça hareket ettirmek yerine objeyi belirtilen konuma ışınlar.

//objeyi sağa doğru sabit hızla hareket ettirir.
Rigidbody rb;
 void Start()
    {
        rb = GetComponent<Rigidbody>();

        // Moves the GameObject using it's transform.
        rb.isKinematic = true;
    }
void FixedUpdate()
    {
        rb.MovePosition(transform.position + transform.right * Time.fixedDeltaTime);
    }


MoveRotation (): Objenin rotasyon değerini ayarlamaya yardımcı olan fonksiyondur. Eğer rigidbody kinematic özelliği açık ise yavaşça, kapalı ise aniden belirtilen rotasyon değerine geçilir.

Rigidbody rb;
Vector3 rotasyonDegisim;
 void Start()
    {
        rb = GetComponent<Rigidbody>();
rotasyonDegisim=new Vector3(1,0,0);
    }
void FixedUpdate()
    {
 Quaternion rotasyonCarpani= Quaternion.Euler(rotasyonDegisim * Time.deltaTime);
        rb.MoveRotation(transform.position + transform.right * Time.fixedDeltaTime);
    }

ResetCenterOfMass (): Ağırlık merkezinin objenin sahip olduğu collider bileşenlerine göre tekrar hesaplayıp resetleyen fonksiyondur.

SetDensity(): Float tipinde değişken alır ve objenin yoğunluğunu ayarlamamızı sağlar. Objenin sahip olduğu collider baz alınarak verilen yoğunluğu elde etmek için ağırlık (mass) değerini hesaplar ve günceller.

Sleep (): Rigidbody bileşenini uyku moduna zorlar. 

SweepTest (): Obje verilen pozisyonda ilerlerse sahnede herhangi bir objeyle çarpışma, temas yaşar mı durumunu kontrol etmemizi sağlayan fonksiyondur.

//verilen temas kontrol mesafesini kullanarak objenin ileri yönünü kontrol işlemi gerçekleştirir
// eğer bir objeye çarpma durumu oluşacaksa log ekranına çarpışmaya/ ne kadar mesafe kaldığı yazdırılır.
public float temasKontrolMesafesi;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void Update()
    {
        RaycastHit temas;
        if (rb.SweepTest(transform.forward, out temas, temasKontrolMesafesi))
        {
	Debug.Log(“Çarpışmaya kalan mesafe”+ temas.distance);
        }
    }

SweepTestAll (): Bu fonksiyonda SweepTest gibi çalışır ancak bir farkı vardır, SweepTest tek bir objeyle teması algıladığı anda dururken, SweepTestAll verilen mesafede çarpışılabilecek, temas edilebilecek bütün objeleri döndürür.

//Objenin önünde verilen mesafede bulunan obje sayısını log ekranına yazdırır.
public float temasKontrolMesafesi;
    public Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        RaycastHit[] temaslar=rb.SweepTestAll(transform.forward, temasKontrolMesafesi);
	Debug.Log(“Objenin önünde ”+ temaslar.Count()+” adet çarpışabileceği obje bulunuyor”);
    }

WakeUp (): Objeyi uyku modundan çıkmaya, tekrar çalışmaya başlamaya zorlar, geçirir.

Evet, bu şekilde Unity Rigidbody Nedir? sorusunu ingilizce Unity Rigidbody dökümanından da yararlanarak olabildiğince cevaplamaya çalıştım. Umarım işinize yarar bir kaynak oluşmuştur. Gelecek yazılarda görüşmek dileğiyle, kendinize iyi bakın.

Unity C# Temel Dersi ve Fizik ile Basit Hareket

Bu yazımızda Unity C# Temel Dersi ve Fizik ile Basit Hareket adlı videomuzu yazılı halde ilerleteceğiz. Yazının genelinde C# temel konularından bahseceğim ve adım adım bir küre (Sphere) nesnesini Unity’nin fizik altyapısı kullanarak basit hareket işlemlerini gerçekleştireceğiz. Biraz eski video olması sebebiyle dönüp bakmanızı çok öneresim gelmiyor ama merak edenler olursa buraya tıklayarak videoya gidebilirsiniz.

Öncelikle temel olarak sahnemizde neler olmalı bunlardan bahsedeyim. Eğer videoyu izlediyseniz rigidbody ile fizik işlemlerinden etkilenen birden fazla GameObject bulunuyor. Ancak 1 adet plane ve 1 adet küre objesinin olması bu ders için yeterli olacaktır. Bunları eklemek için Hieararchy paneline sağ tıklayıp açılan menüden seçerek işlemleri gerçekleştirebilirsiniz. GameObject hakkında daha detaylı bilgi edinmek için Unity – GameObject Nedir ? adlı yazımıza göz atabilirsiniz. 

Sahne içerisinde 1 adet plane ve 1 adet küre oluşturduktan sonra yapmamız gereken 2 şey var. İlki küre objesini seçip “Add Component” butonuna basarak rigidbody eklemek. Ardından tekrar aynı butona basıp “New Script” seçeneği ile bir C# dosyası oluşturmak. Bu dosya otomatik olarak objemize atanacaktır. Bunun ardından script dosyasına çift tıklayarak sahip olduğunuz kod düzenleme programı(VsCode, Visual Studio, XCode vb) üzerinde dosyamızı açalım.

Unity C# Temel

Karşımızdaki ekranda temel olarak Unity’nin bize sunduuğu hazır bir C# yapısı bulunuyor. Burada 2 adet fonksiyon göreceksiniz. Start fonksiyonu oyun başlangıç anında çalışırken Update fonksiyonu oyun çalıştığı sürece her an çağırılan bir fonksiyondur. Oyun saniyede kaç kare çalıştırabiliyorsa Update fonksiyonu da o kadar sık çağırılacaktır. Bu yüzden (benim videoda yaptığımın aksine ) fizik işlemlerini Update yerine FixedUpdate fonksiyonu içerisinde yapmak çok daha sağlıklı olacaktır. Basit işlemlerde çok farketmeyebilirsiniz ancak fizikten etkilenen objelerin sayısı arttıkça performansınıza etki etmeye başlayacaktır.

Bu bilgiler ardından, bilmeyenler için fonksiyon ve değişkenlerde bahsedeyim. Basitçe anlatmak gerekirse fonksiyonlar çağırdığımızda içerisinde bulunan kodları çalıştıran yapılardır. Bazen bir değer döndürebilirler. Ancak bu derste biz void tipini Hareket() adıyla bir fonksiyon tanımlayıp hareket işlemlerini bu fonksiyon içerisinde yapacağız. Void kullandığımız fonksiyonlar bize bir değer döndürmeyecektir. Şu anda da ihtiyacımız yok.

 Öte yandan değişkenler ise, içerisinde farklı tipte değerler tutan yapılardır, yani onları çağırdığımızda bize bir değer gönderirler. Bu değerler tam sayı (int), Ondalıklı Sayı (float) veya metin (string) olabilir. Noktalıklı sayıları yazarken dikkat etmemiz gereken şey sonlarına ‘f’ karakterini koymamız gerektiğidir. Örneğin : float ondalikli= 0.1f; gibi. Metin karakterleri de çift tırnak (“) içerisinde olmalıdır. Örneğin: string metin=”Karadot”; gibi. Bunlar dışında bu derste de kullanacağımız Vector3 gibi Unity’nin sağladığı değişkenler de bulunmaktadır. Bu tip değişkenler içerisinde 3 tane float değer tutar, x-y-z değerleri olarak. Daha çok pozisyon bilgisini tutmak için kullandığımız bir değişken tipidir. Ayrıca, bileşenler (Component) de birer değişken olarak tanımlanabilir. Bu sayede Rigidbody bileşenimizi bir değişkende tutup, üzerinde istediğimiz işlemi rahatlıkla gerçekleştirebiliriz.

Fizik ile Basit Hareket

Gerekli bilgileri size ilettikten sonra artık kodlama kısmına geçebilir ve küremizin fizik ile basit hareket elde etmesini sağlayabiliriz. Bunun için ilk yapacağımız şey Start fonksiyonun öncesinde rigidbody ve Vector3 değişkenlerimizi tanımlamamız gerekiyor. Ardından Start fonksiyonu içerisinde değişken atamasını yapacağız, yani objemizin üzerindeki Rigidbody bileşenine erişeceğiz. Aşağıdaki kod ile bunu gerçekleştirebiliriz.

   Rigidbody rgb;
    Vector3 hareketDegeri;
    void Start () {
        rgb = GetComponent<Rigidbody> ();
    }

Evet, rigidbody bileşenine erişmek bu kadar basit. Artık rgb değişkeni üzerinden istediğimiz işlemleri gerçekleştirebiliriz. Ve hareketin yönünü ve büyüklüğünü de hareketDegeri adlı değişken üzerinden sağlayacağız. Tabii ki hareketi kullanıcıdan yani bir kontrolcü aracılığı ile almamız gerekiyor ki, küreyi kontrol eden cidden biz olalım. Bu veriyi alabilmek için Input.GetAxis(); adlı fonksiyondan yararlanacağız. String tipinde bir değişken alan bu fonksiyon, verilen axis ismini alarak o axis ile bağlantılı tuşlara basılıp basılmadığını öğrenebiliriz. Bu fonksiyon -1 ve 1 arasında değerler döndürür. Örneğin, “A” ve “D” tuşları standart olarak “Horizontal” adlı axis için atanmıştır. “A” değerine bastığımızda -1, “D” değerine bastığımızda 1 değeri dönecektir. Bu sayede yatay(horizontal), yanlara doğru hareketler yapabiliriz. Şimdi bu bilgileri kullanarak hareket fonksiyonumuz oluşturalım. FixedUpdate fonsiyonu içerisinde Hareket fonksiyonunu çağırmayı unutmayın. 

   void FixedUpdate () {
        float horizontal = Input.GetAxis ("Horizontal");
        float vertical = Input.GetAxis ("Vertical");

        hareketDegeri = new Vector3 (horizontal, 0, vertical);
        Hareket (hareketDegeri);

    }
    void Hareket (Vector3 hareketDegeri) {
        rgb.velocity = hareketDegeri;
    }

Bu kodları ekledikten sonra, WASD tuşlarını kullanırsanız objeyi hareket ettirebileceğiniz görürsünüz. Ama bir şeyler yanlış gibi, öncelikle çok yavaş düşüyor, değil mi ? Ve kontrol de çok yavaş. Bunları gayet basit halledeceğiz ama nedenlerinden bahsetmek istiyorum öncelikle. Farkettiyseniz, Vector3 atamamızda 0 değeri verdiğimiz bir alan var, bu vector3 içerisindeki y değeri. Yani kooardinat sistemini düşünürsek dikey eksen, yani aşağı yukarı hareket. Biz bunu sürekli sıfırladığımız için hareket aşağı düşüşü sürekli duruyor ve tekrar yerçekimi tarafından biraz çekiliyor. Şayet Update içerisinde yaptıysanız bu fazlasıyla belli olacaktır. Bunu çözmenin yolu kolay, hareketDegeri.y=rgb.velocity.y; komutunu uygularsak her şey normal şekilde çalışacak. Öte yandan, kontrolün yavaş olmasının sebebi de tamamen verdiğimiz horizontal ve vertical değerleriyle alakalı. Daha önce bahsettiğim gibi, -1 ve 1 değeri değer alıyorlar, ki bu velocity değeri için az, hele kütlesi fazla olan karakterler için. Bu yüzden bu iki değer farklı bir sabit değerle, istediğimiz hız ile çarpmamız lazım. Şimdi kodu son hale getirelim ve güzelce küremizi hareket ettirelim.

    Rigidbody rgb;
    Vector3 hareketDegeri;
    float hiz=5;
    void Start () {
        rgb = GetComponent<Rigidbody> ();
    }
    void FixedUpdate () {
        float horizontal = Input.GetAxis ("Horizontal");
        float vertical = Input.GetAxis ("Vertical");

        hareketDegeri = new Vector3 (horizontal*hiz, 0, vertical*hiz);
        hareketDegeri.y=rgb.velocity.y;
        Hareket (hareketDegeri);
    }
    void Hareket (Vector3 hareketDegeri) {
        rgb.velocity = hareketDegeri;
    }

Bununla beraber artık Unity C# Temel Dersi ve Fizik ile Basit Hareket örneğimizi tamamlamış olduk. Fizik işlemleri hakkında biraz daha fazla bilgi edinmek isterseniz Unity – Rigidbody Nedir ? adlı yazımızı okuyabilirsiniz. Bir dahaki dersimizde görüşmek üzere, hoşçakalın.