Unity Bir Script’ten Başka Bir Script’teki Değişkene Ulaşmak

Yayınlandı: 27 Temmuz 2019 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde

Yeniden merhabalar,

Bu derste, Unity‘de yazdığınız bir C# script’inden başka bir C# script’indeki değişkene ulaşmanın birkaç yolunu göstereceğim:

  • Hedef script’i public bir değişkende tutmak
  • Hedef script’e kod vasıtasıyla ulaşmak
  • Değişkeni static yapmak

Bu konuda sıklıkla soru aldığım için, umarım bu ders akıllardaki bir takım soruları cevaplayacaktır. Hazırsanız derse başlayalım!

Öncelikle, işleri kolaylaştırması adına iki script’e ve ulaşmak istediğimiz değişkene isimler verelim. Ders boyunca, Dusman script’inden Player script’indeki “public Vector3 konum;” değişkenine ulaşmaya çalışacağız. Ulaşmaya çalıştığımız değişkenin ya public olması lazım, ya da o değişkene ulaşmaya yarayan public bir property veya fonksiyonun Player script’inde tanımlı olması lazım. Aksi taktirde bu değişkene ulaşamayız.

Hedef script’i public bir değişkende tutmak

En basit yöntem bu sayılabilir. Dusman script’inde public Player player; değişkeni oluşturun ve Dusman objesinin Inspector’undan Player değişkene değer olarak, Player objesini verin. Artık player.konum şeklinde konum değişkenine ulaşabilirsiniz.

Eğer Dusman script’i bir prefab’da yer alıyorsa ve Player objesi sahnenizde yer alan bir obje ise (yani prefab değilse), Dusman objesinin Player değişkenine Player objesini değer olarak veremezsiniz. Çünkü sahnedeki objeler prefab’ların değişkenlerine değer olarak verilemez. Bu durumda, bahsedeceğim diğer yöntemlere başvurmak zorundasınız.

Hedef script’e kod vasıtasıyla ulaşmak

Oyun esnasında bir objeye veya component’e dinamik olarak erişmek için birkaç fonksiyon mevcut:

GameObject obje = GameObject.Find(“Objenin ismi”): ismi girilen objeyi GameObject olarak döndürür. Aynı isimde birden çok obje varsa, ilk bulunan obje döndürülür. Eğer bu isimde bir obje yoksa null döndürülür

GameObject obje = GameObject.FindWithTag(“Objenin tag’ı”): tag’ı girilen objeyi GameObject olarak döndürür. Aynı tag’e sahip birden çok obje varsa, ilk bulunan obje döndürülür. Eğer bu tag’e sahip bir obje yoksa null döndürülür

Player playerScripti = obje.GetComponent<Player>(): obje’nin Player component’ini döndürür. Eğer objede Player component’i yoksa null döndürülür

Player playerScripti = FindObjectOfType<Player>(): sahnedeki Player component’ine sahip objeyi bulur ve bu objenin Player component’ini döndürür. Eğer birden çok objede Player component’i varsa, ilk bulunan objenin Player component’i döndürülür. Sahnedeki hiçbir objede Player component’i yoksa null döndürülür

Fark edeceğiniz üzere, bu fonksiyonlar vasıtasıyla oyun esnasında sahnedeki herhangi bir objeye dinamik olarak erişebilirsiniz. Ancak bu fonksiyonlar biraz yavaş fonksiyonlardır (özellikle FindObjectOfType ve GameObject.Find), o yüzden bu fonksiyonları Update gibi bir fonksiyonda kullanırsanız bu performans sorunlarına yol açabilir. Onun yerine, ulaşmak istediğiniz objeyi tutacak private bir değişken oluşturup, bu fonksiyonlar yardımıyla Start fonksiyonunda değişkene değerini verebilir ve script’in geri kalanında objeye bu değişken vasıtasıyla ulaşabilirsiniz. Örneğin:

private Player player;

void Start()
{
	// Player objesinin tag'ının Player olması lazım!
	player = GameObject.FindWithTag( "Player" ).GetComponent<Player>();
	
	// veya (daha yavaş)
	player = GameObject.Find( "Player" ).GetComponent<Player>();
	
	// veya (çok daha yavaş)
	player = FindObjectOfType<Player>();
}

void Update()
{
	// Artık değişkene player.konum şeklinde ulaşabiliriz
	Debug.Log( player.konum );
}

Player fonksiyonuna kod vasıtasıyla ulaşmanın daha hızlı bir yolu ise, Player script’ine hızlıca ulaşmaya yarayan bir static değişken oluşturmaktır. Bunun için Player script’inde public static Player instance; şeklinde bir değişken tanımlayıp Awake fonksiyonunda (Awake, Start fonksiyonundan önce çağrılır) instance=this; komutunu çalıştırabilirsiniz:

public static Player instance;

void Awake()
{
	// Player script'i, instance değişkenine değer olarak kendisini (this) veriyor
	instance = this;
}

Bundan böyle Dusman script’inden konum değişkenine Player.instance.konum şeklinde rahatça ulaşabilirsiniz. Bu yöntem, yukarıda bahsettiğim fonksiyonları kullanmaya göre çok daha hızlıdır.

Değişkeni static yapmak

Aslında bu yöntem, bir önceki yöntemde bahsettiğim static instance değişkeni oluşturmakla bayağı benzerdir. Tek fark, static instance değişkeni oluşturmak yerine direkt konum değişkenini static yapmamızdır. Yani public Vector3 konum; değişkenini, public static Vector3 konum; olarak değiştirmek yeterlidir. Artık Dusman script’inden bu değişkene direkt Player.konum şeklinde erişebiliriz.

Bu yöntemin kötü yanı, artık konum değişkenine Inspector’dan değerini veremeyecek olmanızdır çünkü static değişkenler Inspector’da gözükmez. Yani eğer konum değişkenine değerini script’inizden veriyorsanız bu yöntem idealken, konum değişkenine Inspector’dan değer veriyor idiyseniz bu yöntem yerine bir önceki static instance değişkenli yöntemi tercih etmelisiniz.

Bu yöntemle ilgili bilmeniz gereken bir başka husus ise, static değişkenlerin varsayılan değerlerini yalnızca bir kere aldıklarıdır. Bir örnek ile biraz daha açayım: diyelim ki ulaşmak istediğiniz değişken public int skor; (veya public int skor = 0;) olsun. Burada skor değişkeninin varsayılan değeri 0’dır. Bu değişkene sahip script’in olduğu obje her yok olup yeniden oluştuğunda, skor‘un değeri tekrar varsayılan değer olan 0’a döner. Ancak siz bu değişkeni public static int skor; şeklinde static yaparsanız, değişkene ilk kez ulaşırken değişken yine 0 döndürürken, değişkene sahip script’in olduğu obje yok olup yeniden oluştuğunda skor‘un değeri sıfırlanmaz, en son değeri neyse o şekilde kalır. Yani mesela level bitti, ana menüye dönüş yapıldı ve ardından level tekrar başlatıldı diyelim. Bu durumda normalde skorun sıfırlanması beklenirken, en son level’da skor ne idiyse değeri o şekilde devam eder. Her level başında skor’un değeri sıfırlansın isterseniz, skor’un olduğu script’in Awake fonksiyonunda skor = 0; şeklinde değeri elle sıfırlamanız gereklidir.

Böylelikle bu dersin de sonuna geldik, sonraki derslerde görüşmek dileğiyle!

yorum
  1. semin dedi ki:

    Hocam ben endless runner tarzı bir oyun yapmayı deniyorum. Altın prefabının scripti içinden prefab halinde olmayan sahnedeki bir nesnenin child objelerine ulaşmak istiyorum ama kod çalışmıyor.Neden olabilir?

    • yasirkula dedi ki:

      Dediğiniz gibi, prefab’dan sahnedeki objelere doğrudan (Inspector’dan referans vererek) ulaşamazsınız. Bu derste bahsettiğim yöntemleri denediğinizi varsayıyorum. Örneğin hangi yöntem çalışması gerekirken çalışmadı?

  2. MR. Sızz dedi ki:

    Selamun Aleyküm hocam. Build almada sıkıntı yaşıyorum. Telefonum pc’ye bağlı olmadığında telefonu bağlayın hatası alıyorum. Build yaparken telefonumun pc’ye bağlı kalması gerekli mi? Yoksa ayarlardan yapmam gereken bir değişiklik var mı?

  3. Burak Doğan dedi ki:

    Yasir Bey merhabalar öncelikle eğer vaktiniz olursa bir soru sormak istiyorum.Blok kırma oyunu yapmaktayım başlangıç seviyesindeyim hem unity olsun hem c# da.Sorum şu oyuna güçlendirici ekliyorum top ona çarptığında bütün blokların içinden geçerek onları destro edecek.Sorum şu güçlendiriciye çarpma gerçekleştiğinde diğer bloklar(prefabdan çekildi) hepsinin isTrigger ını nası aktif edebilirim
    Yardımcı olursanız minnetar olurumçİyi çalışmalar

    • yasirkula dedi ki:

      Bunun için tüm blokları bir listede tutmanız lazım:

      public static readonly List<Blok> Bloklar = new List<Blok>( 256 );
      void OnEnable() { Bloklar.Add( this ); }
      void OnDisable() { Bloklar.Remove( this ); }

      Ardından Blok.Bloklar şeklinde bu listeye erişebilirsiniz.

      • sifirdanjava dedi ki:

        Çok teşekkür ederim Yasin Bey ilginiz,alakanız ve yardımınız için.

  4. Emre dedi ki:

    Merhaba hocam.Tavsiyenize ihtiyacım var. Bir sahnedeki tuşa bastığımda başka bir sahnedeki gameobject’i aktifliğini değiştirmek istiyorum(görünüp görünmemesi için renk alfasını değiştirmesi de olabilir) bunu Scriptler arası transfer ile yapmaya çalıştım.Ulaşmak istediğim gameobjectin olduğu sahneye script yazıp serializedfield yardımı ile sahneden ekleme yapmayı denedim, FindObject i denedim, static yapmayı denedim. Fakat diğer sahneden tuşa bastığımda Null reference hatası alıyorum. Toparlayacak olursam bir sahneden başka sahnede ki gameobjecte nasıl erişebilirim?

    • yasirkula dedi ki:

      Mevcut sahneler haricindeki sahnelerde yer alan objelere erişemezsiniz. Aklıma gelen en kolay çözüm yolu static bir değişken kullanmak ve diğer sahnedeki objenin Awake’inde, bu static değişken true ise objeyi gizlemek.

      • Emre dedi ki:

        Hocam ilgilendiğiniz için teşekkürler. Dediğinizi denedim yanlış yapmadıysam o da olmadı(Null reference veriyor). Benim amacım aslında market sahnesinden satın alınan bir şeyin eşyalar sahnesinde gözükmesi ama beceremedim. En son Coroutine yapmayı denedim satın alınca 2 saniye sonra eşyalar sahnesine gidiyor, 1 saniye sonrada deaktif olan eşyayı aktif ediyor. Bu işlemi yapan scriptide singleton objenin içine attım, sonra aktif olunacak nesneyi scriptten Gameobject.Find yaptım ama null reference verdi yine. Resources diye bir olay varmış onu araştırıyorum belki o çözüm olabilir.

      • yasirkula dedi ki:

        public static bool bir değişkenin değerini değiştirmek veya bu değişkene erişmek asla null hatası vermez. Markette A eşyasını satın alınca, Market script’indeki “public static bool aEsyasiSatinAlindi;” değişkenini true yapıp, eşyalar sahnesinin Awake’inde ise bu değişkenin değeri true ise ilgili eşyayı aktif hale getireceksiniz sadece.

      • Emre dedi ki:

        Hocam çok teşekkürler. Bugün zihnim biraz kapalı idi , ilk cevabınızda da demişsiniz ama ben ısrarla bool yerine gameobjecte ulaşmaya çalışmışım.Neyse tecrübe kazandım diyelim. Zaman ayırdığınız için teşekkürler tekrardan.

  5. Arif Cem Selçuk dedi ki:

    Merhaba,

    Level1Boss isimli karaktere ait Level1BossManager scripti var ve ben bu karakteri BossSpawner isimli scriptten Level1Boss adında spawn ediyorum. Level1BossManager de health sistemi tanımlı. BossSpawner dan health 0 a yada daha düşük bir değere düştüğü anda destroy işlemi gerçekleştirmek istiyorum. Bunun için Level1BossManager de public static Level1BossManager instance ve awake fonksiyonları da tanımlı. BossSpawner da if(Level1BossManager.instance.health<=0){destroy(Level1Boss)} yazdığımda hiç destroy olmuyor debug.log alıyorum consolda da hiçbirsey olmuyor. Sorun nerededir? Teşekkürler

    • yasirkula dedi ki:

      Destroy(Level1Boss.gameObject) işe yarıyor mu?

      • Arif Cem Selçuk dedi ki:

        Çok teşekkür ederim. Start’a yazıyormuşum update alınca düzeldi şimdi fakat şimdi de if(Level1BossManager.instance.health<=0) için NullReferenceException: Object reference not set to an instance of an object hatası veriyor. Bunu nasıl düzeltebilirim?

        Birde health'in 0' a eşit yada 0'ın altına düştüğü anın kontrolü için update kullanıyorum ve bu sürekli çalışan ve sistemi yorucu bir durum oluyor. Time.timescale =0 durumunda bile çalışıyor bu kontrol. Bunun yerine health değişkeninin durumu kontrol edebileceğim bir metod var mıdır?

        teşekkür ederim.

      • yasirkula dedi ki:

        Boss objesini yok ettiğinizde Level1BossManager.instance null oluyorsa haliyle NullReferenceException alırsınız. if(Level1BossManager.instance) şeklinde, instance’ın null olup olmadığına bakmanız lazım. Sadece health değiştiğinde bir kod çalıştırmak için health’i property yapıp set fonksiyonunda istediğiniz kodu çalıştırmanızı öneririm.

      • Arif Cem Selçuk dedi ki:

        Yasir Bey gerçekten çok teşekkür ederim inceliyorum propertyleri. Kendi kodlarıma ve oyunuma göre kodlara nasıl dökebileceğimi araştırmaya çalışıyorum. Şimdi doğru mu anlamışım, bölüm sonu çıkan boss u öldürdükten sonra boss yok olacak, Level Complete UI açılacak ve sonra zaman sıfırlanacak. Bu işlemeleri sırasıyla yaptığım da haliyle gameobject destroy olduğu için geri kalan işlemleri yapmak için başka bir sciptten health sıfırın altına düşüp düşmediğini sürekli kontrol etmem gerek. İşte bu sürekli kontrol etmek için update fonksiyonu kullanmak yerine propertileri kullanıyoruz. Doğru mu anlamışım ve bu işlemler için tavsiye edeceğiniz daha kısa bir yöntem var mıdır? Biraz uzun yazdım lütfen kusura bakmayın.

      • yasirkula dedi ki:

        Evet burada Update yerine property kullanabilirsiniz. Başka bir scriptten canı kontrol etmenin bir alternatifi ise, boss’ta bir event/UnityEvent bulundurmak ve can propert’sinde değer 0’ın altına inerse bu event’i çağırmak. Boss’un öldüğünü hangi script’lerin bilmesi gerekiyorsa, o script’lerin levelin başında bu event’e kaydolmaları lazım.

  6. MuffinTime dedi ki:

    cevap geleceğini sanmıyorum ama aradığım cevabı bulamadım şunun kodlamaya çevrilmiş hali nedir
    public class a scripti : Monobehaviour

    // a scripti ile b scriptindeki true olan bool değişkenini false yapmak istiyorum
    // şunun kodlamaya çevrilmiş hali nedir
    b_scripti.bool = false
    // bunu nasıl yazabilirim

    • yasirkula dedi ki:

      Bu dersi zaten bunun için yazdım dersi okudunuz mu?

    • Mr. P0TAT0 dedi ki:

      sana basit bir şekilde anlatayım

      diyelim ki nesne adlı bir gameobject var door adlı bir component ve isLocked diye bir değişken var başka bir gameobjectteki scriptten islockedi değiştirmek istiyorsan mesela anahtarın scriptinden

      GameObject.Find(“gameobject”).GetComponent<door>().isLocked = false;

      şeklinde yazıp

  7. lifegames52 dedi ki:

    Hocam öncelikle çok teşekkürler çok faydalı konulara değiniyorsunuz sormak istediğim birşey var kodlara yeni aşina oluyorum uygulama içi satın alma yapacağım youtube de bir video izledim arkadaş kodlarıda paylaşmış link paylaşmak yasakmı bilmiyorum ama dilerseniz bana mailde gönderebilrisiniz şimdi hocam burada satın alım başarılı oluyor tamam ama ben satın alım gerçekleştik den sonra Text e yazmasını yani göstermesini istiyorum birtürlü yapamadım 100 altın aldım butona tıkladım bunu Text de göstereceğim Video Link: https://www.youtube.com/watch?v=RchTCScO3MU

    • yasirkula dedi ki:

      public Text değişkende Text’i tutun. Altın satın alma başarılı olunca bunu SetActive(true) ile görünür yapın. Birkaç saniye sonra isterseniz SetActive(false) ile tekrar görünmez yapın. Birkaç saniye beklemek için coroutine kullanabilirsiniz.

  8. Enes Durmus dedi ki:

    İyi günler ben bir Npc(görev alma) scripti yazıyorum tek sctirpti farklı karakterlere atarak textlerini görevi kabul edip etmediklerini inceptor üzerinden ayarlayabiliyorum fakat her karakter farklı görev vermeli o yüzden benim “public Script sciptIsmi ” gibi bir komuta ihtiyacım var lakin ne kadar araştırsam da buna benzer bir yöntem bulamadım kısaca aynı scriptle farklı scriptlere yönlendirme yapabilir miyim yoksa her npc için aynı kod yazmak zorunda kalacağım 😦

  9. Furkan dedi ki:

    Hocam yazdığım kod çalışmıyor hata nerde bulamadım oyuna altın sistemi eklemeye çalışıyorum altına goldtemas adında bir script ekledim
    {
    gold gos;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
    if(collision.gameObject.tag == “Player”)
    {
    gos.GetComponent().abc();
    Destroy(gameObject);

    }
    }

    }
    sahnedeki boş bir objeye ise gold adında bir script ekledim oda şöyle
    {
    public int gol;

    [SerializeField]
    Text goll = default;

    // Start is called before the first frame update
    void Start()
    {
    goldGoster();
    }

    // Update is called once per frame
    void Update()
    {

    }

    void goldGoster()
    {
    goll.text = “Gold: ” + gol;
    }

    public void abc()
    {
    gol += 5;
    goldGoster();
    }
    }
    karakter altına temas edince gol +5 değer kazanması ve altının yok olması lzm fakat olmuyor sizce hata nerede olabilir?

    • Furkan dedi ki:

      Hocam goldtemas scriptinde gos.GetComponent().abc(); şeklinde yazılı kopyalarken orayı almamış farklı şekilde start fonksiyonuna gos = GetComponent(); olarak yazıp trigger kısmınada gos.abc(); olarak da denedim iki türlüde gold scriptindeki abc fonksiyonunu çalıştıramadım.

    • yasirkula dedi ki:

      OnTriggerEnter2D çalışmıyor olabilir. Bu gibi durumlarda, altın artana kadar çalışan tüm satırlara Debug.Log koyup hangi satırda log’ların kesildiğine bakabilirsiniz.

      • Furkan dedi ki:

        Hocam OnTriggerEnter2D çalışıyor sadece destroy varken altın yok oluyor temas edince fakat abc() yi eklediğim zaman ikiside çalışmıyor

      • Furkan dedi ki:

        Yani hocam demek istediğim OnTriggerEnter2D destroy(gameObject) varken çalışıyor fakat ne zaman abc(); yi eklersem çalışmayı kesiyor

      • yasirkula dedi ki:

        Konsolda bir hata yoksa bunun sebebini bilemedim.

      • Furkan dedi ki:

        Teşekkür ederim hocam yine de

      • Furkan dedi ki:

        Aynı sıkıntıyı yaşayan olursa sorunu çözdüm buraya yazıyorum
        gos = GetComponent(); yerine gos = (gold)FindObjectOfType(typeof(gold)); yazdım sorun çözüldü

  10. Barış dedi ki:

    Benim amacım değişkene ulaşmak değil mesela şunu istiyorum; a ya basınca Player daki PlayerController scriptindeki ienumerator u StartCoroutine ile çaıştırmak istiyorum ama a ya basmayı algılayan kod başka kodda. Bir türlü yapamadım. Veya şu da olabilir
    void CoroutineBaslatici() olur bunu çalıştırırım ve bu şekilde bu kodun içine StartCoroutine koyarım öyle çalıştırırım. Ama başka kodun ne void () ine ne de ienumerator una erişemedim.

    • yasirkula dedi ki:

      Değişkene ulaşmakla fonksiyona ulaşmak arasında önemli bir fark yok. Diyelim değişkene GetComponent<Player>().asd diye ulaşıyorsanız, fonksiyona GetComponent<Player>().Asd() şeklinde ulaşabilirsiniz. Ya da değişkene Player.asd diye erişiyorsanız, fonksiyona Player.Asd() diye erişebilirsiniz.

  11. serhat ak dedi ki:

    hocam vallahi bu msjı görürmüsünüz bilmem ama inş görürüsünüz başka bir c# dosyasındaki metodu nasıl çalıştırabilirim

    • yasirkula dedi ki:

      Derste bahsettiğim yöntemlerle public fonksiyonlara da erişebilirsiniz. Örneğin player.konum yerine player.BirFonksiyon() yazabilirsiniz.

  12. birol dedi ki:

    Yasir Hocam Konu ile pek alakalı değil fakat bir sorum olacaktı bakarsanız sevinirim,

    Instantiated ile prefab obje yapıyorum fakat bu obje orignal game obje gibi snap pointe gittiginde snappointe yapışmıyor. prefab ile original gameobje aynı ozelliklerde olması gerekmezmi,

    • yasirkula dedi ki:

      Aynı özelliklere sahip olması gerekir. Belki siz snap kısmında if(snapEdilenObje==prefabObje) gibi bir kod çalıştırıyorsunuzdur, prefab obje ile ondan Instantiate ile türeyen obje farkı nesneler olduğu için, bu kod Instantiate edilmiş objede false döndürür.

      • birol dedi ki:

        yasir hocam script aşağıdaki linkteki gibi. eklemem gereken birşeymi var acaba plate objesi içinde mi snap scripti yazmam lazım? target objesini tekrardan oluşturmuyor mu initiate code .tşk.
        https://hatebin.com/etmtcuufvm

      • yasirkula dedi ki:

        Prefab’ı Instantiate ettikten sonra, Instantite’in döndürdüğü objeyi target’a değer olarak vermeniz lazım gibi duruyor.

  13. djv45 dedi ki:

    hocam benim animasyonlarla ilgili bir sıkıntım var. konu ile alakasız ama yardımcı olursan sevinirim.

    bir animasyon oluşturdum ve animasyonu eklediğim image öğesinin fillAmount değeri 1f olduğunda bu animasyonun çalışmasını istiyorum. ekrandaki butonlara basınca bu image öğesinin fillAmount değeri artmaya başlıyor. fillAmount değeri 1 olduğunda animasyon ilk kez çalışıyor (animator.enabled=true ile componenti açıyorum) ve sonlanıyor (sonlanınca Invoke ile 1f saniye sonra animator.enabled = false oluyor). Ardından . bu arada script üzerinden de fillAmount’un değeri tekrardan 0 oluyor. Tekrar ekrandaki butonlara basılıyor ve zaman içerisinde fillAmount değeri yeniden 1 oluyor fakat bu sefer animasyon çalışmıyor, sadece script üzerinden fillAmount değeri hemen 0 a düşüyor.

    bunu nasıl çözebilirim acaba ? şimdiden teşekkürler 🙂

    • djv45 dedi ki:

      Sorunumu çözdüm. Ben animasyonu da fillAmount değerini sıfırlamayı da aynı obje üzerinden yapıyordum. Sanırım o yüzden ilk seferde çalışıp, sonrakilerde çalışmıyordu.

      bunu iptal ettim ve objeyi duplicate edip, animasyonu duplicate olan objede oluşturdum. Kopya olan objenin içerisine bir script yazarak ObjeyiKapat adlı bir method yazdım ve içerisinde gameobject.setactive(false) yazdım. Daha sonra start methodundan önce OnEnable() methodu yazdım ve içerisine Invoke(“ObjeyiKapat”, 1f); yazdım.

      Diğer script üzerinde de public gameobject ile kopya objeye eriştim. Scriptte fillAmount değeri 1f olunca klon objenin SetActive özelliğini true yaptım. Böylece animasyon fillAmount değeri her 1f olduğunda tekrar çalıştı.

      3 gündür çeşit çeşit yöntemler deneyip sonuca ulaşınca insan seviniyor 🙂

  14. birol dedi ki:

    Merhaba,
    konuyla yakından alakalı olmayabilir..benim sorum
    Bir obje baska bir obje tarafından kullanıldıgında kullanılan objeye “Flag” veya “kullanıldı” gibi bir ozellik atamak istiyorum ki bir daha başka bir obje tarafından kullanılmasın ustuste objeler kullanaılabilir olmasın diye.. bunu nasıl yaparım Yasir bey

    şöyle bir kod buldum ama.. manage diye bir şey yaratılamıyor..

    public Managed[] managedObjects;
    void Start()
    {
    // Find them if not set already in the editor
    this.managedObjects = FindObjectsOfType(typeof(Managed)) as Managed[];
    }
    void Update()
    {
    foreach (Managed managed in this.managedObjects)
    {
    if (managed)
    {
    // do something
    }
    }
    }
    }

    • yasirkula dedi ki:

      Eğer objelerin tag’leri ile bir işlem yapmıyorsanız, kullanılan objelerin gameObject.tag değerini örneğin “Finish” yapabilirsiniz. Daha sonra da obje kullanılmış mı kontrol etmek için obje.CompareTag("Finish") fonksiyonunu çağırabilirsiniz. Aksi taktirde, kullanılan objeleri “List<GameObject>” veya “HashSet<GameObject>” türünde bir değişkende tutabilirsiniz. Alternatif olarak, KullanilanObje adında yeni bir script oluşturup bunu gameObject.AddComponent<KullanilanObje>() ile kullanılan objelere verebilirsiniz. Obje kullanılmış mı kontrol etmek için de obje.GetComponent<KullanilanObje>() != null sorgusu yapabilirsiniz.

  15. mehmet dedi ki:

    List oluşturdum değer atadım ve sıfırıncı elemente ulaşmak istediğim zaman bu hatayı veriyor.(ulaşmak isteğim değer static)

    cannot be accessed with an instance reference; qualify it with a type name instead

    • yasirkula dedi ki:

      Değişken A script’indeyse ve adı b ise, değişkene A.b diye erişin. İlk elemana erişmek için: A.b[0]

      • Mehmet dedi ki:

        List oluşturdum ve sahneden oyun nesneleri listeye ekledim sıfırıncı elemente erişmek istiyorum. Oyun nesnesindeki a scriptin static değişkene nasıl erişebilir.

      • yasirkula dedi ki:

        Static değişkene bahsettiğim gibi ClassIsmi.degiskenIsmi şeklinde erişilir. Hâlâ sıkıntı yaşıyorsanız “c# static değişkenler” şeklinde google araması yaparak oradaki derslere bakmanızı öneririm.

  16. anilcan dedi ki:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class SkeletonAI : MonoBehaviour
    {

    private GameObject player;

    void Start ()
    {
    player= GameObject.FindWithTag(“Player”).GetComponent();
    }

    void Update ()
    {
    transform.LookAt(player.transform);

    if(Vector3.Distance(player.transform.position, this.transform.position)<10)
    {
    Vector3 direction=player.transform.position-this.transform.position;
    this.transform.rotation=Quaternion.Slerp(this.transform.rotation,
    Quaternion.LookRotation(direction),0.1f);
    }

    }

    }
    burada playerin transformunu takip ettiremiyorum yardımcı olurmusunuz.

    • yasirkula dedi ki:

      this.transform.rotation yapmak yerine (aynı şeyi zaten LookAt fonksiyonu ile yapıyorsunuz) “transform.Translate(new Vector3(0,0,5*Time.deltaTime);” satırı ile saniyede 5 metre hızla player’a doğru hareket edebilirsiniz.

  17. Murat dedi ki:

    Hocam merahab
    2 sahnem var ilk sahnemde köşede highscore yazdıracagım ikinci sahnemde oyunum mevcut
    ilk sahneme public Text oluşturyorum UI panelden text olusturup ekliyorum ınspectorden atıyorum high score yazılıyor sorun yok sorun surada oluşuyor ikinci sahne bu text game objecti olmadığı için nesneyi bulamıyor ilk ekrana döndüğümde haliyle highsocre bulamadığ için ekrana basımıyor. Bunu inpectorden değilde sciript ile nasıl atama yapabilirim

  18. kareka17 dedi ki:

    Kolay gelsin,
    Hocam ben 3D Mobil proje üzerinde uğraşıyorum asset store dan hazır sahne aldığım zaman hiçbir kasma olmadan çok akıcı oynayabiliyorum. Ama kendim o free objeleri kullanıp sahne tasarladığımda çok takılma oluyor. Hatta aynı objeleri bile kullansam kasıyor ama o demo sahneyi kullandığımda çok akıcı bir şekilde oynanıyor. Render ayarlarıyla alakalı bir tavsiyeniz var mı? Nasıl düzeltebilirim bu durumu? Demo sahnenin objelerinin aynısını bir kare evin içine koysam bile kasma oluyor çünkü

    • yasirkula dedi ki:

      Kameranın ayarlarına, sahnedeki ışık sayısına ve Window-Lighting Settings’deki ayarlara da bakın. İki sahne arasında bunlar farklılık gösteriyor olabilir. Mümkünse Skybox kullanmayın, gölgeleri kapatın ve ışık sayısına minimuma indirgeyin.

  19. kareka17 dedi ki:

    Kolay Gelsin,
    Editör ekranında objeleri hareket ettirirken mesela iki tane küpü nasıl üst üste getirebiliriz. x,y ve z ayarlarıyla ayarlamak zamanı çok alıyor. Bir videoda gördüm ancak kısayol tuşunu bilmediğim için soruyorum. Adam kısayol tuşuna basıp objeyi köşesinden tutuyor ve direkt üst üste biniyor yani x,y ve z ile manuel uğraşmıyor. Yardımın için teşekkür ederim.

  20. kareka17 dedi ki:

    Merhaba Süleyman Bey,
    Oyunumda butona tıkladığımda belirli bir obje bulunduğu konumdan 20 birim yer değiştiriyor ve tekrar tıkladığımda aynı yerine geliyor. Bunu:
    transform.positiyon=new vector3(…) yöntemi ile yaptım. Bu yer değiştirmeyi bir anda değilde zamana bölerek yani obje bir güç tarafından o noktaya itiyormuş gibi nasıl yaparım. Yapmak istediğim obje direkt olarak 20 birim kaymak yerine saniyeler içinde gidecek.

  21. kareka17 dedi ki:

    Kolay gelsin Süleyman Bey,
    Mesela sahnemde aynı componenti kullanan 3 tane obje var. Her obje kendi üzerine tıklandığında hareket ediyor vs. Ben kod ile bu 3 objenin aynı anda componentine ulaşabilir miyim? Yani şöyle açıklayayım; Objelerin içerisinde bir bool değişkenim var bu true olduğunda sola doğru gidiyorlar false olduğunda sağa doğru. Kod ile bunların 1 tanesi hariç hepsini istediğim şekilde (true/false) tanımlayabilir miyim? Teşekkür ederim..

    • yasirkula dedi ki:

      Script’inizde 3 tane public değişken tanımlayıp bu 3 objeyi Inspector’dan değişkenlere değer olarak verin derim. Eğer 3 obje oyun esnasında spawn oluyorsa veya başka bir durum varsa onu belirtirseniz alternatif bir çözüm yolu düşünebiliriz.

      • kareka17 dedi ki:

        3 tane değişken olayı amacıma ulaşmamı sağlıyor ancak her seferinde 3 obje olması gerekiyor. Benim bir bölümde 3 bir bölümde 10 tane objem oluyor bunu dinamik yapabilmem için bir tavsiyeniz var mı?

      • yasirkula dedi ki:

        Bir array (mesela GameObject[]) veya list (mesela List<GameObject>) değişken kullanabilirsiniz. Bu değişkene Inspector’dan istediğiniz kadar objeyi değer olarak verebilirsiniz.

  22. Emrullah Ertaş dedi ki:

    merhabalar hocam, böyle bir sorun ile karşı karşıyayım. https://youtu.be/i45ikEs9qBo

    8 saniyelik video.
    Video da gördüğünüz gibi adobe animate ve adobe after da hiçbir sıkıntı yok. Ama unity de titreşimli oluyor. Acaba adobe animate üzerinden farklı format ilemi render almam gerekiyor? Yardımcı olursanız çok sevinirim video 8 saniye fark çok anlaşılıyor karşılaştırma yaptım teşekkürler şimdiden.

  23. kareka17 dedi ki:

    İyi Günler Süleyman Bey,
    Acaba elinizde kamera ile ilgili bir script var mı?
    Android oyun yapmaya çalışıyorum 3D şeklinde ve karakterimin kamerasını sağa sola çevirmek için bir scripte ihtiyacım var yani ekranda elimizi kaydırarak kameranın açısını/karakterin yönünü değiştirmem lazım. Yardımlarınızı bekliyorum kolay gelsin..

    • yasirkula dedi ki:

      Şu script ile kameranın hedefi yumuşak bir şekilde takip etmesini sağlayabilirsiniz:

      using UnityEngine;
      
      public class KameraTakip : MonoBehaviour
      {
      	public Transform hedef;
      	public Vector3 kameraUzaklik = new Vector3( 0f, 3f, -5f );
      
      	public float kameraHareketHizi = 10f;
      	public float kameraDonmeHizi = 10f;
      
      	// Karakter fizik ile FixedUpdate içerisinde hareket ediyorsa, burada da LateUpdate yerine FixedUpdate kullan
      	private void LateUpdate()
      	{
      		// Kameranın olması gerektiği noktayı bul
      		Vector3 kameraKonum = hedef.position + new Vector3( 0f, kameraUzaklik.y, 0f );
      
      		if( kameraKonum.z != 0f )
      		{
      			Vector3 ileriYon = hedef.forward;
      			ileriYon.y = 0f;
      			ileriYon.Normalize();
      
      			kameraKonum += ileriYon * kameraUzaklik.z;
      		}
      
      		if( kameraUzaklik.x != 0f )
      		{
      			Vector3 sagYon = hedef.right;
      			sagYon.y = 0f;
      			sagYon.Normalize();
      
      			kameraKonum += sagYon * kameraUzaklik.x;
      		}
      
      		// Kamerayı hedef noktaya yumuşak bir şekilde (Lerp) yaklaştır
      		Vector3 yeniKonum = Vector3.Lerp( transform.position, kameraKonum, Time.deltaTime * kameraHareketHizi );
      		transform.position = yeniKonum;
      
      		// Kamerayı hedef eğime yumuşak bir şekilde döndür
      		Quaternion egim = Quaternion.LookRotation( hedef.position - yeniKonum );
      		transform.rotation = Quaternion.Lerp( transform.rotation, egim, Time.deltaTime * kameraDonmeHizi );
      	}
      }
      
  24. Levent dedi ki:

    Yasir bey
    Unity android için yaptığım oyunda karakter titriyor( yalpalanıyor ) ve nesnelerin kaplamaları yarılıyor.
    oyun fps si ortalama 80 fps nasıl dzeltebilirim yardımcı olurmusun . Teşekkurler

    • yasirkula dedi ki:

      Eğer kamera hareket ederken karakter titriyorsa belki titreyen şey kameradır. Karakteri Update’te hareket ettiriyorsanız kamerayı LateUpdate’te, karakteri FixedUpdate’te hareket ettiriyorsanız kamerayı da FixedUpdate’te hareket ettirin. Kaplamaların yarılmasını örnek bir resimle gösterebilir misiniz?

      • Levent dedi ki:

        Yasir bey
        Kamerayı karakterin içine attım .

      • yasirkula dedi ki:

        Karakterin hareket script’inde bir sıkıntı vardır tahminimce. Script’in tüm alakasız kısımlarını silip script’i burada paylaşırsanız inceleyebilirim.

  25. Eren dedi ki:

    Merhaba, ben bir prefab’dan canvas içindeki imageyi SetActive(true) yapacağım. Önce public olarak bir GameObje değişken tanımlıyorum oradan prefab içindeki scripe sürüklemem lazım fakat hierarhcy panelinde sadece prefab gözüküyor. Ben bu prefab dan nasıl imageyi setActive yapacağım? teşekkürler 🙂

    • yasirkula dedi ki:

      Bu durumda yazıda bahsettiğim “Hedef script’e kod vasıtasıyla ulaşmak” yöntemini kullanmanız lazım. Ben olsam oradaki “static instance” değişkenli yolu kullanırdım.

      • Faruk dedi ki:

        public Canvas canvasb;
        canvasb = GameObject.FindGameObjectWithTag(“Canvas”).GetComponent();

        bu kodu denediğimde NullReferenceException bu hatayı alıyorum

      • yasirkula dedi ki:

        Kodu çalıştırdığınız esnada sahnede Canvas tag’ına sahip bir obje bulunamadı diyor. Objenin isminin değil tag’ının Canvas olduğundan ve objenin o anda inaktif değil aktif olduğundan emin olun.

  26. Faruk dedi ki:

    hocam bir scripten başka bir scripte getcomponet ile ekliyorum sonra hareket.bullet = true diyorum ve nullreferanceexeption hatası alıyorm nasıl çözerim

    • yasirkula dedi ki:

      GetComponent’i çağırdığınız esnada objede o component henüz yokmuş olabilir. Ama daha büyük bir olasılıkla, GetComponent ile değişkene attığınız component’e sahip obje yok olmuştur (Destroy ile veya sahneler arası geçiş esnasında) ve bu yüzden hata alıyorsunuzdur.

  27. Drunkeinstein dedi ki:

    Hocam sizin yazıları Ali kaya denilen şahış izinsiz olarak kendi blogunda yayınlıyor ve Yazar olarak kendi adını yazıyor. https://alikaya.info/unity3d-ogrenimi-ders-3-2017/ buyurun link bu diğer derslerine bakmadım ama vardır büyük ihtimalle.

  28. kareka17 dedi ki:

    Kolay gelsin hocam,
    Sayfanı beğenerek takip ediyorum ve başarılarının devamını diliyorum. Konu ile alakalı değil ama internet üzerinde bulamadığım bir sorunun cevabını sormak istiyorum belki yanlış araştırdığım için bulamadım bilmiyorum ama yardımcı olabilirsen minnettar olurum.
    Hocam, ana sayfamda; başlat, ayarlar ve oyundan çık butonu var. Bu butonların anchorlarını ayarlayarak sayfaya göre şekillenmesini sağladım. Ancak içlerinde bulunan yazılar sayfa büyüyünce çok küçük oluyor ve okunmuyor. Buton boyutlarında sorun yok sayfaya göre şekilleniyor ama içerisindeki yazının fontunu sayfaya göre bir türlü ayarlayamadım. Yardımını bekliyorum, saygılar..

    • yasirkula dedi ki:

      İlk önerim Canvas objenizin Canvas Scaler’ının Scale Mode’u ile oynamanız. Gerekirse de yazının “Best Fit” ayarını açarak dinamik olarak boyutunun değişmesini sağlayabilirsiniz.

  29. Arda dedi ki:

    başka bir scriptden başka bir objenin ontriggerenter2d sini nasıl kullanabilirim

    • yasirkula dedi ki:

      O fonksiyonu public yapıp, dersteki değişkene ulaşma yöntemlerinin aynısını uygulayarak fonksiyona ulaşabilirsiniz (yani A script’inin b değişkenine A.b ile erişecek idiyseniz, onun yerine istediğiniz fonksiyona A.OnTriggerEnter2D(…) ile erişebilirsiniz).

  30. Yasin Çakıcı dedi ki:

    Tek bir hedefim var oda mobil oyun için, ama bir türlü c# dilinin mantığını kavrayamadım.
    elinizde varmıdır bir ders veya kaynak?

    Yani demek istediğim C# dilini (mantığını) hiçbir bilgisi olmayan birine nasıl anlatabilirsiniz?

    bu soruya cevap 🙂

    • yasirkula dedi ki:

      Benim önerim C#’ın temellerini Unity’den bağımsız olarak öğrenmeniz çünkü Unity ile C# programlamaya başlamak konusunda Türkçe çok iyi kaynak bulmakta belki zorlanırsınız ama “c# giriş dersleri -visual” diye arama yaparsanız, Türkçe ve kaliteli C# başlangıç dersleri bulabilirsiniz. Bu dersler ile C# ile programlamanın temelini iyice kavradığınıza inandıktan sonra Unity’e geçiş yapabilirsiniz.

      Sadece şuna dikkat edin: C# ile konsol tabanlı ve pencere tabanlı (visual) uygulamalar yapılabilir, siz başlangıç seviyesinde olduğunuz için konsol tabanlı derslere bakın, visual C# yazan derslere hiç bakmayın. Zaten temeli kaptıktan sonra görsel kısmı Visual C# ile değil Unity’de C# kullanarak yapacaksınız. Konsol tabanlı derslerin kodlarında Console.WriteLine gibi satırlar görürsünüz.

  31. ali dedi ki:

    Hocam scripti çağırıyorum çağırdığım scriptten public olmasına rağmen değişkenlere de metotlarada ulaşamıyorum. Sizce sorun ne olabilir ?

    • yasirkula dedi ki:

      Değişkenlere ulaşmaya çalıştığınızda aldığınız hata mesajı nedir?

      • ali dedi ki:

        Tanımlandı ancak kullanılmadı gibi bir hata ve değişkenlerim static

      • yasirkula dedi ki:

        Script’i nasıl çağırdığınızı ve çağırdığınız script’teki public değişkene nasıl ulaşmaya çalıştığınızı görebilir miyim?

    • ali dedi ki:

      Yardımcı olmaya çalıştığınız için teşekkür ederim benim statik değişken olduğu için player.staticdeger şeklinde çağırdım hallettim 🙂

  32. Kerem Güneş dedi ki:

    Öncelikle merhaba hocam benimde bir sorum olucaktı Unity 3d ile bir oyun geliştiriyorum bu oyununda başlangıçta eğer daha önceden takım olusturulmadiysa takım oluştur sayfasına geçicek daha önceden takım olusturduysa direk ana menüye geçicek birde takım oluşturduğunda takımın logosu adı felan bunları nasıl ana menüde gösterebilirim bunun ile ilgili bir yazınız varsa linkini atabilirmisiniz yada dili farketmez bir ders varsa atarsanız çok sevinirim ne zamandır googlda arıyorum bir türlü bulamıyorum nasıl arayacagimi da bilemiyorum 😊 bu konuda yardimci olursaniz cok sevinirim.

    • yasirkula dedi ki:

      Kendiniz araştırırken “unity persist data” şeklinde arayabilirsiniz. Unity oyunlarında veri kaydetmenin en kolay yolu PlayerPrefs’tir. PlayerPrefs ile kaydettiğiniz veriler oyun kapansa da değerini korur (ama oyun cihazdan silinirse değerler kaybolabilir). Diğer alternatiflerden bazıları JsonUtility, XMLSerializer ve BinaryFormatter’dır. Bunlarla veriyi bir dosyaya çeşitli formatlarda kaydedebilir, daha sonra veriyi geri yükleyebilirsiniz.

      Takımın adı gibi basit şeyleri PlayerPrefs ile çok hızlı bir şekilde kaydedebilirsiniz ama eğer logoyu kullanıcı kendisi bilgisayarından seçecekse (yani var olan bir kaç logo arasından tercih yapmayacaksa), o zaman bu logonun bir kopyasını Application.persistentDataPath klasöründe tutup onun konumunu PlayerPrefs veya bahsettiğim diğer metotlar ile kaydedebilirsiniz. Daha sonra bu konumdan logoyu Texture2D olarak yüklemek için, Texture2D.LoadImage fonksiyonunu kullanabilirsiniz.

  33. Emir Yılmaz dedi ki:

    Merhaba yasir bey. İyisinizdir umarım 🙂 Bir sorum olacak bu konuyla pek alakası yok ama nereye yazacağımı bilemedim. Ben bir mobil oyun yapıyorum. Oyun başında logo geldikten sonra loading ekranı gelicek. Bu loading ekranı 3-4 saniye tutucam. Bu sürede arkaplanda nesneler objeler yüklenicek. Bir nevi optimizasyon. Bunu nasıl yaparım ? Bir kaynak var mıdır İngilizce türkçe ? Ya da siz daha önce bu konuda makale yazdıysanız link atabilir misiniz ? Bu benim için çok önemli 🙂 İyi günler iyi çalışmalar

  34. Chucklestone dedi ki:

    Yaşadığını öğrendiğimiz için Mutluyuz : D

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 )

Facebook fotoğrafı

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.