UNITY Fonksiyonlarının (Update gibi) Görevleri ve Çalıştırılma Öncelikleri

Yayınlandı: 15 Ağustos 2013 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde
Etiketler:, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

Hepinize merhaba,

Bu derste Unity‘nin Start, Update gibi MonoBehaviour fonksiyonlarının kısaca ne zaman çalıştırıldıklarını ve birbirlerine göre çalıştırılma önceliklerini göreceğiz. Yani önce hangi fonksiyon, sonra hangi fonksiyon çalıştırılır onu göreceğiz. Bu sıralamayı bilmek bazen çok işinize yarayabilir. Dersin İngilizce kaynağı için tıklayın: http://docs.unity3d.com/Documentation/Manual/ExecutionOrder.html

Artık derse başlayalım…

NOT: Ders boyunca frame (oyun karesi) terimini göreceksiniz. Bu terimi şöyle açıklayabilirim: Siz oyununuzu oynarken bilgisayar donanımınızın gücüne göre oyununuz akıcı ya da yavaş çalışır. İşte bu hız olayı frame ile ilgilidir. Bir saniyede gördüğünüz frame sayısı ne kadar çoksa oyun o kadar akıcıdır. Her bir frame’de objelerinizin scriptlerindeki Update, OnGUI gibi devamlı görev yapan fonksiyonlar çalıştırılır. Objeler hareket ettirilir, fizik simülasyonları gerçekleşir vb.

Yeni Bir Scene Yüklendiğinde

Bu fonksiyonlar yeni bir scene yüklendiği anda, sahnedeki her obje için tek seferlik çalıştırılır.

  • Awake: Bu fonksiyon daima Start fonksiyonundan önce çalıştırılır, ayrıca bir prefab Instantiate edildiği anda da çalıştırılır. (Eğer GameObject aktif (active) değilse bu fonksiyon obje aktif olana kadar ya da bu objedeki bir scriptte yer alan bir fonksiyon dışarıdan çağrılana kadar çalıştırılmaz.)
  • OnEnable: (sadece eğer obje active ise çalıştırılır) Bu fonksiyon script enabled yapıldığı anda çalıştırılır. Bu durum ise objeye oyun sırasında yeni bir component eklenmesiyle, scene’in yüklenmesiyle ya da GameObject’in Instantiate edilmesiyle gerçekleşir.

Update Metodu İlk Kez Çalıştırılmadan Hemen Önce

  • Start: Start metodu, Update fonksiyonu henüz hiç çalıştırılmamışken tek seferlik gerçekleşir (eğer script enabled ise). Yani Update’ten önce çalıştırılır.

İki Frame Arasında

  • OnApplicationPause: Mevcut frame’de yapılacak işlemler bittikten sonra (frame’in sonunda) eğer pause durumu gerçekleşmişse bu fonksiyon çalıştırılır.

Update Sıralaması

Genelde aşağıdaki fonksiyonlardan Update’i kullanmanız tavsiye edilir ama duruma göre diğerlerini de kullanmak isteyebilirsiniz.

  • FixedUpdate: Genelde Update’ten daha sık çalıştırılır. Eğer oyun kasıyorsa bir frame’de birden çok kez çalıştırılabilir ya da oyun çok akıcıysa bazı karelerde hiç çalıştırılmayabilir de. Fizik olayları ve hesaplamaları FixedUpdate’ten hemen sonra gerçekleşir. Bu fonksiyonun içinde Time.deltaTime kullanmanıza lüzum yok çünkü Update’in aksine bu fonksiyon hep sabit bir süre aralıkla çalıştırılır.
  • Update: Her frame’de tek bir kez çalıştırılır. En sık kullanılan Update çeşididir.
  • LateUpdate: Sahnedeki objelerdeki Update metodlarının çalıştırılması bittikten sonra LateUpdate çalıştırılır ve yine her frame’de sadece bir kez çalışır. En meşhur kullanım alanlarından biri kameranın gerçek zamanlı konumlandırılmasıdır. Karakter Update metodunda hareket ettikten sonra kamera LateUpdate fonksiyonunda karakterin yeni konumunu baz alarak uygun şekilde konumlandırılabilir.

Render (Görüntü) Alma

  • OnGUI: Bir frame’de birkaç kez çalıştırılır. Önce GUI elemanları ekrana dizilir (layout) ve çizdirilir (repaint), ardından her Input eventi için tekrar çalıştırılır.
  • OnDrawGizmos: Oyunu test ederken görsel anlamda kılavuz olması için Scene panelinde gizmo çizmeye yarar.

Coroutine

Tüm Update fonksiyonları bittikten sonra çalıştırılırlar. Coroutine fonksiyonların özelliği çalıştırılmasının yarıdayken bir süreliğine duraklatılabilmesidir. Bu süre belli bir miktar (mesela 5 saniye) olabileceği gibi belirsiz bir miktar da olabilir (mesela internetten oyununuz için global yüksekskor verilerini çekiyorsunuz diyelim. Bu işlem bitene kadar coroutine vasıtasıyla çalıştırdığınız fonksiyonu duraklatabilirsiniz.).

  • yield: Coroutine’i bir frame bekletir. Yani kodun devamını bir sonraki frame’deki Update fonksiyonu çalıştıktan sonra işleme sokar.
  • yield WaitForSeconds(2): Belli bir saniye geçtikten sonra kodun çalıştırılmasına devam edilir.
  • yield WaitForFixedUpdate(): Tüm scriptlerdeki FixedUpdate fonksiyonlarının çalıştırılmasının bitmesini bekler.
  • yield WWW: Bir WWW verinin internetten indirilmesi tamamlandıktan sonra kodu çalıştırmaya devam eder.
  • yield StartCoroutine( BirCoroutineFonksiyon ): İçine girilen coroutine fonksiyonu çalıştırır ve onun bitmesini bekler. Ardından mevcut kodu çalıştırmaya kaldığı yerden devam eder.

Obje Yok Olduğunda

  • OnDestroy: Obje yok olmadan önceki son frame’inde, tüm Update() fonksiyonları çalıştırıldıktan sonra gerçekleşir. Objenin yok olmasının sebebi Destroy metodunun kullanımı olabileceği gibi başka bir sahneye (scene) geçiş de olabilir.

Oyundan Çıkarken

  • OnApplicationQuit: Oyundan çıkılmadan hemen önce gerçekleşir. Web player’da oyuncu web sayfasını kapatmak istediği anda çalıştırılır.
  • OnDisable: Script disabled yapıldığında ya da GameObject inactive yapıldığında çalıştırılır.

Özetleyecek olursak, işte scriptlerin çalıştırılma sıralaması:

  • Tüm scriptlerdeki Awake fonksiyonları
  • Tüm Start fonksiyonları
  • Tüm FixedUpdate fonksiyonları
  • Fizik hesaplamaları
  • OnEnter/Exit/Stay Trigger fonksiyonları
  • OnEnter/Exit/Stay Collision fonksiyonları
  • Eğer Rigidbody’de interpolate özelliği açıksa bunun için gerekli hesaplamalar yapılır
  • OnMouseDown/Up vb. olaylar gerçekleşir
  • Tüm Update fonksiyonları
  • Animasyon işleri gerçekleştirilir
  • Tüm LateUpdate fonksiyonları
  • Render (görüntü) alma işlemi
yorum
  1. umut dedi ki:

    Oyuna pause buttonu koydum ona basınca oyunun durmasını istiyorum bu kodu yazdım ama yemedi sorun sizce neyde ?

    var paused : boolean;
    paused = false;

    function OnMouseDown()
    {
    if(paused = false )
    {

    function OnApplicationPause(pauseStatus: true)
    {
    paused = pauseStatus;
    }
    }
    else
    {

    function OnApplicationPause(pauseStatus: false)
    {
    paused = pauseStatus;
    }
    }
    }

    • yasirkula dedi ki:

      Şunu deneyin; eğer çalışırsa iki kodu kıyaslayarak sorunları bulmaya çalışın:

      var paused : boolean = false;
      paused = false;

      function OnMouseDown()
      {
      if(paused == false )
      {
      Time.timeScale = 0;
      paused = true;
      }
      else
      {
      Time.timeScale = 1;
      paused = false;
      }
      }

  2. Selçuk dedi ki:

    Merhaba,benim şöyle bir kodum var:

    void Start(){

    StartCoroutine (Spawn ());

    }

    IEnumerator Spawn(){

    while( timeLeft>0){
    Vector3 spawnPosition=new Vector3(Random.Range(-maxWidth,maxWidth),transform.position.y,0);
    GameObject ball=balls[Random.Range(0,balls.Length)];
    Instantiate (ball, spawnPosition, Quaternion.identity);
    yield return new WaitForSeconds (Random.Range(5f,10f));
    }

    }
    while içindeki timelefti while(timeLeft>0 && timeLeft<60) yaptığım zaman kod hata vermemesine rağmen oyunda çalışmıyor.Bunu nasıl düzeltebilirim.Start fonksiyonu ilk başta çalıştığından kodum çalışmyor StartCoroutine (Spawn() ) komutunu nerde çağırsam çalışır?

    • yasirkula dedi ki:

      timeLeft’in değeri nerede nasıl değişiyor?

      • Selçuk dedi ki:

        public float timeLeft;
        public GameObject []balls;
        void UpdateText(){
        timeText.text = “Time Left\n” + Mathf.RoundToInt (timeLeft);

        }
        void FixedUpdate(){
        timeLeft -= Time.deltaTime;

        if (timeLeft <= 0)
        Application.LoadLevel (3);

        UpdateText ();

        }
        FixedUpdate 1 azalıyor..

      • yasirkula dedi ki:

        Ben bir sıkıntı göremedim.

  3. Selçuk dedi ki:

    using UnityEngine;
    using UnityEngine.UI;
    using System.Collections;

    public class BonusMap1Gamekontrol : MonoBehaviour {
    float maxWidth;
    public Text timeText;
    public float timeLeft;
    public GameObject []balls;
    void UpdateText(){//güncelleme
    timeText.text = “Time Left\n” + Mathf.RoundToInt (timeLeft);

    }
    void FixedUpdate(){
    timeLeft -= Time.deltaTime;

    if (timeLeft <= 0)
    Application.LoadLevel (3);

    UpdateText ();

    }
    void Start(){
    Vector3 upperCorner = new Vector3 (Screen.width, Screen.height, 0);
    Vector3 targetWidth = Camera.main.ScreenToWorldPoint (upperCorner);
    float ballWidth = balls[0].GetComponent().bounds.extents.x;
    maxWidth = targetWidth.x-ballWidth;

    StartCoroutine (Spawn ());

    UpdateText ();
    }

    IEnumerator Spawn(){

    while (timeLeft>0) {

    Vector3 spawnPosition = new Vector3 (Random.Range (-maxWidth, maxWidth), transform.position.y, 0);
    GameObject ball = balls [Random.Range (0, balls.Length)];
    Instantiate (ball, spawnPosition, Quaternion.identity);
    yield return new WaitForSeconds (Random.Range (0f, 1f));

    }
    }

    }

    Kodun Tamamı bu.Ben timeLeft’in değerini 80 yapıp while içini de (timeLeft > 0) yaptığım zaman kod çalışmıyor.Bunu nasıl çalıştırabilirim?

    • yasirkula dedi ki:

      Dediğim gibi, ben kodda sıkıntı görmüyorum. İsterseniz while’ın içinde Debug.Log(“TEST:”+Time.time) yapın, belki kod zaten düzgün çalışıyordur.

      • Selçuk şener dedi ki:

        Kod şuan zaten düzgün çalışıyor ben while içini değiştirdiğimde çalışmıyor. While içini 0 dan büyük 60 dan küçük şeklinde yaptığımda çalışmıyor.

      • yasirkula dedi ki:

        20 saniye beklediğiniz vakit çalışacaktır.

  4. Aslan dedi ki:

    Merhaba!Ben bir objeyi bir noktadan diger noktaya taşımak istiyorum,ama objeyi haraket ederek taşınsın.Misal uçak bir noktadan uzun bir mesafede yerleşen noktaya ben verdiyim hız ve zamanla gitsin.Şimdiden teşekkürler.

    • yasirkula dedi ki:

      Objenin gitmesi gereken yön: ( hedef.position – transform.position ).normalized

      Bu yönü hız ve Time.deltaTime ile çarpıp Update’te Translate fonksiyonuna parametre olarak atarsanız amacınıza ulaşırsınız.

      • Aslan dedi ki:

        Örnek bir kodla update de yazacağım kodu yazsaydınız tam anlardım

      • yasirkula dedi ki:

        public var hiz : float = 100f;
        public var hedef : Transform;
        private var yon : Vector3;

        function Start() {
        yon = ( hedef.position – transform.position ).normalized;
        }

        function Update() {
        transform.Translate(yon*hiz*Time.deltaTime);
        }

      • Aslan dedi ki:

        Allah razı olsun.Cevapladığınız için teşekkürler!

  5. musa dedi ki:

    yasir bey sizden rica etsem mesela oyunumda skoru 25 yapınca animasyonun çalışmasını istiyorum kodunu rica etsem en kısa halde yazarmısınız

  6. ömer dedi ki:

    Kardeş Bir Sorum Olacak musadenle Oyuna bir pause buttonu koydum tıklayınca oyun duruyor ama tam anlamıyla değil örnek verecek olursam spawn olan objeler Durmuyor Ama Kraktere Temas Edince kodlar çalışmıyor benim istediğim bu spawn olan objelerinde durması bu normal bir durum gibi gelmedi bana daha öncede çalışmalarım oldu unity ile fakat böyle bir sorunla hiç karşılaşmadım Bunun sebebi ne olabilir ?

    • yasirkula dedi ki:

      Time.timeScale’in değeri değişse de Update fonksiyonu çalışmaya devam eder (ancak FixedUpdate çalışmaz). Hareket kodlarınızdaki vektörleri Time.deltaTime ile çarparsanız artık o objeler de pause esnasında hareket etmeyi keser; çünkü oyunu pause edince Time.deltaTime’ın değeri de 0 olur.

    • ömer dedi ki:

      Bir Sorum daha olacak Yorum Düzenleme Buttonu göremediğim için yeni yorum atacam kusuruma bakma. 🙂 Oyun Başlamadan önce 3 saniye beklemesini istiyorum oyunun fakat bu timescale ile mümkünmü veya başka bir yol ile deneme imkanımız varmı ?

  7. Bilal Emre dedi ki:

    Rigitbody nin fizik kodlarını yazarken update değil de fixupdate kullanılmasının nedeni nedir?

    • yasirkula dedi ki:

      Kendim anladığım kadarıyla cevap yazacak olursam: fizikte FixedUpdate kullanımının 2 önemli sebebi var:

      1- Unity PhysX fizik motoru ile sahnedeki fiziği simüle etmeden hemen önce FixedUpdate çağrılmakta. Yani bu fonksiyon Unity’nin fizik motoru ile senkronize bir şekilde çalışmakta.
      2- FixedUpdate fonksiyonu sabit bir gecikme ile çağrılmaya çalışılır (varsayılan olarak 0.02 saniye) ve bu yüzden güçlü cihazlarda iki frame arasındaki süre çok kısa olduğunda Update fonksiyonu birden çok kez çağrılırken FixedUpdate fonksiyonu bir kaç frame geçene kadar hiç çağrılmayabilir. Benzer şekilde, güçsüz cihazlarda da iki frame arasındaki süre uzun olduğunda 0.02 saniyeyi telafi etmek için FixedUpdate fonksiyonu birden çok kez çağrılabilir. Yani o iki frame arasında sahnenizdeki objelere yerçekimi hiç etki etmeyebileceği gibi (güçlü bir cihaz) birden çok kez de etki edebilir (güçsüz bir cihaz). Objenize ileri yönde 10N kuvvet uyguluyorsanız ve iki frame arasında yerçekimi objenize iki kez etki ettiyse (güçsüz bir cihaz) bu iki frame arasında objeye ileri yönde 2*10N=20N kuvvet uygulanmış olması beklenir. Fizik kodunuzu FixedUpdate’e yazdığınızda bu tutarlılığı sağlamış oluyorsunuz.

      • Bilal Emre dedi ki:

        Çok teşekkür ederim çok faydalı oldu. Neyi niye yaptığımı bilince anlaması daha kolay oluyor

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s