Hepinize merhabalar,
Bu derste, Unity‘nin popüler ve bir o kadar da güçlü bir özelliği olan coroutine‘lerden bahsedeceğiz. Coroutine’ler vasıtasıyla örneğin bir kodun çalışmasını birkaç saniye geciktirebilir, belli bir işlemin bitmesini bekleyebilir veya işlemi birkaç saniyeye yayabilirsiniz (bir objeyi bir yerden başka bir yere 2 saniyede hareket ettirmek gibi).
Hazırsanız derse başlayalım!
Coroutine’ler de aslında birer fonksiyondurlar ve birkaç ufak fark haricinde, aşina olduğunuz normal fonksiyonlardan bir farkları yoktur:
- coroutine’ler IEnumerator döndürmelidir. Bu arayüze erişebilmek için kodunuzun başına
using System.Collections;
satırını eklemeniz gerekir. Ama belki fark ettiğiniz üzere, yeni oluşturulan script’lere Unity otomatik olarak bu satırı ekler çünkü coroutine’ler Unity’de sıklıkla kullanılmaktadır - coroutine’ler StartCoroutine fonksiyonu ile çağrılmalıdır (aksi taktirde coroutine çalışmayacaktır)
- coroutine’in içinde en az bir yield return ifadesi kullanılmalıdır
Örneğin alttaki koda bir göz atalım:
void Start() { Debug.Log( "Start başlangıç" ); StartCoroutine( CoroutineTest() ); // CoroutineTest coroutine'ini başlat Debug.Log( "Start bitiş" ); } IEnumerator CoroutineTest() { Debug.Log( "İlk frame" ); yield return null; // 1 frame bekle Debug.Log( "İkinci frame" ); }
Tahmin edeceğiniz üzere, bu koddaki coroutine’imiz CoroutineTest fonksiyonu. Bu coroutine içerisine yazdığımız yield return null;
satırı, coroutine’in orada 1 frame beklemesini sağlar. Coroutine’ler, onları çağıran fonksiyonlardan bağımsız olarak hareket eder. Yani bizim CoroutineTest fonksiyonunu 1 frame bekletmemiz, Start fonksiyonunu da 1 frame bekletiyor olmamız anlamına gelmez. CoroutineTest 1 frame beklerken, Start normal seyrinde çalışmaya devam eder. Bu yüzden de bu programın çıktısı şöyle olur:
Start başlangıç
İlk frame
Start bitiş
İkinci frame
Şimdi bir de şu coroutine’e göz atalım:
IEnumerator CoroutineTest() { Debug.Log( "Zaman: " + Time.time ); yield return new WaitForSeconds( 1.5f ); // 1.5 saniye bekle Debug.Log( "Zaman: " + Time.time ); }
Gördüğünüz üzere, WaitForSeconds fonksiyonu vasıtasıyla bir coroutine’i belli bir süre boyunca bekletebilirsiniz. Burada dikkat etmeniz gereken nokta, bu sürenin Time.timeScale’e bağlı olmasıdır. Yani eğer timeScale’i 0.5 yaparak oyunu yavaş çekime aldıysanız, bu kod 1.5 saniye değil de 3 saniye bekler. Eğer timeScale’den bağımsız bir şekilde birkaç saniye beklemek isterseniz, WaitForSecondsRealtime fonksiyonunu kullanabilirsiniz.
Aşağıdaki örnekte ise, WWW sınıfını kullanarak internetten nasıl resim indirip bu resmi, script’in atandığı objenin materyaline atayabileceğinizi görüyorsunuz. Ayrıca bir coroutine’in parametre de alabileceğini görmüş oluyorsunuz. Bir WWW objesini yield return yaparsanız, kodunuz o WWW işleminin bitmesini bekler (bu örnekte, resmin internetten inmesini). Koddaki using ibaresinin coroutine’ler ile bir alakası olmadığı için ona çok takılmayın.
void Start() { StartCoroutine( ResimIndir( "http://flags.fmcdn.net/data/flags/w580/tr.png" ) ); // ResimIndir coroutine'ini, girilen parametre ile başlat } IEnumerator ResimIndir( string url ) { using( WWW www = new WWW( url ) ) // WWW bir IDisposable obje olduğu için using kullanıyoruz, yani bunun coroutine'lerle bir alakası yok { yield return www; // Resmin inmesini bekle if( !string.IsNullOrEmpty( www.error ) ) // Resmi indirirken bir hata alıp almadığımıza bak Debug.LogError( "Bir hata oluştu: " + www.error ); else { // Bir hata yok, resmi bu objenin materyaline texture olarak ata Texture2D resimTexture = www.texture; GetComponent<Renderer>().material.mainTexture = resimTexture; } } }
NOT: eğer WWW yerine UnityWebRequest kullanmak isterseniz, işlemin bitmesini beklemek için UnityWebRequest objesinin Send/SendWebRequest fonksiyonunu çağırınca döndürülen objeyi yield return yapabilirsiniz.
Aşağıdaki örnek kod, kodun atandığı objeyi 3 saniyede mevcut konumundan 10,10,10 konumuna taşımaya yarar:
IEnumerator ObjeyiKimildat() { float kimildamaSuresi = 3f; // Objeyi 3 saniyede hareket ettir float gecenSure = 0f; Vector3 mevcutKonum = transform.position; Vector3 hedefKonum = new Vector3( 10, 10, 10 ); while( gecenSure < kimildamaSuresi ) // Henüz kimildamaSuresi kadar süre geçmediği müddetçe bu kodu çalıştır { gecenSure += Time.deltaTime; // gecenSure her saniye 1 artar transform.position = Vector3.Lerp( mevcutKonum, hedefKonum, gecenSure / kimildamaSuresi ); // Objenin konumunu mevcutKonum ile hedefKonum arasında oynat yield return null; // 1 frame bekle (yumuşak hareket için objenin konumunu bir anda değil, frame frame değiştirmeliyiz) } // kimildamaSuresi kadar süre geçti, objenin hedefKonum'a tam oturduğundan emin ol transform.position = hedefKonum; }
Dilerseniz, yine StartCoroutine ile bir coroutine’in içerisinden başka bir coroutine’i başlatabilir ve bu coroutine’in bitmesini beklemek için, onu yield return yapabilirsiniz (eğer beklemek istemezseniz yield return yapmak zorunda değilsiniz):
IEnumerator CoroutineTest() { Debug.Log( "Test2'yi beklemeden önce" ); yield return StartCoroutine( CoroutineTest2() ); // CoroutineTest2 coroutine'ini başlat ve bitmesini bekle Debug.Log( "Test2'yi bekledikten sonra" ); Debug.Log( "Test2'yi başlatmadan önce" ); StartCoroutine( CoroutineTest2() ); // CoroutineTest2 coroutine'ini başlat ama bitmesini bekleme Debug.Log( "Test2'yi başlattıktan sonra" ); } IEnumerator CoroutineTest2() { Debug.Log( "Test2 başlangıç" ); yield return new WaitForSecondsRealtime( 1 ); Debug.Log( "Test2 bitiş" ); }
Peki diyelim ki çalışmakta olan bir coroutine’i durdurmak istiyorsanız napacaksınız? Burada ise StopCoroutine ve StopAllCoroutines fonksiyonları devreye giriyor. StopAllCoroutines fonksiyonu, bu objede StartCoroutine ile başlatılan tüm coroutine’leri durdurmaya yararken, StopCoroutine fonksiyonu ise, parametre olarak girilen belli bir coroutine’i durdurmaya yarar. Bunun için, durdurmak istediğiniz coroutine’i bir Coroutine değişkeninde tutmanız lazım. Örneğin:
private Coroutine donmeCoroutine; void Update() { if( Input.GetKeyDown( KeyCode.E ) ) // E tuşuna basınca { if( donmeCoroutine == null ) // Çalışmakta olan bir DondurCoroutine yok, bu coroutine'i çalıştır ve değişkene at donmeCoroutine = StartCoroutine( DondurCoroutine() ); else // DondurCoroutine çalışıyor, onu durdur { StopCoroutine( donmeCoroutine ); donmeCoroutine = null; } } } IEnumerator DondurCoroutine() { while( true ) // Bu coroutine, durdurulmadığı sürece sürekli çalışmaya devam eder { transform.Rotate( 0, 90 * Time.deltaTime, 0 ); // Objeyi Y ekseninde döndür yield return null; } }
Bu şekilde bu dersin sonuna geldik. Daha sonraki derslerde görüşmek üzere!
merhaba hocam blogunuz çok güzel burada paylaştığınız şeyler sayesinde kendimi çok iyi geliştirdim size bir kaç soru soracaktım bu coroutineler update fonksiyonu gibi degil anladıgım kadarıyla işi bitince StopCoroutine ile durduruyoruz surekli update fonksiyonu gibi sistemi yormuyor degil mi ? bir de bu while(true) içine en son yazdıgımız yield return null; kodu ne işe yarıyor tam olarak cunki benim izledigim bir yabancı kaynakta hemen hemen su sekilde kullanılmaktaydı
public void ShopBtn()
{
if (!ShopOn)
{
MenuCanvas.SetActive(false);
CameraAnim.Play(“CameraMenuShopAnim”);
StartCoroutine(“ShopOnClick”);
}
}
IEnumerator ShopOnClick()
{
while (true)
{
if (Camera.transform.position == ShopPos)
{
ShopCanvas.SetActive(true);
StopCoroutine(“ShopOnClick”);
}
yield return null;
}
}
şimdiden zaman ayırdıgınız ve guzel blogunuz için teşekkür ederim!
Coroutine sonsuza kadar çalışan bir loop içeriyorsa, durdurmak için StopCoroutine yapmak ya da objeyi inaktif hale getirmek gerekir evet. Aksi taktirde, coroutine fonksiyonu tamamen çalıştığında coroutine otomatik olarak durur. StartCoroutine’e string parametre vermek yerine, derste gösterdiğim şekilde kullanmanızı öneririm. Ayrıca DOTween’i de öğrenmenizi öneririm çünkü attığınız örnek kod DOTween için biçilmiş kaftan. “yield return null” coroutine’in 1 frame beklemesini sağlar. Yani oyun 60 fps ise, 1/60 saniye beklemeyi (sonraki frame’i beklemeyi) sağlar.
Hızlı cevabınız için teşekkür ederim önerilerinizi uygulayacağım iyi günler dilerim.
hocam kolay gelsin bir butona tıklayınca 2 saniye sonra iki fonksiyon çağırsın istiyorum ama bende birtürlü olmuyor
örnek butona tıklayınca aşağıdaki fonksiyonlar 2 sn sonra çalışsın
public void tikla() //buton onclicki ne eklediğim script
{
StartCoroutine(m_wait);
mDelete();
StartCoroutine(Rastgele());
}
IEnumerator m_wait()
{
Debug.Log( “Zaman: ” + Time.time );
yield return new WaitForSeconds( 2f ); // 1.5 saniye bekle
Debug.Log( “Zaman: ” + Time.time );
}
AMA OLMUYOR TIK DİYE ÇALIŞIYOR.
2. Debug.Log satırınız 2 saniye sonra çalışır, gecikme olmaması mümkün değil. mDelete fonksiyonunun 2 saniye sonra çalışmasını istiyorsanız, onu
yield return
‘den sonra yazmalısınız.çok teşekkürler
Merhaba unity de yeni oyun yapıyorum 2d ile zıplama yapıyorum zıpladıktan sonra belli bir süre bekleme süresi olmasını ıstiyorum IEnumerator bu kod ile denedım olmadı yardım edermisiniz.
birde sag sol hareketleri input.GetKey ile yaptım sizce dogrumu
Şöyle yapabilirsiniz: “float sonZiplamaAni;” değişkeni olur ve zıplarken “Time.time-sonZiplamaAni”nın değerinin 1 saniyeden büyük olup olmadığını kontrol edersiniz. Büyükse zıplar ve sonZiplamaAni’nı Time.time’a eşitlersiniz. Sağ-sol hareket için genelde Input.GetAxis(“Horizontal”) kullanılıyor çünkü WASD ve ok tuşlarını (ve sanırım joystick) destekliyor ama bu sizin için önemli değilse GetKey kullanmanızda hiç sakınca görmüyorum.
Çok iyi bir anlatım olmuş. Her şey kafamda oturdu.
Sevindim, rica ederim.
Hocam Unity personal ‘i kullanmak için github kullanmamız gerekiyormuş diye öğrendim ama github hesabını açtım da unity de nasıl personal ‘ı kullanacağımı bilemedim. Biliyorsanız yardımcı olabilir misiniz?
GitHub hesabı gerekmiyor. Sadece Unity’nin web sitesinden ücretsiz bir şekilde hesap açmanız yeterli. Ardından Unity Hub programına hesabınızla giriş yaparken, lisans olarak ücretsiz Personal lisansı seçebilirsiniz (eğer sorarsa).
Bana github ile ilgilli birşeyler söyledi bu seferde ben github da öğrencilik doğrulaması filan yaptum o zaman bne yanlış bir şey mi yapmış oldum?
Evet GitHub hesabı açmanız kesinlikle gerekmiyor. Hesap açmanızda sakınca yok ama gerekmiyor.
Anladım teşekkür ederim.
Selamun aleyküm hocam ben şunu anlamadım. yield return, Coroutine ‘de ne göreve sahip?
Aleykümselam. O kod 1 frame beklemeye yarar. Oyun saniyede 60 kare (frame) (60fps) oynanıyorsa, saniyenin 1/60’ı kadar beklemiş olursunuz.
Tamamdır teşekkür ederim. Hayırlı akşamlar.
Merhaba,
Biraz uzun ama bir konuda sorum olacak şimdiden teşekkürler.
Oyun level geçmeyi sağlayan yada bölümü tekrarlatan oyun bitti ve yeni level kodlarım var tek script içinde.
Oyun bitti kısmı farklı bir scripte de tag üzerinden temas oluyorsa çalışıyor ve GamePanel butonunu aktif ediyor.
OYUN BİTTİ TAG
”
if (col.tag == “kucukarrowtag”)
{
oyunYoneticisi.GetComponent().OyunBitti();
}
”
Game paneli üzerinde tekrar oyna ve anamenü dön seçenekleri var
10 ok varsa 9cu ok temas ederse sorun yok bölümü tekrarlıyor, fakat 10uncu ok oyunbittitag çalıştırsa bile bölüm geçmesine sebep oluyor.
public void OyunBitti() içine ” SceneManager.LoadScene(int.Parse(SceneManager.GetActiveScene().name) + 1);” Eklemem lazım
Bunu ekleyince GamePanel.SetActive(true); paneli aktif oluyor hemen seçim yatprmadan oyun başlıyor kaldığın yerden bunu butonla manuel yapmak istiyorum bunu nasıl yapabilirim.
public void OyunBitti()
Yerine
IEnumerator OyunBitti() Yapınca
if (col.tag == “kucukarrowtag”)
{
oyunYoneticisi.GetComponent().OyunBitti();
}
Kodu tag kodu hata biliyor
————————————————————————————–
IEnumerator yenilevel()
{
hedef.GetComponent().enabled = true;
AnaArrow.GetComponent().enabled = false;
yield return new WaitForSeconds(2);
if (kontrol)
{
SceneManager.LoadScene(int.Parse(SceneManager.GetActiveScene().name) + 2);
level_id = int.Parse(SceneManager.GetActiveScene().name) + 0;
if(PlayerPrefs.GetInt(“levelid”) < level_id)
PlayerPrefs.SetInt("levelid", level_id);
}
}
public void OyunBitti()
{
GamePanel.SetActive(true);
hedef.GetComponent().enabled = false;
AnaArrow.GetComponent().enabled = false;
}
Mesajınızı iki defa okudum ama yaşadığınız sıkıntıyı tam anlayamadım. Oyununuzla ilgili hiçbir şey bilmeyen birine anlatır gibi (örneğin oklar nedir, 9. ok ve 10. okun farkı nedir hiç fikrim yok) anlatır mısınız?
normalde internette çok yorum bırakmam ama sanırım tam da aradığım şeyi buldum, c# winform’da timer gibi unity için de bu tarz bir şey arıyordum InvokeRepeating de işime yarıyordu ama parametre giremediğim için buna yöneliyorum, gerçekten çok yararlı ve güzel anlatımın için teşekkür ederim.
Rica ederim, faydalı olmasına sevindim.
Merhaba. Bu verdiğiniz bilgiler çok ama çok değerli. Bu kadar bilgiyi ücretsiz biçimde insanlara sunduğunuz için ben kendi adıma size teşekkür ediyorum. Mükemmel bir insansın.
Rica ederim, iyi dilekleriniz için teşekkürler.
Burayı okudum okuyunca anlıyorsun ancak uygulamada sorunlar çıkıyor malum. Şunu yapmak istiyorum yardımcı olur musunuz.
speed adında bir değişken var. Bir butona bastığımızda bu speed değişkeni 5 saniye boyunca 2 katına çıksın, sonrasında tekrar eski haline gelsin istiyorum.
public void ButtonSpeed()
{
StartCoroutine(SpeedPower());
}
Öncelikle bir butona basınca çalışması için yukarıdaki gibi yapmak şart mı?
IEnumerator SpeedPower()
{
Burada tıkandım. İstiyorum ki speed = speed*2 olsun 5 saniye boyunca. Bu 5 saniye bittiğinde de tekrar speed eski haline gelsin. Speed için bir değer giremeyiz çünkü o başka yerlerde değişiyor.
}
Butona basınca çalışması için yukarıdaki gibi yapmak maalesef şart, StartCoroutine’in çağrılması zorunlu. Coroutine’in içerisinde ise speed’i 2’ye katlayıp WaitForSeconds ile 5 saniye bekleyip ardından speed’i 2’ye bölmek işinizi görmüyor mu?
while gibi bir şeyler olup içine bir şeyler yazmak gerekiyor diye düşünmüştüm. Şimdi siz söyleyince while falan kullanmadan yazdım oldu sanırım. While gibi ifadelerin her zaman olması gerektiğini düşünmüştüm bu şekilde de problem yok sanırım.
speed = speed*2;
yield return new WaitForSeconds (5);
speed = speed/2
Evet bunun bu şekilde olması gerekiyor. while’ı sadece ihtiyacınız olduğunda kullanacaksınız.
Gerçekten süper bir yazı. Yabancı kaynaklardan bile iyi.
İlginiz için teşekkür ederim.
ben bir spawner yazdım.birkaç saniyede bir obje spawnlıyor.bu beklemeyi coroutine ile sağladım ama 1kere bekliyor spawnlıyor daha sonra beklemeyi atlayıp sürekli spawnlıyor.bunun sebebi nedir?
Coroutine’iniz DondurCoroutine() gibi olursa sıkıntı yaşamazsınız.
Merhabalar, açıklama için teşekkürler güzel bir konu olmuş. Birçok yerde işe yarayacak bir sistem.
Bir sorum olacak size:
Ben oyunumda bir güç olsun istiyorum, örneğin topu hızlı gitmesi. Bu gücün 5 veya belirlediğim bir değişkene bağlı saniye kadar çalışmasını daha sonra eski hızına dönmesini istiyorum. Bunu nasıl sağlarım? Bu konuyla benziyor gibi bu şekilde mi çözülür tam emin olamadım. Kodlar dilinden biraz detaylı açıklayacak olursam.
speed = 300 normalde
F tuşuna basınca
speed = 5 saniyeliğine(veya bir süre) 600 olsun, 5 saniye sonunda tekrar 300e(ilk haline) dönsün.
İlk haline dönsün kısmını 300 olarak elimle girmek istemiyorum açıkçası, çünkü bu değişebilecek bir şey, normal hızı ileride 400 yapabilirim örneğin.
yapmak istediğim böyle bir şey. Yarımcı olabilirseniz çok memnun olurum.
Araştırmalarım sonucu net bir bilgiye ulaşamadım. Sürekli belirli bir saniye aralığında ya da belirli bir saniye sonra çalıştırılan fonksiyonlar ya da işlemlerin cevaplarını görüyorum. Bu konuda benim mi bir hatam var acaba? Oyunda istediğim bu işlemi farklı bir şekilde mi yapmalıyım. Yani siz olsanız bu özel kullanılabilir gücü nasıl eklerdiniz.
speedMultiplier diye 2. bir değişken oluşturabilir ve değerini 5 saniyeliğine 1’den 2’ye çekebilirsiniz. Hareket kodunuzda da hız olarak
speed*speedMultiplier
‘ı kullanabilirsiniz.Teşekkürler, evet dediğinizi anladım fakat asıl sorum “5 saniyeliğine” kısmı. Herhangi bir fonksiyonu veya bir değişkeni 5 veya 10 saniye yani belirli bir süreliğine nasıl çalıştırabiliriz. Bu süre bittiğinde eski düzenine dönecek şekilde.
private float speed;;
private float speedMultiplier;
void Speed() //Speed isminde bir fonksiyon
{
speed = speed*speedMultiplier; //sanırım böyle bir şey diyorsunuz
}
Örneğin bu şekilde “Speed” isminde bir fonksiyon var. Bu fonksiyon 5 saniye çalışsın ve 5 saniye sonunda speed değişkenim tekrar ilk haline dönsün istiyorum
IEnumerator SpeedMultiplierCoroutine()
{
speedMultiplier = 2;
yield return new WaitForSeconds(5);
speedMultiplier = 1;
}
Ardından: rigidbody.AddForce(speed*speedMultiplier);
üstad bir bölümde çarpışmadan sonra animasyon çıkıyor . 3-4 saniye sonra levelin tekrar başlamasını istiyorum. Bu şekilde bir kod yazdım ama çalışmıyor hatam nerede olablir.
unity bu hatayı veriyor.
Assets\scripts\CollisionDetector.cs(16,25): error CS0103: The name ‘yenidenbasla’ does not exist in the current context
https://hizliresim.com/5JGdUd
Hocam kodun resmini paylaştım bir bakarmısınız teşekkğrler
16. satıdaki yenidenbasla fonksiyonunu CollisionDetector class’ında tanımlamamışsınız, tanımlamadığınız bir fonksiyonu kullanmaya çalışıyorsunuz.
Kokay gelsin. Bu WWW olayı kaldırılmış galiba? Bilginiz var mı ?
Kaldırıldı mı bilmiyorum ama kaldırıldıysa da aynı işlevi gören UnityWebRequest’i kullanabilirsiniz: https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html
Abi Unityde bir oyun tasarlıyorum ama animasyonu yapamadım karakter düşmana değdiği zaman bir animasyon çalışması gerekiyor bi türlü yapamadım çözüm önerebilirmisin ?
Animation component’i kullanıyorsanız animationComponenti.Play(“AnimasyonIsmi”), Animator component’i kullanıyorsanız animatorComponenti.Play(“AnimasyonIsmi”) veya animatorComponenti.SetTrigger veya animatorComponenti.SetBool kullanmanız lazım. Animasyonunuz Animation component’ine veya Animator component’inin AnimatorController’ına ekli olmalı. Eğer hiç Animation veya Animator kullanmadıysanız, önce YouTube’da bu konuyla alakalı birkaç video izlemenizi öneririm.
Kaçırdığım önemli bir yorum var.
Acaba yorum geçmişini nerden bakabilirim?
“Nurullah Ertaş” , “Emrullah Ertaş” , “Yasin Çakıcı”
bunların yaptıkları yorum önemliydi. nerden bakabilirim yardımcı olabilirmisiniz?
yan tarafta yorum geçmişi bulunuyor lakin sadece 5 yorum geçmişi
Not : 2 gün önceki yorum
Şu yorumlar olabilir:
https://yasirkula.com/2014/07/07/unity-c-tps-oyunu-yapimi-ceviri-projesi/#comment-22600
https://yasirkula.com/2018/06/05/unity-android-calisma-zamani-izinleri-yonetmek-runtime-permissions/#comment-22607
https://yasirkula.com/2019/07/27/unity-bir-scriptten-baska-bir-scriptteki-degiskene-ulasmak/#comment-22606
üzgünüm buradan yazıyorum ama bir sorum daha var
ben karakterime şöyle zıplama verdim
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up*ziplama);
anim.speed = 1;
anim.SetBool(“JUMP”, true);
}
ve bu sefer hem addforce sayesinde zıplıyor hemde karakterin animasyonu sayesinde böylece fazla zıplamış gözüküyor bunu nasıl düzeltebilirim
Sıkıntıyı anladım ama çözüm yolu önerme konusunda benim tecrübem yetersiz kalıyor. Şu konuya bakmanızı öneririm: https://gamedev.stackexchange.com/questions/162853/how-to-disable-animation-root-motion
merhaba öncelikle ben unity ye yeni başladım ve karakter animasyonlarını yapıyordum
if (Input.GetKey(KeyCode.W) && (Input.GetKey(KeyCode.V)))
{
transform.Translate(transform.forward * 0.3f);
anim.speed = 1;
anim.SetBool(“TAKLA”, true);
}
if (Input.GetKeyUp(KeyCode.V))
{
transform.Translate(transform.forward * 0.3f);
anim.speed = 1;
anim.SetBool(“TAKLA”, false);
}
ben 2 .if de transformdan önce bekle kullanmak istiyorum oyun hata veriyor bunu yaptığımda
yani kısaca sorunum şu ben W + V tuşuna bastığımda takla atacak ama basılı tutmam gerekiyor
alttaki if kısmını eklemezsem bu olayı sürekli tekrar ediyor.
ben sizin anlattığınız kısımda IEnumerator bunu anlamadım galiba oyuzden yapamadım void update altına yazıyorum kodlarımı şimdiden teşekkürler
Animasyonlar arası geçiş kötü durduğu için biraz beklemek istiyorsunuz diye düşünüyorum. Bence karakterin AnimatorController asset’ini açın (Window-Animator penceresini açıp AnimatorController’a Project panelinden çift tıklayın), ardından TAKLA false olduğunda gerçekleşen geçişe tıklayın ve Inspector’dan Settings’teki ayarları biraz düzenleyin (dokümantasyon: https://docs.unity3d.com/Manual/class-Transition.html). Örneğin Exit Time’ın değerini değiştirmeyi deneyebilirsiniz (0 ile 1 arasında değerler deneyin).
demek istediğim şu ben tek tıklamada yapmak istiyorum ama ozaman animasyon iptal oluyor yani yaptığım komutta basılı tutmam gerekiyor
Boolean değil de Trigger değişkeniniz olsun ve anim.SetTrigger(“TAKLA”) fonksiyonu ile bunu aktifleştirerek takla animasyonuna geçiş yapın. Takla animasyonundan normal animasyona geri geçişte bir Condition kullanmayın, hata alırsanız Exit Time condition’ı kullanın.
bu sefer sonsuz döngü oldu yani sürekli takla atıyor sizide yoruyorum kusura bakmayın
SetTrigger sürekli çağrılıyor demek ki. SetTrigger’ın olduğu satıra Debug.Log ekleyerek de bunu tespit edebilirsiniz. SetTrigger’ı sadece karakterin takla atmasını istediğinizde çağırın.
Yasir bey iyi akşamlar .
Benim oyunumda iki karakter var ikisinin healt ı box collider is triger seçeneği seçili vaziyette . Ben bu iki karakterin birbirlerinin içinden geçmemesini nasıl yaparım . ( Herbirine bir collider daha verdim is triger seçili değil , bu şekilde de savruluyorlar . ) Yardım ricası ile kolay gelsin .
Birbirinin içinden geçemediğini ama temas ettiklerinde bi titreştiklerini anlıyorum, yanlışım varsa düzeltin. Eğer transform.Translate ile hareket ediyorsanız Rigidbody’nin MovePosition’ını kullanmayı deneyebilirsiniz.
Yasir bey
Hareket için GetAxis kullanıyorum .Benim istediğim iki karakterde birbirine temas ettiğinde hareket etmemeli .Misal bir duvara yada engele karakter dokunduğu zaman onu nasıl geçemiyorsa oyuncunun başka bir tarafa yönlendirmesiyle gidiyorsa bende o şekilde yapmaya çalışıyorum .
Teşekkurler.
Eğer MovePosition işe yaramadıysa maalesef bir fikrim yok
Yasir bey
Yaptığım bir oyunda (Samsung app ta yayınladım askıya alındı .) canvasta olan joystyic, buttonlar , karakterin yaşam çizgisi farklı boyutlardaki telefon veya tabletlerde şeklinin bozulduğu veya kaybolup görünmediği ile bilgili bildirim aldım . Her boyutta ve çözünürlükte cihaza uygun olarak nasıl yapabilirim .
Yardım ricası ile kolay gelsin .
RectTransform’daki Anchor’lardan ve Canvas’taki Canvas Scaler’dan faydalanmanız lazım. Ayrıca bkz: https://yasirkula.com/2015/01/21/unity-ui-arayuz-sistemi/ (Arayüzün Her Çözünürlükte Aynı Görünmesini Sağlamak)
Sağolun Yasir bey anchor ları ayarlamıştım .Diğerlerine bakacağım .
Teşekkrler
Merhaba Yasir hocam ufak bir sorum olacaktı.
Oyun menüsünde butona basılınca coroutine ile ekranda 1.texti gösteriyorum ve belli bir saniye sonra text objesini destroy ediyorum. Oyuncu aynı butona tekrar basınca 2.text objesini göstermek istiyorum ama burada sıkıntı oluyor.
Nasıl yapabilirim acaba ? Coroutine’nin içine ikinci bir if bloğu ekleyerek yapmaya çalıştım ama her seferinde direkt 2.text’i ekrana yazdırdı.
Yardımlarını bekliyorum kolay gelsin hocam.
Bir “bool text1Gozuktu = false;” değişkeniniz olsun. Bunun değeri false ise ilk text’i gösterin ve değişkeni true yapın, değeri true ise de ikinci text’i gösterin.
Yasir bey iyi akşamlar ben yuzey objesine collider vermek istiyorum yuzey çok girintili çıkıntılı olduğu için mesh collider vereceğim convex yapıp yüzeyde olan objelerin düşmemesini sağlamak istiyorum fakat mesh girinti ve çıkıntılara uymuyor kare şeklinde çıkıyor convex i kapatınca tam yuzeye colider oturuyor bu seferde objeler üstünden düşüyor. Yardım ricası ile kolay gelsin .
Yasir bey bir türlü yapamadım .Onun yerini tek tek collider verdim .Uzun sürdü ama oluyor .
Unity’nin dokümantasyonunda yazdığına göre, yüzeyde Rigidbody component’i olmazsa Mesh Collider’daki Convex’in işaretini kaldırabilirmişsiniz ve sistem düzgün çalışırmış. Ama kendim test etmedim. Bu işe yaramazsa da ya bir plugin kullanmalı (“unity concave collider” şeklinde arama yapabilir) ya da tek tek collider vermeye devam etmelisiniz.
Yasir bey teşekkürler .
Öncelikle bu site için teşekkürler. Ben bilgisayara karşı bir satranç oyunu yapsam, ben bir taş oynayınca bilgisayarda bir taş oynayacak, bu sistemde sıra bana gelene kadar ben bekleyeceğim, sıra bana gelince bilgisayar bekleyecek. Burada bir fonksiyonun işlemi bittikten sonra başka bir fonksiyonun bitmesini beklemesini nasıl sağlayabilirim.
Bir coroutine’de while(birDegisken==true) yield return null; kodu yazarak birDegisken’in değeri false olana kadar o coroutine’i bekletebilirsiniz.
Coroutine fonksiyonu ile halledebilirsin sanırım. Aynı sorunu ben yield return new WaitUntil( () => (değerlendirilecek ifade)) komutu ile çözmüştüm.
Merhaba Yasir Bey,
Ben Unity ile basit oyunlar geliştiriyorum. Geliştirmekte olduğum bir uygulama da girilen konutları stackleyip, başlama butonu ile stackdeki komutları teker teker gerçekleştirmek istiyorum. Girilen komutları diziye atıp döngüler ile işliyorum. Komutlar, ileri gitme, sağa ve sola dönme ve geri gitmeden oluşuyor. Sorunum şu; hareket etme işlemini anında gerçekleştiriyor bense her bir adımı 1 saniye gibi bir zamanda gerçekleştirmesini istiyorum uygulamanın daha anlaşılır olması için. Hareket etme işlemini Canvas’a yerleştirdiğim 4×4 lük panellerin position bilgisi ile gerçekleştiriyorum. Sorunumu Coroutine ile çözebilir miyim? Şimdiden teşekkürler saygılarımla iyi çalışmalar.
Uygulamanın görüntüsü; https://i.hizliresim.com/JZMEjY.jpg
Evet coroutine işinizi görür. Her bir komut arasında bir yield return new WaitForSeconds(1.0f); çalıştırarak 1 saniye bekleyebilirsiniz.
–Konuyla alakasız–
Merhaba ben bir shooter oyunu yapıyorum.Elimde bir spawner var bunun sayesinde bir çok düşman oluşturabiliyorum yaptığım kodlarda eğer düşmanla aramadaki mesafe 1.5 den küçükse benim canımın azalması şeklinde ayarlı ama bu işlem sadece bir düşman için geçerli çevremdeki her düşmanla aramdaki mesafeyi ölçmesini nasıl sağlarım ?
Component’i player’a vermek yerine düşman prefab’ına verebilirsiniz, böylece her düşman kendi mesafesini kendi ölçer. Daha iyisi ise, tüm düşmanları bir List veya array’de tutabilir ve bu listenin içindeki tüm düşmanların player’a mesafesini tek tek ölçebilirsiniz.
Component’i düşman prefab’ına vermeyide denedim çalıştı hepsi izliyor,vuruyor falan ama can barım sıkıntı oluyo bazıları scriptte canımı götürüyo gözüküyor ama bar azalmıyor bazen script sadece son oluşan klonda is görüyor.
Can barı script’iniz nasıl ve ne zaman güncelleniyor bilmediğimden bu konuda pek yardımcı olamayacağım. Player’a hasar verdikçe can barını da güncellemeniz lazım normalde.
–Konuyla Alakası Yok–
Ben Unity de Monodevelop Kullanıyorum Yeni Bir Kod Yazdıkdan Sonra Monodevelop da f5 e Basmadan yada Debug Yapmadan Unity Yeni Yazdığım Kodu Görmüyor Bunu Nasıl Çözebilirim
Maalesef hiç MonoDevelop tecrübem yok.
Yasir bey klonlama yaparken (Instantite) for döngüsü kullanarak (int i=0;i<2;i++)start ta yazınca sadece 2 adet kolonluyor azalınca artırmıyor update ye yazınca sınırsız olarak arttırıyor .klonlanan nesne ikiden az olunca tekrardan sadece iki taneyi instante edemedim . Nasıl yapabilirim . Yardım ricasıyla kolay gelsin .
Kodu Start’ta bırakın ve objeye verdiğiniz script’in OnDestroy fonksiyonunda yeni bir obje Instantiate edin. Böylece bir obje yok olunca yeni bir obje oluşacak. Daha da iyisi, yeni bir obje Instantiate etmek yerine var olan objenin yerini değiştirmek suretiyle o objeyi tekrar kullanın; ama bu işlemi OnDestroy’da değil, objeyi nerede Destroy ediyorsanız orada yapmanız lazım.
Teşekkürler Yasir bey .
Size bişey sormak istiyorum. Coroutinelerle alakası yok farkındayım.Ben bir bool tanımladım ve eğer bu bool açıksa bir gameobject tanımlamasını istiyorum yani şöyle
public bool asd
if(asd){
public GameObject dsa
}
Ama bu kodu
****——-if(asd){
public GameObject dsa
}———-****
Setup Veya Updatenşn içine yazdığımda sıkıntı veriyor çözümü varmı
Bu arada bir strateji oyunu yapmak istiyorum
Şimdiden teşekkürler.
Bu şekilde değişken tanımlamanız mümkün değil. Bunu niçin istiyorsunuz? Örneğin bir bool’un değeri false ise başka bir değişkeni Inspector’da göstermemek için mi?
Yinede Teşekkür ederim.Evet false ise kapat gibi.
Bunun için paralı asset’ler var ama ücretsiz bir asset henüz bulamadım.
EDIT: Şurada aşağıda yer alan kodu, Editor klasörü içerisinde oluşturacağınız HideWhenFalseAttribute.cs isimli bir C# dosyasına yapıştırıp, “public GameObject dsa;” değişkeninin üstüne [HideWhenFalse(“asd”)] eklemeyi deneyebilirsiniz: https://feedback.unity3d.com/suggestions/attribute-to-show-slash-hide-variables-in-inspector-based-on-another-public-boolean
Peki Başka bir classdaki boolun true yada false olduğunu anlayabilirmiyim
Verdiğim kod ile olacağını sanmıyorum.
Destroy ettiğim enemy objesi silinince ses kayboluyor .destroyu bu sistemde geciktiremedim . Nasıl yapmalıyım : patSesi.PlayOneShot (PatlamaSesi, 0.1f);
patSesi.PlayOneShot yerine AudioSource.PlayClipAtPoint(PatlamaSesi,transform.position,0.1f) fonksiyonunu kullanmayı deneyebilirsiniz.
Yasir bey teşekkürler .
Deneyeceğim . Çok sağolun .
Abi ben playerprefs A sahnesinde altin degerini alip B sahnesindeki magza yerini yazdirmak istiyorum bunu nasil yapabilirim bi turlu yapamadim
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System;
public class Menu : MonoBehaviour {
public GameObject menucanvas;
public GameObject settingcanvas;
public GameObject shopcanvas;
public GameObject infocanvas;
public GameObject backbtn;
public Toggle mutetog;
public Toggle shoptog;
public Text infotext;
int newaltin;
public static int totalaltin;
public Text toplamaltintext;
public Text bincoinstext;
void Start ()
{
newaltin = PlayerPrefs.GetInt(“Altin”);
totalaltin = Rabbit.altindeger;
newaltin = Convert.ToInt32(toplamaltintext);
}
void Update ()
{
totalaltin += newaltin;
PlayerPrefs.SetInt(“Altin”, totalaltin);
toplamaltintext.text = totalaltin.ToString();
}
public void Playbutton()
{
menucanvas.SetActive(false);
settingcanvas.SetActive(false);
SceneManager.LoadScene(1);
}
public void Settingsbutton()
{
menucanvas.SetActive(false);
settingcanvas.SetActive(true);
}
public void Shopbutton()
{
menucanvas.SetActive(false);
shopcanvas.SetActive(true);
}
public void Backbutton()
{
if (mutetog.isActiveAndEnabled==true)
{
menucanvas.SetActive(true);
settingcanvas.SetActive(false);
}
else if (shoptog.isActiveAndEnabled == true)
{
menucanvas.SetActive(true);
shopcanvas.SetActive(false);
}
else if (infotext.isActiveAndEnabled == true)
{
infotext.gameObject.SetActive(false);
settingcanvas.SetActive(true);
backbtn.SetActive(false);
}
}
public void Infobutton()
{
settingcanvas.SetActive(false);
infocanvas.SetActive(true);
infotext.gameObject.SetActive(true);
backbtn.SetActive(true);
}
public void Exitbutton()
{
Application.Quit();
}
public void Bincoins()
{
if(Rabbit.altinvalue == 2000)
{
Debug.Log(“Satın alındı”);
Rabbit.altinvalue -= 2000;
}
else
{
Debug.Log(“Para Yeterli Değil”);
}
}
private void OnApplicationQuit()
{
PlayerPrefs.SetInt(“Altin”, totalaltin);
}
}
A sahnesinde altının değerini kaydetmek için PlayerPrefs.SetInt(“Altin”, altın miktarı) fonksiyonunu kullanıp B sahnesinde bu değere PlayerPrefs.GetInt(“Altin”) şeklinde erişebilirsiniz. Attığınız kod static değişkenlerle vs. karmaşık geldi ben onu tam çözemedim.
Harika bir ders herkesin işine yaricaktir teşekkürler hocam
Ben teşekkür ederim.