Unity Oyunlarınızdan 360° Screenshot Almak

Yayınlandı: 23 Ekim 2017 yasirkula tarafından Oyun Tasarımı, UNITY 3D içinde
Etiketler:, , , , , , , , , , ,

GÜNCELLEME (19.03.2018): Asset Store linki eklendi.

Yeniden merhabalar,

Bu yazımda, Unity oyunlarınızdan 360 derece ekran görüntüleri almanıza yarayan basit bir script paylaşacağım. Bu ekran görüntülerini Facebook veya Flickr gibi sitelere yüklediğinizde, resim etkileşimli bir şekilde 360 derece görüntülenir. Örneğin şu resmi bu yöntemle çektim (resmi 360 derece görmek için ise buraya tıklayın):

Asset Store: https://www.assetstore.unity3d.com/en/#!/content/112864

Alternatif Link: https://github.com/yasirkula/Unity360ScreenshotCapture/raw/master/360Screenshot.unitypackage

Açıklama ve örnek kod için yazının devamını okuyabilirsiniz…

Linteki unitypackage‘ı projenize import ettikten sonra artık kodlarınızda I360Render.Capture() fonksiyonunu kullanarak 360 derece ekran görüntüleri alabilirsiniz. Dilerseniz bu fonksiyona parametre olarak resmin genişliğini ve resmin JPEG olarak mı yoksa PNG olarak mı kaydedilmesi gerektiğini de girebilirsiniz (örneğin I360Render.Capture(2048, false); fonksiyonu 2048×1024 boyutunda bir PNG resim oluşturur). Fonksiyon bir byte[] objesi döndürdüğü için bu array’i File.WriteAllBytes fonksiyonu ile istediğiniz bir yere kaydetmelisiniz.

Aşağıdaki örnek kod, oyun esnasında P tuşuna bastığınızda 360 derece bir screenshot alıp bunu cihazınıza kaydeder ve kaydedilen konumu konsola yazdırır. Ardından bu resmi Facebook’unuza yükleyecek olursanız resmin 360 derece görüntülendiğini göreceksiniz:

using System.IO;
using UnityEngine;

public class RenderTest : MonoBehaviour
{
	public int resimGenisligi = 1024;
	public bool jpegKaydet = true;

	void Update()
	{
		if( Input.GetKeyDown( KeyCode.P ) )
		{
			byte[] bytes = I360Render.Capture( resimGenisligi, jpegKaydet );
			if( bytes != null )
			{
				string path = Path.Combine( Application.persistentDataPath, "360render" + ( jpegKaydet ? ".jpeg" : ".png" ) );
				File.WriteAllBytes( path, bytes );
				Debug.Log( "Resim kaydedildi: " + path );
			}
		}
	}
}
yorum
  1. ali dedi ki:

    merhaba.yaptığım oyunda ui bileşenleri oyunun yüklü olduğu cihazın ekran çözünürlüğüne göre dağılıyor ekran çözünürlüğünü sabit tutmanın yolu varmı örneğin ekran 1920×1080 ama ben oyunu bu ekranda 1280×720 çözünürlüğe zorlayabilirmiyim.yada çözünürlükten bağımsız olarak menu yapılabilirmi,hangi çözünürlük olursa olsun benim bilgisayardan ayarladığım şekilde durabilrimi?

    • ali dedi ki:

      Anchor ları ekranda objenin durmasını istediğim şekilde ayarladım ama objenin büyüklüğü küçüklüğü değişmiyor sadece istediğim yerde duruyor bunu büyütmenin bi yolu varmı

      • ali dedi ki:

        objenin boyutunu scrren.width screen.height komutlarıyla çözmeye çalıştım örneğin

        yükseklik=screen.height;
        genişlik=screen.width;

        gameobject.width=varolan genişlik * genişlik/720;
        gameobject.height = varolan yükseklik * yükseklik/1280;

        burada 1200 ve 720 benim oyunu ayarladığım çözünürlük yeni ekran boyutu neyse ona göre ayarlayacaktı ama objenin width yada height değerlerine kod üzerinden erişemiyorum

        gameobject.getcomponent<recttransform() dedikten sonra width yada height degerleri çıkmıyor

        birde bilgisayarda kameranın tam sınırlarına collider koydum oyuncu kamera sınırından dışına çıkmasın diye ama telefonda oynayınca objenin yarısı kameranın dışına çıkıyor collider hala var ama telefonda biraz ötelenmiş gibi bunun nedeni nedir bilginiz varmı?

      • ali dedi ki:

        bahsettiğim kenarlardaki colliderların kayması çözünürlük farkındanmış yeni çözünürlük ekleyip düzelttim ama objelerin boyut farkını hala çözemedim şöyle birşey yapabilirmiyiz oyunu editorde belirlenen çözünürlükte açılmaya zorlayabilirmiyiz yani 720p çözünürlük sahibi oyunu örneğin 1080p ekranda 720p olarak açsak kenarda kalan siyah boşlukarıda oyunun olduğu kısmı esneterek doldursak windows duvar kağıtlarındakı fill the screen özelliği gibi böyle bi özellik varmı

      • ali dedi ki:

        Canvasta canvas scaler diye script varmış gözümün önünde olmasına rağmen görmedim kusura bakmayın o kadar yorum yaptım

      • yasirkula dedi ki:

        Evet menünün her çözünürlükte düzgün gözükmesi için Canvas’ta Canvas Scaler, arayüz elemanlarında da doğru yerleştirilmiş anchor işinizi görecektir. Önceki sorularınıza cevap verecek olursam:

        – arayüz elemanlarının genişlik ve yüksekliklerini bulmak için ((RectTransform) transform).rect.width ve ((RectTransform) transform).rect.height’tan faydalanabilirsiniz. Ancak iki değere de aynı anda erişmek istiyorsanız, performans açısından ((RectTransform) transform).rect’i bir değişkene atayıp o değişkenin width ve height’ını kullanmanızı öneririm.

        – ekranın sağ ve sol kenarlarına koyduğunuz objeler, sizin de tecrübe ettiğiniz üzere, çözünürlük değiştikçe sağa sola kayabiliyor. Her çözünürlükte dinamik olarak ekranın sol kenarının koordinatını bulmak için Camera.main.ViewportToWorldPoint( new Vector3( 0f, 0.5f, 10f ) ) ve ekranın sağ kenarının koordinatını bulmak için de Camera.main.ViewportToWorldPoint( new Vector3( 1f, 0.5f, 10f ) ) fonksiyonunu kullanabilirsiniz. Buradaki 10f değeri, fonksiyonun döndürdüğü noktanın kameradan kaç birim uzakta olacağını belirler.

        – çözünürlüğü değiştirmek için Screen.SetResolution fonksiyonunu kullanmayı deneyebilirsiniz. Ancak bu fonksiyon her platformda/cihazda doğru çalışır mı onu bilemiyorum, test etmeniz lazım.

      • ali dedi ki:

        Menu elemanlarını hallettim sormak istediğim başka bir soru var.Ben bir sahneden başka bir sahneye geçmek için application.loadlevel fonksiyonunu kullanıyorum ama unity her defasında scene manager kullanmam için uyarı çıktısı veriyor bu iki fonksiyon aynı değilmi sonuçta başka bir sahneyi yüklüyorlar performans olarak scene manager dahamı iyi

        mesela oyunda yanınca tekrar oynamak için application.loadlevel(“şimdikilevel”) fonksiyonunu kullanıyorum sıkıntı çıkarırmı siz hangisini önerirsiniz loadlevel fonksiyonununa devammı edeyim yoksa scene managermi kıullanayım.

      • ali dedi ki:

        birde şu resimdeki alttaki geliştirici olmaktan bir adım uzaktasınız mesajı gibi mesajı unityde nasıl verebilirim

        https://i.hizliresim.com/Lbl9nz.png

      • yasirkula dedi ki:

        Bahsettiğiniz iki fonksiyonun da performsları aynı. Unity aynı anda birden çok scene’in açık olmasına olanak sağlıyor ama bu sistem Application sınıfındaki fonksiyonlarla tam olarak kontrol edilemiyordu; bunun için de SceneManager sınıfı oluşturuldu. Application.LoadLevel gibi fonksiyonların işlevselliğini SceneManager.LoadScene ile de birebir sağlayabildiğimiz için, aynı işi yapan birden çok fonksiyon olmasın diye Application.LoadLevel gibi eski fonksiyonlar artık uyarı veriyor. Unity’nin ilerleyen sürümlerinde Application.LoadLevel’ın desteği tamamen kalkabileceği için SceneManager.LoadScene fonksiyonunu kullanmanızı öneririm.

        Resimdeki gibi bir “Toast” mesajı vermek için ise şu dersimden faydalanabilirsiniz (oradaki hazır unitypackage’ı indirip en sondaki örnek kodu inceleyebilirsiniz): https://yasirkula.com/2015/10/14/unity-androide-eclipse-adt-ile-basit-bir-plugin-yazmak/

      • Ali dedi ki:

        Teşekkürler

  2. yakup dedi ki:

    Konuyla alakası yok kusura bakmayın ama çözemediğim bir sorunum var. ben bir int türünde a
    değişkeni tanımladım ve bunu Random.Range(1,10) şeklinde 1 ile 10 arasında rasgele bir sayı belirledim.daha sonra bir b değişkeni tanımladım.Sorum şu b değişkenini 1 ile 10 arasında rasgele bir sayı seçmek istiyorum ama b’nin a’ya hiçbir zaman eşit olmamasını istiyorum.Bunu nasıl yapabilirim?Teşekkürler

    • yasirkula dedi ki:

      Bunun için do-while kullanabilirsiniz:

      do
      {
      b = Random.Range( 1, 10 );
      } while( b == a ); // b’nin değeri a’ya eşit olduğu sürece b’ye tekrar random bir değer ver

  3. ali dedi ki:

    Merhaba 2d araba oyununda tekerlerimin yere değdiğini nasıl bilebilirim şöyle hill climp racing oyunundaki gibi araba yerdeyse ileri gidecek havadaysa arabayı kendi ekseni etrafında rotate fonksiyonuyla döndürecem tekerlerde circle collider2d var tekerlerin yere değdiğini nasıl anlarım

    • yasirkula dedi ki:

      Şuna benzer bir kod kullanabilirsiniz (ancak kendim test etmedim):

      public CircleCollider2D teker1, teker2;
      private Collider2D[] temp = new Collider2D[10];
      
      public bool TekerlerHavadaMi()
      {
      	return Physics2D.GetContacts( teker1, temp ) == 0 && Physics2D.GetContacts( teker2, temp ) == 0;
      }
      
      • ali dedi ki:

        kusura bakmayın ben biraz cahilim bu kodu nasıl kullanacam?

      • yasirkula dedi ki:

        Kodu araba scriptinizin içine yapıştırıp Inspector’dan Teker1 ve Teker2’ye teker objelerini vereceksiniz. Ardından araba scriptinde TekerlerHavadaMi() fonksiyonunu çağırarak tekerler havada mı (true) yoksa yerde mi (false) bulabilirsiniz.

      • ali dedi ki:

        teşekkürler

  4. iran dedi ki:

    Klavye indirdik haha .
    Yasir abi yemin ederim , Unitynin yapımcısın dan daha çok şey biliyorsun ,

    Çok sağol bunu da anladım.iki gündür esirdim 😱
    Tekrar dan teşekkür ederim.

  5. iran dedi ki:

    merhaba
    yasin bey ben kac tane oyun yapdim
    ama simdi Vector de kaldim
    Vector3.magnitude ne anlama geliyor?
    biliyorum vectorun uzunlugu , ama demedik mi ki Vector 3 bir nokta?
    bir noktanin uzunlugu mu var?
    bu kounuda deli oldum yardiiiiiiiiiiim

    • yasirkula dedi ki:

      Vector3 bir noktayı da temsil edebilir (bkz. transform.position) bir yönü de (bkz. transform.forward). Veya iki objenin transform.position’larını birbirinden çıkarırsak da, bu iki obje arasındaki yön vektörünü temsil eder. Vector3.magnitude, sadece vektör bir yönü temsil ettiğinde anlamlı olmakta. Vektör bir noktayı temsil ettiğinde ben de bir kullanım alanı görmüyorum.

      • iran dedi ki:

        mukemmel anlattiniz cok sagolun (shimdi bir sheyler zihnimde canlanmaya basladi)

        bir sorum daha var (ozur dileyerek):
        bu sorumda normalized’i niye kullaniyoruzu anlamak istiyorum (biliyouz ki normalized , bir vectorun uzunlugunu 1 yapiyor)

        player ve enemy arasindaki bi vectoru , iki objening positionunu bir birnne cikiyoruz;
        ve player in , enemy ye taraf hareket etmesi icin , player in simdiki positionunu , ele getirdigimiz Vector le topluyoruz;

        ben test eddim (* time.deltatime da yapdim) player , enemy ye dogru gitti ve hatta yapisdi;

        bazi yerlerde gordum , iki objenin arasindaki vectoru Normalize edib , ondan sonra playerin positionu yla topluyorlar , niye?

        Normalize edelim etmiyelim kod calisiyor ama herkes Normalize ediyor , neden?

        (turkcem biraz koto cun ki iranliyim , bide turkce kilavyem yok cok cok ozur diliyorum)

      • yasirkula dedi ki:

        Düşmanın player’a saniyede 5 birim hızla gitmesini istiyorsunuz diyelim. Ve diyelim ki düşman ile player arasındaki yön vektörünün magnitude’u 10. Bu durumda bu yön vektörünü direkt Time.deltaTime ile çarpıp kullanırsanız, düşman saniyede 5 değil 10 birim hızla gider. Ve düşman player’a yaklaştıkça, aradaki magnitude azalacağı için düşmanın hızı azalır. Ancak eğer yön vektörünü normalize edip 5 ile çarparsanız, vektörün magnitude’u daima 5 olur ve bu vektörü Time.deltaTime ile çarpıp kullandığınızda da düşman 5 birim/saniye hızla hareket eder.

  6. mehmet dedi ki:

    Merhaba Yasir Hocam Öncelikle Çalışmalarınıza hayranım Çok faydalı pylaşım lar yapıyorsunuz. sizden bir rıcam olucak ben basit bir sensor kodu arıyorum andrıid için yani bir kutu olucak o kutuyu telefonun sensorüyle hareket ettiricem yerinde hareket edicek sola ve sağa sadece.

  7. ahmet dedi ki:

    Merhabalar ben sonsuz bir araba yarışı yapıyorum bunun için üç adet teraain oluşturdum ve ilk terraine yolları ekledim istediğim şey şu bir obje terrain yada yol farketmez araba ileriye doğru giderken kameranın arkasında kalıp invisible oluyorsa onu ileriye taşımak istiyorum bunun için transform.translate komutunu kullandım ama bu kodu sadece obje kameranın arkasında kaldığı zaman taşımak istiyorum bunun yolu nedir

    birde mesala invisible olunca değilde kameranın arkasında kalınca taşınsın çünkü bazı yollar ve tarrain ler kameranın önünde ama onlarda görünmez vaziyette

    • ahmet dedi ki:

      merhabalar bu işi kamerayla değilde transform komutuyla çözmeye çalıştım

      kodum şu ,

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

      public class yol : MonoBehaviour {

      public Transform car;
      float araba, yol;

      void Update ()
      {
      araba = car.position.z;
      yol = gameObject.transform.position.z;

      if (araba > yol + 180)
      gameObject.transform.Translate(new Vector3(0, 0, 540));
      }
      }

      bu script yol için aynı scripti terrainlere uyguladığımda çalışıyor ama yollara uyguladığım zaman float limitlerinden dolayı olmuyor daha düşk değerli olarak girin falan dedi bende değeri 180 e kadar düşürdüm ama olmuyor terrainler kendini tekrar ederken yollar scriptte belirlenen değere ulaştığında ileri taşınmak yerine kayboluyorlar scene ekranından objeye tıklayıp f ye bastığı halde objeyi bulamıyorum halbuki hiyerarşide varlar

      • ahmet dedi ki:

        sonradan fark ettim ki yollar kaybolmuyor ama y eksenleri sürekli artıyor sürekli yukarıya doğru çıkıyorlar ama terrainlerde böyle bişey olmuyor sadece yollarda oluyor

    • ahmet dedi ki:

      Yolların taşınması sorununu cozdum translate komutunda translate(0,0,300 ) yerine translate (0,-300,0) seklinde kullanılınca oldu

      • ahmet dedi ki:

        Kusura bakmayın çok fazla yorum yaptığımın farkindayim ama oyunda translate kullanınca sanki biraz kasiyor gibi bu isi yapmanın başka bir yolu varmı?

      • yasirkula dedi ki:

        Elinize sağlık. Bir başka alternatif de transform.Translate(new Vector3(0, 0, 300), Space.World); fonksiyonunu kullanmak.

        Oyunu gerçekten kastıran şeyin Translate olup olmadığından emin olmak için Window-Profiler’dan faydalanabilirsiniz. O pencerede oyunu en çok kastıran şeyler en tepede yer alır. “Time ms” sütunu, ilgili işlemin kaç milisaniye sürdüğünü belirtir.

        Ayrıca dilerseniz optimizasyon dersime de göz atabilirsiniz: https://yasirkula.com/2016/06/19/unity-optimizasyon-onerileri/

      • ahmet dedi ki:

        teşekkür ederim şimdi kontrol ettim oyunun en fazla zorlayan şeyler translate komutunun olduğu fixedupdate fonksiyonu ama aşırı zorlayan bir fonksiyon bilgisayarda kendini belli etmesede telefonumda denediğimde oyun kare kare ilerliyordu ve hiç fps yoktu saniyede bir kare sanki unityde oyunu çalıştıtıken durdurup bi tık ileriye sardırmışşım gibi

        tek başına translate komutu bukadar zorlayabilirmi bilmiyorum ama diğer en çok işlem harcayan şeyler ise biri gtx ile başlayan ama ne olduğunu bilmediğim birşey diğeri ise intilaztion tarzı bişey ama yazımını blmiyorum

        optimizasyon dersinizide göz atacağım teşekkürler emekleriniz için

      • yasirkula dedi ki:

        Tek başına Translate’in oyunu dediğiniz kadar yavaşlatması pek olası gelmedi bana. Ancak şöyle bir şey deneyebilirsiniz: eğer Translate edilen objelerde Collider var ama Rigidbody yoksa, bu objelere “Is Kinematic”i işaretli bir Rigidbody verebilirsiniz.

        Eğer dilerseniz Profiler’ı, uygulama telefonunuzda çalışırken de kullanabilirsiniz. Bunun için Build Settings’te “Development Build” ve “Autoconnect Profiler” seçili iken Build&Run yapmalısınız. Uygulama açıldığı halde Profiler bir veri göstermiyorsa “Active Profiler”a tıklayıp telefonunuzu seçmeniz gerekebilir.

      • ahmet dedi ki:

        teşekkürler dediğim gibi telefon için uygulamanın apk’sını derleyip yüklediğim zaman dahada kötüleşip oyun kare kare ilerlemeye başladı.oyunun içinde 3 terrain var ve her terrainde yaklaşık 10 adet yol objesi ve 4 tane dekor objesi var yani toplam 45 tane obje var translate komutunu kullanan belki sayı fazladır bilemiyorum ama yeni bi method deneyeceğim sizin sonsuz yol dersinizi indirip scriptini anlamaya çalıştım ama yapamadım c# bilgim zayıf önce c#öğrenmek istiyorum ama youtube daki dersler visual studio odaklı dersler ve unity de kullanamayacağım şeyleride öğretiyorlar sizce bu dersleri öğrensem unity ye ne kadar faydalı olur

        bir diğer alternatif ise unitynin kendi scripting tutorialleri bunları pek inceleme fırsatım olmadı bu dersler gerçekten öğretiyormu programlamayı unity için bilginiz varsa söylerseniz iyi olur

        yoksa hem youtube daki visual studio için olanı hemde unity nin kendi tutoriallerini mi izlemeliyim
        yada boşver onları al şuna bak dediğiniz bi kaynak varmı

      • yasirkula dedi ki:

        Bence hem Visual Studio için olan tutoriallere hem de Unity’nin kendi tutoriallerine bakın. İlk başta C#’ın syntax’ı, sınıflar, koşullar vs. temeller oturana kadar Visual Studio için olan derslere ağırlık verin; ondan sonra ise artık Unity’nin kendi tutoriallerinden devam edin.

        Eğer C# dersleri size çok sıkıcı veya anlaşılması zor gelirse Java (Javascript değil!) derslerine de bakabilirsiniz; C# ile Java birbirine oldukça benzediği için onun da faydası olur.

      • ahmet dedi ki:

        teşekkürler

  8. ali dedi ki:

    Konuyla alakası yok ama bir şey sorabilirmiyim ben iki boyutlu ortamda hill climb tarzı bir oyun yazıyorum ve hareket kısmı bitti yani klavyede axis tuşlarına bastığımda ileri geri gidiyor ben bunu nasıl bi butona aktarabilirim mobil platformlar için hill climbte oldugu gibi butona basınca nasıl hareket ettirebilirim cevaplarsanız sevinirim şimdiden teşekkürler

    • yasirkula dedi ki:

      Şu dersteki input sistemini bu tarz durumlar için yazdım: https://yasirkula.com/2017/07/19/unity-gelismis-input-sistemi-mobil-destekli/

      Oradaki örnek sahneyi inceleyip sistemi kendi projenize yedirebilirsiniz.

      • ali dedi ki:

        Teşekkür ederim.Bir sualim daha var oyunda araba seçme menüsü eklemeyi düşünüyorum

        her haritaya arabaların hepsini, ekleyip set aktive degerlerini false olarak ayarlayacağım menüden seçtiği arabanın set aktif değeri true olacak ve sahne yüklenince seçtiği arabayı kullanacak bu sistem nasıl yapılır

        yada araba seçme ile ilgili daha güzel bir yontem varsa paylaşırmısınız şimdiden teşekkürler

      • yasirkula dedi ki:

        Konuyla ilgili video ders bulmak isterseniz “unity car selection menu” şeklinde arama yapabilirsiniz. İsterseniz her sahneye her arabayı koymak yerine arabaları Resources klasörüne koyup oyun başlayınca doğru arabayı şuna benzer bir kod ile oluşturabilirsiniz:

        GameObject araba = Instantiate( Resources.Load<GameObject>( "oluşturulacak araba prefab'ının ismi" ) );
        araba.transform.position = spawnPosition;
        araba.transform.rotation = spawnRotation;
        

        Araba seçme menüsünde seçilen araba prefab’ının ismini ise string türündeki public static bir değişkende tutarsanız oyun sahnesinden bu prefab’ın ismine kolayca erişebilirsiniz.

      • ali dedi ki:

        teşekkür ederim daha önce bu terimleri car selection menu yada car choosing menu aratmama rağmen birşey bulamamıştım ancak sizin verdiğiniz resources klasorunude aramaya katınca playerprefs diye bir konuyla karşılaştım inşallah işimi görür

        teşekkür ederim

  9. mert32 dedi ki:

    Bu I360Renderer class’ı size mi ait ?

  10. Ensar dedi ki:

    Hocam iyi günler. Başlıkla alakası yok ama bi sorum olacak. 2 boyutlu bi Sahnede bulunan karakterimizi sabit olarak artacak şekilde (5birim sağa) nasıl yaparım. Şuan karakter hareket ediyor ama geri gelmek istediğimde aynı noktaya gelmiyor. Yardımcı olursanız sevinirim.

  11. enceweb dedi ki:

    Faydalı bir çalışma olmuş hocam elinize sağlık…

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 )

Google+ fotoğrafı

Google+ 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 )

Connecting to %s

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