Merhabalar,

Bu Unity dersinde, Android ve iOS platformlarda nasıl cihazın galerisine resim/video kaydedebileceğinizi veya galeriden resim/video çekebileceğinizi göstereceğim. Bu iş için kendi yazdığım NativeGallery plugin’ini kullanacağız.

Hazırsanız başlayalım!

Kurulum

Öncelikle şu adresteki unitypackage‘ı Assets-Import Package yoluyla projenize import edin:  https://github.com/yasirkula/UnityNativeGallery/releases

Alternatif olarak, asset’i Asset Store’dan da import edebilirsiniz: https://assetstore.unity.com/packages/tools/integration/native-gallery-for-android-ios-112630

Eğer Android’e build alacaksanız Edit-Project Settings-Player‘daki Write Permission‘ı External (SDCard) yapın.

Eğer iOS’a build alacaksanız, Plugins/NativeGallery/Editor/NGPostProcessBuild.cs scriptindeki PHOTO_LIBRARY_USAGE_DESCRIPTION‘ın değerini dilerseniz değiştirin. Buraya girdiğiniz yazı, kullanıcıdan galeriye erişim izni isterken gözükecek.

Fonksiyonlar

A) Resim Kaydetmek

Galeriye resim kaydetmek için 3 farklı fonksiyon mevcut:

  • NativeGallery.SaveImageToGallery( byte[] mediaBytes, string album, string filename, MediaSaveCallback callback = null )

Eğer resmi bir byte array‘inde tutuyorsanız bu fonksiyonu kullanın. Bir texture‘un byte array’ine EncodeToPNG veya EncodeToJPG fonksiyonlarıyla erişebilirsiniz.

album: Resmin kaydedileceği albümü belirler.

filename: Resim dosyasının ismini belirler. Dosya ismine uzantıyı da eklemeyi unutmayın.

Resim Android’de DCIM/album/filename konumuna yazılırken iOS’ta ise cihazın galeri için rezerve ettiği özel bir konuma yazılır.

callback: Eğer buraya string parametre alan bir fonksiyon verirseniz, resmin kaydedilmesi bittikten sonra bu fonksiyon çağrılır. Eğer resim başarıyla kaydedildiyse bu string’in değeri null olurken bir hata olduysa hata mesajı bu string’de depolanır.

  • NativeGallery.SaveImageToGallery( string existingMediaPath, string album, string filename, MediaSaveCallback callback = null )

Eğer halihazırda varolan bir resim dosyasını galeriye kaydetmek istiyorsanız bu fonksiyonu kullanın. Bu durumda resim dosyası ilgili albüme kopyalanacaktır.

existingMediaPath: Varolan resim dosyasının konumunu buraya girmelisiniz.

  • NativeGallery.SaveImageToGallery( Texture2D image, string album, string filename, MediaSaveCallback callback = null )

Bir Texture2D objesini galeriye kaydetmek için bu fonksiyonu kullanabilirsiniz. Eğer filename parametresi .jpg veya .jpeg ile biterse texture JPEG formatında, yoksa PNG formatında kaydedilir.

B) Video Kaydetmek

  • NativeGallery.SaveVideoToGallery( byte[] mediaBytes, string album, string filename, MediaSaveCallback callback = null )

Eğer video’yu bir byte array‘inde tutuyorsanız bu fonksiyonu kullanın. Mesela projenizde yer alan bir video asset’ini bu fonksiyon ile galeriye kaydetmek isterseniz, videoyu scriptinizdeki bir TextAsset değişkenine değer olarak verebilir ve mediaBytes‘a değer olarak textAssetDegiskeni.bytes verebilirsiniz.

  • NativeGallery.SaveVideoToGallery( string existingMediaPath, string album, string filename, MediaSaveCallback callback = null )

Eğer halihazırda varolan bir video dosyasını galeriye kaydetmek istiyorsanız bu fonksiyonu kullanın. Bu durumda video dosyası ilgili albüme kopyalanacaktır.

C) Galeriden Resim Çekmek

  • NativeGallery.GetImageFromGallery( MediaPickCallback callback, string title = "", string mime = "image/*" )

callback: Kullanıcı galeriden bir resim seçince veya işlemi iptal edince bu fonksiyon çağrılır. Buraya vereceğiniz fonksiyon bir string parametre almak zorundadır. Eğer işlem iptal edildiyse bu parametrenin değeri null olurken aksi taktirde seçilen resim dosyasının konumu bu string’de depolanır.

title: Kullanıcının karşısına gelen resim seçme diyaloğunun başlığında yazan yazıyı belirler. Bu parametrenin iOS’ta bir etkisi yoktur.

mime: Galerideki resimleri filtrelemeye yarar. Varsayılan olarak tüm resimler gözükürken, mime’ı örneğin “image/jpeg” yaparsanız sadece JPEG resimler görünür. Bu parametrenin iOS’ta bir etkisi yoktur çünkü iOS’ta seçilen resimler daima PNG formatında olur.

D) Galeriden Video Çekmek

  • NativeGallery.GetVideoFromGallery( MediaPickCallback callback, string title = "", string mime = "video/*" )

Bu fonksiyon, GetImageFromGallery fonksiyonuna benzer şekilde çalışır. Galeriden bir video seçilince veya işlem iptal edilince callback fonksiyonu çağrılır.

E) Çalışma Zamanı İzinleri (Runtime Permissions) Hakkında

Android 6.0 sürümü itibariyle artık önemli bir Android fonksiyonuna erişmeden önce, çalışma zamanında bu fonksiyona erişim izni istemek zorundayız. NativeGallery fonksiyonları çalışmadan önce otomatik olarak izin isterler ancak dilerseniz kendi başınıza da izinlerin mevcut durumunu sorgulayabilir veya izin isteyebilirsiniz.

  • NativeGallery.CheckPermission( PermissionType permissionType )

İzinlerin durumunu sorgular ve bir NativeGallery.Permission enum‘u döndürür. Eğer galeriye erişim iznimiz varsa bu enum’un değeri Permission.Granted olurken eğer henüz iznimiz yoksa Permission.ShouldAsk olur. Eğer kullanıcı karşısına gelen izin ekranını “Bir daha sorma” seçili bir şekilde reddederse veya kullanıcının cihazında aktif olan bir ebeveyn kontrol sistemi bu iznin verilmesini engelliyorsa, Permission.Denied döndürülür. Bu durumda kullanıcı izni cihazın ayarlar menüsünden elle vermek zorundadır. Böyle bir durumla baş başa kalırsanız, kullanıcıya ayarlar menüsünden izin vermesini söyleyen bir uyarı penceresi göstermenizi öneririm. permissionType‘ın değeri, GetImage ve GetVideo fonksiyonları için NativeGallery.PermissionType.Read, SaveImage ve SaveVideo fonksiyonları için ise NativeGallery.PermissionType.Write olmalıdır.

  • NativeGallery.RequestPermission( PermissionType permissionType )

Galeriye erişim izni ister ve sonucu bir NativeGallery.Permission enum’unda döndürür. Resim kaydetmeye/çekmeye yarayan NativeGallery fonksiyonları bu fonksiyonu otomatik olarak çağırıp sonucu döndürürler.

F) Seçilen Resim Dosyasını Texture’a Çevirmek

  • NativeGallery.LoadImageAtPath( string imagePath, int maxSize = -1, bool markTextureNonReadable = true, bool generateMipmaps = true, bool linearColorSpace = false )

Bu fonksiyon vasıtasıyla bir resim dosyasını hızlıca bir Texture2D objesine çevirebilirsiniz.

imagePath: Texture2D olmasını istediğiniz resim dosyasının konumunu buraya girmelisiniz.

maxSize: Eğer resmin genişliği veya yüksekliği bu değerden büyük olursa, resmin bu boyuta küçültülmüş bir versiyonu döndürülür. Varsayılan olarak bir büyüklük limiti yoktur ancak resim ne kadar büyük olursa hafızada o kadar çok yer kaplayacağı için bu parametreye 512, 1024 vs. gibi işinizi görmeye yetecek bir değer vermeniz şiddetle önerilir.

markTextureNonReadable: Texture2D objesinin RAM’deki kopyasını silerek hafızayı rahatlatır. Bunun dezavantajı, artık resmin piksellerine elle erişemezsiniz; yani eğer GetPixel veya SetPixel fonksiyonlarını kullanıyorsanız bu parametreyi false yapın.

generateMipmaps: Texture’un mipmap’lerinin olup olmayacağını belirler.

linearColorSpace: Texture’un linear renk uzayını mı yoksa gamma renk uzayını mı (varsayılan) kullanacağını belirler.

Örnek Kod

Aşağıdaki örnek kodun 3 işlevi bulunmaktadır:

  • ekranın soluna tıklarsanız bir screenshot alınır ve bu screenshot galeriye kaydedilir
  • ekranın ortasına tıklarsanız galeriden bir resim seçmeniz istenir ve seçilen resim geçici bir küp objesine texture olarak verilir
  • ekranın sağına tıklarsanız galeriden bir video seçmeniz istenir ve seçilen video oynatılır
void Update()
{
	if( Input.GetMouseButtonDown( 0 ) )
	{
		if( Input.mousePosition.x < Screen.width / 3 )
		{
			// Screenshot al ve galeriye kaydet
			StartCoroutine( ScreenshotAlVeKaydet() );
		}
		else
		{
			// Eğer halihazırda bir resim/video seçme diyaloğu aktifse,
			// o diyalog kapatılana kadar bir şey yapma
			if( NativeGallery.IsMediaPickerBusy() )
				return;
 
			if( Input.mousePosition.x < Screen.width * 2 / 3 )
			{
				// Galeriden bir PNG resim çek
				// Eğer resmin genişliği veya yüksekliği 512 pikselden büyükse, resmi ufalt
				GaleridenResimCek( 512 );
			}
			else
			{
				// Galeriden bir video çek
				GaleridenVideoCek();
			}
		}
	}
}
 
private IEnumerator ScreenshotAlVeKaydet()
{
	yield return new WaitForEndOfFrame();
 
	Texture2D ss = new Texture2D( Screen.width, Screen.height, TextureFormat.RGB24, false );
	ss.ReadPixels( new Rect( 0, 0, Screen.width, Screen.height ), 0, 0 );
	ss.Apply();
 
	// Screenshot'ı galeriye kaydet
	Debug.Log( "İzin durumu: " + NativeGallery.SaveImageToGallery( ss, "Örnek albüm", "Resim.png" ) );
 
	// Artık screenshot'a ihtiyacımız kalmadı
	Destroy( ss );
}
 
private void GaleridenResimCek( int maksimumBuyukluk )
{
	NativeGallery.Permission izin = NativeGallery.GetImageFromGallery( ( konum ) =>
	{
		Debug.Log( "Seçilen resmin konumu: " + konum );
		if( konum != null )
		{
			// Seçilen resmi bir Texture2D'ye çevir
			Texture2D texture = NativeGallery.LoadImageAtPath( konum, maksimumBuyukluk );
			if( texture == null )
			{
				Debug.Log( konum + " konumundaki resimden bir texture oluşturulamadı." );
				return;
			}
 
			// Texture'u geçici bir küp objesine ver
			GameObject kup = GameObject.CreatePrimitive( PrimitiveType.Cube );
			kup.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 5f;
			kup.transform.forward = -Camera.main.transform.forward;
			kup.transform.localScale = new Vector3( 1f, texture.height / (float) texture.width, 1f );
 
			Material material = kup.GetComponent<Renderer>().material;
			if( !material.shader.isSupported ) // eğer Standard shader desteklenmiyorsa Diffuse shader'ı kullan
				material.shader = Shader.Find( "Legacy Shaders/Diffuse" );
 
			material.mainTexture = texture;
 
			// 5 saniye sonra küp objesini yok et
			Destroy( kup, 5f );
 
			// Küp objesi ile birlikte Texture2D objesini de yok et
			// Eğer prosedürel bir objeyi (Texture2D) işiniz bitince yok etmezseniz,
			// mevcut scene'i değiştirene kadar obje hafızada kalmaya devam eder
			Destroy( texture, 5f );
		}
	}, "Bir resim seçin", "image/png" );
 
	Debug.Log( "İzin durumu: " + izin );
}
 
private void GaleridenVideoCek()
{
	NativeGallery.Permission izin = NativeGallery.GetVideoFromGallery( ( konum ) =>
	{
		Debug.Log( "Seçilen videonun konumu: " + konum );
		if( konum != null )
		{
			// Seçilen videoyu oynat
			Handheld.PlayFullScreenMovie( "file://" + konum );
		}
	}, "Bir video seçin" );
 
	Debug.Log( "İzin durumu: " + izin );
}

Böylece bu dersin sonuna geldik. Sonraki derslerde görüşmek üzere!

Enes için bir cevap yazın Cevabı iptal et


70 yanıt

  1. Omer Avatar
    Omer

    Galeriden çekmiş olduğumuz resmi kare şeklinde değilde yuvarlak bir biçimde nasıl texture’a çevirebiliriz. Teşekkürler.

  2. Mahmut Can Avatar
    Mahmut Can

    Yasir bey merhaba, Native Gallery unity editor de kusursuz çalışmakta ama biz uygulamamızı apk olarak çıktığımızda ve bir telefonda test ettiğimizde resim ekleme butonuna basınca galeriden resim seçince seçtiğimiz resim uygulamaya aktarılmıyor sebebi sizce ne olabilir?

    1. yasirkula Avatar

      Logcat kullanarak aldığınız hata mesajlarına bakmanız lazım: https://yasirkula.com/2015/10/13/unity-android-oyunlarinizi-debug-etmek/

      1. Mahmut Can Avatar
        Mahmut Can

        Anladım Yasir bey, hemen denedik ve sonuçta böyle bir hata ile karşılaştık [Error wpa_supplicant IAPP SNAP_HDR Mismatch] bu sizce ne anlama gelmekte?

      2. yasirkula Avatar

        Daha önce görmediğim bir hata, benim plugin’imle bağlantılı olduğundan emin değilim. Galeriden resim seçtiğiniz andan itibaren birkaç saniye içinde gelen loglara bakın, daha önceki logları göz ardı edin.

      3. Mahmut Can Avatar
        Mahmut Can

        Resim eklemek için bastığımız butonun Image ne resmi ekletiyoruz ve butonun boyutuda bir dikdörtgen şeklinde acaba ondan dolayı eklememezlik yapıyo olabilir mi? Ya da belki kullanıcının android de bulunan resim path’ine erişemiyo da olabilir bilemedik açıkçası 😦 Teşekkürler bu arada yardımınız için.

      4. yasirkula Avatar

        Örnek kod çalışıyor mu?

      5. Mahmut Can Avatar
        Mahmut Can

        Aynen çalışıyor, Unity Editorde çok iyi çalışıyo, resimde geliyo. Andorid cihazda ise test ederken galeriye bağlanıyo ancak resim seçtikten sonra resim gelmiyo. Yani unity editorde çalışıp da android bir cihaz da çalışmaması ilginç değil mi?

      6. Mahmut Can Avatar
        Mahmut Can

        KOD BU ŞEKİLDE:

        public void pickImage()
        {
        int maxSize = 100000;
        string path_1 = “Assets/profilePhoto.png”;
        NativeGallery.Permission permission = NativeGallery.GetImageFromGallery((path) =>
        {

        Debug.Log(“Image path: ” + path);

        if (path != null)
        {
        string expath = path.ToLower();
        char[] charpath = expath.ToCharArray();

        for (int i = 0; i < charpath.Length; i++) // Blob için pathin içindeki türkçe harfler
        kaldırılmakta
        {
        if (charpath[i] == 'ı')
        {
        charpath[i] = 'i';
        }
        else if (charpath[i] == 'ö')
        {
        charpath[i] = 'o';
        }
        else if (charpath[i] == 'ü')
        {
        charpath[i] = 'u';
        }
        else if (charpath[i] == 'ğ')
        {
        charpath[i] = 'g';
        }
        else if (charpath[i] == 'ş')
        {
        charpath[i] = 's';
        }
        else if (charpath[i] == 'ç')
        {
        charpath[i] = 'c';
        }
        else if (char.IsWhiteSpace(charpath[i]))
        {
        charpath[i] = 'x';
        }
        }

        string realpath = new string(charpath); // değiştirilen path adı
        Debug.Log("Değiştirilen Path: " + realpath);

        Texture2D texture = NativeGallery.LoadImageAtPath(path, maxSize, false);
        Texture2D tex = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false);
        tex = texture;
        byte[] bytes = tex.EncodeToPNG();
        File.WriteAllBytes(path_1, bytes);
        // FindObjectOfType().label = GetComponent();
        FindObjectOfType().PutImage(bytes, realpath);
        UpdateAvatarUrlMethod(imageblobURL);

        Debug.Log(imageblobURL); //Resmin blob url’si imageblobURL string de saklı
        if (texture == null)
        {
        Debug.Log(“Couldn’t load texture from ” + path);
        return;
        }

        Sprite sprite = Sprite.Create(texture, new Rect(0.0f, 0.0f, texture.width, texture.height), new Vector2());
        AddImageButton.GetComponent().image.sprite = sprite;
        AddImageButton.GetComponent().image.color = Color.white;
        AddImageButton.GetComponentInChildren().text = “”;

        }
        }, “Select a JPG image”, “image/jpg”);
        }

      7. yasirkula Avatar

        Build alınan oyunda asset’leri düzenleyemezsiniz, yani File.WriteAllBytes(path_1, bytes); satırı çalışmaz. Logcat’te bu hata eminim gözükmüştür, iki defa logcat’e bakmanızı söylemiştim oysa.

      8. Mahmut Can Avatar
        Mahmut Can

        Aynen, çok saolun onu kaldırınca sorun da kalktı.

      9. Mahmut Can Avatar
        Mahmut Can

        Yasir bey kusura bakmayın rahatsız ediyorum bi sorun daha çıktı da şimdi bizim test ettiğimiz android 5.1 sürümlü android cihazda sorunsuz çalıştırdı ancak android sürümü 10 olan cihazda gene resim gelmedi. Bu neyden olabilir?

      10. yasirkula Avatar

        Maalesef bilmiyorum. Logcat’te bir hata var mı bakmanız lazım.

  3. Tayfun Avatar
    Tayfun

    Hocam çok güzel bir çalışma olmuş. Böyle açıklayıcı kaynaklar bulmak her zaman kolay olmuyor. Elinize sağlık. Galeriden seçtiğim fotoğrafı kısaca default olan fotoğraf ile değiştirmek istiyorum. Ancak fotoğrafı galeriden aldıktan sonrasını yapamadım. Yukarıda puzzle yapan arkadaş da tıpkı benim gibi galeriden aldığı fotoğrafı display etmek istemiş ve siz bir link bırakmışsınız ancak link kapatılmış. Yardımcı olabilirseniz çok mutlu olurum. İyi çalışmalar.

    1. yasirkula Avatar

      Orada linkini attığım plugin bu: https://github.com/yasirkula/UnityTextureOps/releases. Bununla işiniz olduğunu sanmıyorum. Siz galeriden aldığınız resmi Application.persistentDataPath’e “DefaultImage.png” ismiyle kaydetmeli (File.Copy ve Path.Combine) ve oyun tekrar açıldığında bu dosya var ise (File.Exists) direkt o dosyayı default resim olarak yüklemelisiniz (NativeGallery.LoadImageAtPath).

  4. Ömer Avatar
    Ömer

    Merhabalar bu güzel eklenti için çok teşekkür ederiz. Galeriden çekmiş olduğum resmin sahne değiştirince kaybolmaması için nasıl bir yol izleyebilirim ? Kullanıcıya sadece bir defa resim seçtirip onu profil fotoğrafı yapması ve bu fotoğrafın sonuna kadar kalmasını istiyorum.

    1. yasirkula Avatar

      Önce çekilen resmi File.Copy ile Application.persistentDataPath’e “profile.png” adıyla kaydetmeli, ardından bu konumda bu dosya varsa (File.Exists) her oyunun başında onu oradan yüklemelisiniz. Resmin sahneler arası kaybolmaması için onu bir static değişkende tutabilirsiniz.

      1. Ömer Avatar
        Ömer

        İlgilendiğiniz için çok teşekkür ederim, biraz araştırma yaptım nasıl yapabilirim bunu diye fakat tam olarak beceremedim sanırım 🙂 şöyle birşey denedim:
        static void CopyImage(){
        File.Copy(“Application.persistentDataPath”,”profile.png”);
        if (!File.Exists (Application.persistentDataPath + “/profile.png”));
        }

      2. yasirkula Avatar

        İhtiyacınız olan bilgiler:

        – string profilResmiKonum = Path.Combine(Application.persistentDataPath, “profile.png”); // Resmin depolanacağı konum
        – bool resimDosyasiMevcut = File.Exists(profilResimKonum); // Resim var mı yok mu
        – File.Copy(galeridenSecilenResminKonumu, profilResmiKonum); // Resmi kopyalamak

  5. efsane Avatar
    efsane

    event trigger de update selectedi sadece basılı tuttuğum sürece kullanmasını istiyorum android de düğmeye basınca veya baslılı tutunca hareket etsin düğmeyi bıraktığımda dursun olduğu yerde bunu nasıl yapabilirim

      1. efsane Avatar
        efsane

        sağolun yaptım ama build ederken bi hata ile karşılaştım android e build ediyorum bu hatayı alıyorum —— https://hizliresim.com/aFlXaF

  6. Enes Avatar
    Enes

    Hocam Merhabalar,
    Video kaydetme kısmı çok güzel fakat mobilde butona basılı tutup videoyu nasıl byte array içinde tutabilirim. Eğer bunu yapabilirsem sizin yazdığınız methoda direk verebilirim videoyu galeriye kaydetme kısmında.

    1. yasirkula Avatar

      Butona basılı tutunca ekran kaydı mı yapacaksınız? Bunun için ücretsiz bildiğim tek asset Everyplay. Onun haricinde Asset Store’daki ücretli plugin’lere bakabilirsiniz.

      1. Enes Avatar
        Enes

        Evet hocam. Basılı tutma fonksiyonunu nasıl halledebilirim onu soracaktım.

      2. Enes Avatar
        Enes

        Asseti indirdim de start recording gibi bir method göremedim sanırım save etmek için bir asset bu everyplay. Butona bastığımda kayıt etmeye başlayacak methodu hangisi acaba benimle paylaşırsanız çok memnun olurum.

      3. Enes Avatar
        Enes

        Hocam şimdi yaptım video ekranı açılıyor fakat ben AR uygulaması üzerinde çalışıyorum telefonun kamerasını değilde halihazırda açık ola AR kamerası üzernde video kaydı yapıcaktım. Onu nasıl kullanabilirim. Durum acil olmasa sizi rahatsız etmezdim hocam bu şekilde . Teşekkür ederim

      4. yasirkula Avatar

        Everyplay ile AR ekran kaydı alınıyor olması lazım. İhtiyacınız olan tüm fonksiyonlar şurada: https://github.com/Everyplay/everyplay-unity-sdk/blob/master/USAGE.md. Bir butona basınca ve basmayı bitirince ayrı ayrı bildirimler almak için, Event Trigger component’i kullanıp Pointer Down ve Pointer Up event’lerine kaydolabilirsiniz.

      5. Enes Avatar
        Enes

        Hocam Gradle problemi almaya başladım unity de platform olarak androidi seçtikten sonra. Önerdiğiniz bir çözüm yöntemi varmıdır acaba ?

      6. yasirkula Avatar

        Aldığınız hatayı Google’da aratmanızı öneririm. Çoğu hatanın çözümü Unity forumlarında veya başka yerlerde yazıyor.

  7. Can Avatar
    Can

    Hocam merhaba ben bu plugin ile beraber imagecropper plugininizide kullanıyorum, şimdi galeriden resim çekip imagecropperda crop ediyorum androidde veya ios’te benim crop ettiğim fotoğrafı telefona kaydedip kaydettiğim yerin konumunu almam lazım firebase storage’e yüklemek için.

    NativeGallery.SaveImageToGallery(croppedImage, “Album1”, “Resim”);

    Debug.Log(“benim save yerim: ” + Application.persistentDataPath);

    bu şekilde kaydediyorum ancak kaydedilen yerin tam adresini alamıyorum, SaveImageToGallery kodunu incelediğim zaman Application.persistentDataPath kısmına yüklendiğini gösteriyor yanlış anlamadıysam ancak orada öyle bir dosya yok, şimdi sizin burda yazdığınızı okuduğumdada DCIM/Album1/Resim.png şeklinde kaydettiğini görüyorum ancak bana string şeklinde full konumu vermesi gerek bunu nasıl alabilirim?

    Teşekkürler.

    1. yasirkula Avatar

      Bu path’i almak iOS’ta mümkün değil, Android’de ise %100 çalışan bir yöntem yok. Texture’u önce Application.persistentDataPath’e kaydetmenizi (texture.EncodeToPNG ve File.WriteAllBytes ile) ardından bu konumu SaveImageToGallery fonksiyonuna ve Firebase’e vermenizi öneririm.

  8. Mahmutcan ZAMAN Avatar
    Mahmutcan ZAMAN

    Merhaba hocam dediğiniz işlemleri yaptım resimi sprite a atadım. Bu resmi resources kısmına kaydetmek istiyorum.(Oyun dosyalarında kayıtlı kalmasını istiyorum sürekli kullanabilmek için) nasıl project kısmına kayıt alabilirim aldığımız resimi?

    1. yasirkula Avatar

      Bunu sadece editörde yapmak istiyorsanız mümkün ama anladığım kadarıyla build aldığınız oyunda yapmak istiyorsunuz, oyunu build aldıktan sonra Resources klasörünü değiştiremezsiniz. Dosyayı sadece Application.persistentDataPath veya Application.temporaryCachePath klasörlerine kaydedebilirsiniz.

  9. Ahmet Gül Avatar
    Ahmet Gül

    Hocam çok rahatsız ettim ama gelen fotoğrafı kodlarla otomatik 16 parçaya slice etme şansım var mı

    1. yasirkula Avatar

      Şuradaki Slice fonksiyonu ile yapabilirsiniz: https://github.com/yasirkula/UnityTextureOps

  10. Mahmutcan zaman Avatar
    Mahmutcan zaman

    Hocam texture olarak resmi galeriden aldığımız da unity içerisinde bir image içine tam oturacak şekilde nasıl tanımlayabilirim.Yada gelen resmi hiyerarşiye nasıl kaydedebilirim.

    1. yasirkula Avatar

      Resmi Hierarchy’e kaydetmeyi anlayamadım ama resmi Image’ın sprite’ına atayabilmek için önce LoadImageAtPath ile Texture oluşturmalı, sonra Sprite.Create ile o Texture’dan Sprite oluşturmalısınız: imageObj.sprite = Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f), 100.0f);

      1. Mahmutcan zaman Avatar
        Mahmutcan zaman

        Hocam kusura bakmayın yeni başladım. Rahatsız ediyorum sürekli. The name ‘sprite’ does not exist in the current context diye bir hata aldım, dediğinizi yaparak. Bu konuda ki gördüğüm tek kaynak da sizsiniz bu konuda elinize sağlık.

      2. yasirkula Avatar

        public Image imageObj; değişkeni oluşturup Inspector’dan değer vermeniz lazım.

  11. Ahmet Gül Avatar
    Ahmet Gül

    Hocam galeriden aldığım fotoğrafı kırpmak ve çözünürlüğünü değiştirmek istiyorum. Örneğin 1920*1080 bir fotoğrafı seçtikten sonra kare şekilde kırpıp sonradan çözünürlüğü 1000*1000 şeklinde sabit ayarlamak istiyorum. Mümkün müdür ?

    1. yasirkula Avatar

      Resmi oyuncu elle istediği yerden mi kırpacak yoksa kod ile resmin orta kısmı otomatik mi kırpılacak?

      1. Ahmet Gül Avatar
        Ahmet Gül

        Oyuncu 1000*1000 piksel
        bir kare alanın içinde sürükleyerek kırpacak. En son kendi istediği yeri seçmiş olacak ama çözünürlük 1000*1000 olacak

      2. yasirkula Avatar

        Şu plugin ile kırpma işlemini yapabilirsiniz: https://github.com/yasirkula/UnityImageCropper. Şu örnek koddaki croppedImageResizePolicy içerisinde width ve height değerlerini 1000 yaparsanız, oyuncu ne kadar büyük veya ne kadar küçük bir alan seçmiş olursa olsun en son Texture 1000×1000 çözünürlüğünde olur. selectionMinAspectRatio ve selectionMaxAspectRatio’ya değer olarak 1f verirseniz, oyuncunun seçimi daima kare şeklinde olur.

  12. Ali Avatar
    Ali

    Merhaba
    ResimSec.cs(56,49): error CS1501: No overload for method ‘GetImageFromGallery’ takes 4 arguments

    eklentiyi projeye aktadım fakat bu şekilde bir hata alıyorum. Nasıl çözülebilir ?

    Unity 2019.3.15f1

    1. Ali Avatar
      Ali

      Hocam githubda eklentiyi yeniledim bu sefer bu şekilde bir konsol hatası alıyorum..

      Copying assembly from ‘Temp/com.unity.multiplayer-hlapi.Runtime.dll’ to ‘Library/ScriptAssemblies/com.unity.multiplayer-hlapi.Runtime.dll’ failed

    2. yasirkula Avatar

      O fonksiyonun dokümantasyonu eski kalmış, şimdi güncelledim. Aldığınız diğer hata NativeGallery ile alakalı değil; eğer konsolu Clear yapınca hata gidiyorsa, hatayı yoksayabilirsiniz. Aksi taktirde bir şekilde Unity’nin HLAPI multiplayer package’ı sıkıntı çıkarıyordur. Multiplayer oyun yapmıyorsanız Package Manager’dan HLAPI/Multiplayer’ı çıkarabilirsiniz.

  13. Furkan Çalışkan Avatar
    Furkan Çalışkan

    Hocam merhabalar,
    Kullanıcı, resim seçme menüsüne girdiğinde ana sunucuyla olan bağlantısı direk kesiliyor.
    Uygulamayı arkaplana alınca da direkt timeout hatası veriyor.
    Bunu nasıl engelleyebilirim?

    1. Furkan Çalışkan Avatar
      Furkan Çalışkan

      Sorunu çözdüm. Aynı sorunu yaşayan arkadaşlar için yazıyorum. Telefonunuz güç tasarruf modunda ise yaptığınız uygulamayı arkaplana alır almaz görevi sonlandırıyor. Bunun için telefon ayarlarından güç tasarrufunu kapatabilir veya uygulama profiline girip yaptığınız uygulamaya özel güç tasarrufunu kapatabilirsiniz. Kod ile izin alınarak yapılabilse güzel olurdu, bilen arkadaşlar varsa yazabilirlerse memnun olurum.

  14. Saffet Avatar
    Saffet

    merhabalar. emeğiniz için çok teşekkürler..
    acemi olduğum için tam çözemedim. bu dersin finalinde bu linkteki uygulamaya benzer bir sonuç
    alabilir miyim.. yani istediğim sadede uygulamayı kullanan bilgisayarından yada android’ inden
    materyal üzerine dokusunu kendi atabilsin
    Link

    1. yasirkula Avatar

      Evet yapabilirsiniz ama NativeGallery sadece Android ve iOS’ta çalışır, PC’de ya resmin konumunu önceden bilmeniz lazım ya da şuna benzer bir plugin kullanmanız lazım: https://yasirkula.com/2018/06/05/unity-oyun-ici-dosya-secme-kaydetme-penceresi-android-destekli/. Dosyanın konumunu elde ettikten sonra, obje.GetComponent<Renderer>().material.mainTexture = NativeGallery.LoadImageAtPath(dosyaKonumu); fonksiyonunu çağırabilirsiniz.

  15. Faruk Avatar
    Faruk

    hocam firebase ile ilgili bir eğitim yazarmısınız

    1. yasirkula Avatar

      Şu anda Firebase veya Google Play Services gibi servisler için ders planlamıyorum. Halihazırda yazmayı planladığım başka dersler var ama onlara bile zaman bulamıyorum şu anda.

  16. Baki Şahin (@solobasay) Avatar

    Merhabalar,
    Öncelikle paylaşımınız için çok teşekkür ederim ancak ufak bir sorum olacak:
    Kullanıcının seçtiği resmi firebase stroge’ye upload etmek istiyorum. Teoride her şey düzgün ancak android cihazımda deneyince upload işlemi işe yaramıyor.
    Android’de /storage/emulated/0/… şekilde bir konum alıyorum, konum alma işlemi çalışıyor ancak firebaseye bu konumdaki dosyayı yüklemesini söyleyince işe yaramıyor. Aynı şeyi bilgisayarda C:/user/Downloads/… tarzı bir konum ile deniyorum ve bilgisayarda sıkıntısız çalışıyor. Yine de Android’de hatayı ve sebebini çözemedim.
    Bu konuda yardımcı olabilir misiniz? Şimdiden teşekkürler

    1. yasirkula Avatar

      Firebase bir hata döndürüyor mu? Kontrol etmek için logcat kullanabilirsiniz: https://yasirkula.com/2015/10/13/unity-android-oyunlarinizi-debug-etmek/

      Ayrıca isterseniz dosyayı System.IO.File.Copy ile Application.persistentDataPath klasörü içerisine kopyalayıp ardından bu kopyaladığınız dosyayı yüklemeye çalışabilirsiniz.

  17. Furkan Çalışkan Avatar
    Furkan Çalışkan

    Selamlar hocam, kullanıcıdan resim yükletip profil resmi olarak veritabanına kaydetmek istiyorum. Fakat yazdığınız konum değişkeninden ve callback fonksiyonundan pek bir şey anlayamadım.

    public string deneme;

    NativeGallery.GetImageFromGallery(deneme, “Profil Resmi”, “image/*”, 512);

    deneme kısmı hata veriyor.

    Kullanıcının, eklediğim butona bastığında galerisinin açılmasını ve oradan resim seçmesini nasıl yapabilirim?

    1. yasirkula Avatar

      Örnek koddaki GaleridenResimCek fonksiyonunu inceleyebilirsiniz. Oradaki “// Texture’u geçici bir küp objesine ver” comment’inden sonrasını, resmi veritabanına kaydetme kodunuzla değiştirebilirsiniz.

      1. Furkan Çalışkan Avatar
        Furkan Çalışkan

        GaleridenResimCek fonksiyonundaki konum değişkeninin türü nedir?

      2. Furkan Çalışkan Avatar
        Furkan Çalışkan

        Yazdığınız kodu kopyala yapıştır yapınca düzeldi hocam. Sanırım ileri düzey bir kod olduğundan anlamakta zorlandım 🙂 Teşekkür ederim.

    2. nur Avatar
      nur

      İyi günler Firebase resim yükleme konusunda bir kaynak bulamadığım için size sormak istedim acaba Firebase ekleme işlemini nasıl gerçekleştirdiniz ?

  18. enes beser Avatar
    enes beser

    çok saolun hocam peki 10 tane resim seçtirmek istesem max galeriden bunları 2d imageler içerisine atmak istiyorum nasıl olur texture ı image e dönüştürmeyi birtaz araştırdım kafam karıştı yardımcı olursanız sevinirim 2 konuda da

    1. enes beser Avatar
      enes beser

      ios ve android için

    2. yasirkula Avatar

      Texture oluşturmak için “Seçilen Resim Dosyasını Texture’a Çevirmek” kısmındaki fonksiyonu kullanabilirsiniz. Birden çok resim seçtirmek için ekranda bir + tuşunuz olabilir ve kullanıcı buna her bastığında yeniden NativeGallery.GetImageFromGallery fonksiyonunu çağırırsınız.

  19. Erol ŞIVKIN Avatar
    Erol ŞIVKIN

    Çok teşekkürler hocam sağolun. Keşke UDEMY’de kapsamlı bir eğitim hazırlasanız.

  20. Erol Şıvkın Avatar
    Erol Şıvkın

    Hocam çok yararlı bir ders olmuş. Teşekkürler. Ben basit bir puzzle yaptım da android için. Galeriden resim seçtirdim sizin metodunuzla. Seçtiğim resmi sahneye alabilir miyim? Sahnede hazır bir resim var ve ben sprite editor ile 6 ya böldüm. Kodlar şöyle;

    // Use this for initialization

    [SerializeField]
    private Transform[] pictures;

    [SerializeField]
    private GameObject winText;

    public static bool youWin;

    private void Start()
    {

    winText.SetActive(false);
    youWin = false;
    }

    private void Update()
    {

    if (pictures[0].rotation.z == 0 &&
    pictures[1].rotation.z == 0 &&
    pictures[2].rotation.z == 0 &&
    pictures[3].rotation.z == 0 &&
    pictures[4].rotation.z == 0 &&
    pictures[5].rotation.z == 0)

    {
    winText.SetActive(true);
    youWin = true;
    }
    }

    public void Kapat()
    {

    Application.Quit();

    }
    public void GaleridenResimCek()
    {
    // ÖRNEK KOD
    }

    İyi çalışmalar.

    1. yasirkula Avatar

      Resmi kaç satır kaç sütun olacak şekilde böldünüz (örneğin 2×3)? Ayrıca, rotation.z yerine eulerAngles.z yapmanız gerekebilir.

      1. Erol ŞIVKIN Avatar
        Erol ŞIVKIN

        Hocam 6 hücre yani 2 satır 3 sütun olacak şekilde.

      2. yasirkula Avatar

        Öncelikle projenize şu plugin’i import edin: https://github.com/yasirkula/UnityTextureOps/releases

        Ardından NativeGallery’den elde ettiğiniz resmi bir Texture’a çevirip bu Texture’u şu fonksiyon vasıtasıyla 6 parçaya bölebilirsiniz:

        public Sprite[] ResmiParcalaraBol( Texture2D resim )
        {
        	Texture2D[] parcalar = TextureOps.Slice( resim, resim.width / 3, resim.height / 2, TextureFormat.RGB24 ); // 2 satır 3 sütun
        	
        	Sprite[] sonuc = new Texture2D[parcalar.Length];
        	for( int i = 0; i &lt; parcalar.Length; i++ )
        		sonuc[i] = Sprite.Create( parcalar[i], new Rect( 0.0f, 0.0f, parcalar[i].width, parcalar[i].height ), new Vector2( 0.5f, 0.5f ), 100.0f );
        	
        	return sonuc;
        }