Merhaba,
Bu derste, Unity’de bir webcam’e (ya da bir kameraya) erişip onun görüntüsünü oyun motoru içinde kullanmayı göstermeye çalıştım. Kodları comment’leyerek neyin ne olduğunu kısaca açıkladım. Zaten tek bir script yeterli; o da oldukça kısa bir script.
NOT: Bu webcam olayı tüm cihazlarda (cep telefonları dahil) çalışıyor ancak eğer webcam kullanan bir Android uygulaması yaparsanız uygulama kurulmadan önce uygulamanın istediği izinler arasında “Hardware controls : take pictures and videos” da gözüküyor.
Kodu görmek için yazının devamını okuyabilirsiniz…
WebcamTest adında yeni bir C# script oluşturup içeriğini aşağıdaki gibi değiştirmeniz ve bu objeyi webcam görüntüsünü hangi objede göstermek istiyorsanız ona component olarak vermeniz yeterli. Bu objede Mesh Renderer gibi bir component olmalı ve objenin z ekseni (mavi eksen), webcam görüntüsünün görünmesini istediğiniz yöne doğru bakmalı.
using System.Collections; using UnityEngine; public class WebcamTest : MonoBehaviour { private WebCamTexture webcam; private int mevcutWebcam; // Cihazda birden çok webcam varsa aralarında geçiş yapmak için kullanacağımız bir kod private WebCamDevice[] webcamCihazlari; // Aygıttaki tüm webcam'leri depolayan bir değişken private Quaternion anaRotasyon; // Kameranın ekrana yamuk yumuk açılarla yansımasını engellemek için bir değişken IEnumerator Start() { // Webcam'e erişmek için kullanıcıdan izin istememiz gerekiyor mu kontrol et if( !Application.HasUserAuthorization( UserAuthorization.WebCam ) ) { // Kullanıcının izni gerekiyor, izin iste ve bekle yield return Application.RequestUserAuthorization( UserAuthorization.WebCam ); // Kullanıcı izin vermezse script'i objeden kaldır if( !Application.HasUserAuthorization( UserAuthorization.WebCam ) ) Destroy( this ); } webcamCihazlari = WebCamTexture.devices; // Eğer cihazda en az 1 tane webcam varsa, 0. indexteki webcam cihazını "webcam" değişkenine ata; eğer webcam yoksa hata mesajı ver if( webcamCihazlari.Length != 0 ) { webcam = new WebCamTexture( webcamCihazlari[0].name ); mevcutWebcam = 0; } else { Debug.LogError( "Hata! Cihazda webcam bulunamadı." ); // Hata mesajının ardından bu scripti objeden kaldır Destroy( this ); } // Objeye texture olarak webcam görüntüsünü ata GetComponent<Renderer>().material.mainTexture = webcam; // Webcam'den veri almaya başla (webcam'i çalıştır) webcam.Play(); anaRotasyon = transform.rotation; } void Update() { // Her kameranın kendine has bir çekim açısı olabilir. Bu kod, objeyi kameranın çekim açısına göre otomatik olarak döndürüyor (benim de tam anlamadığım bir şekilde) transform.rotation = anaRotasyon * Quaternion.AngleAxis( webcam.videoRotationAngle, Vector3.forward ); } void OnGUI() { // Webcam'i duraklatmak/devam ettirmek ya da durdurmak için ekranın sol üstüne butonlar ekle if( webcam.isPlaying ) { if( GUI.Button( new Rect( 10, 10, 100, 50 ), "DURAKLAT" ) ) webcam.Pause(); if( GUI.Button( new Rect( 10, 70, 100, 50 ), "DURDUR" ) ) webcam.Stop(); } else { if( GUI.Button( new Rect( 10, 10, 100, 50 ), "OYNAT" ) ) webcam.Play(); } // Görüntüyü ters çevirmek için butonlar ekle if( GUI.Button( new Rect( 10, 150, 100, 50 ), "DİKEY ÇEVİR" ) ) { Vector3 scale = transform.localScale; scale.y = -scale.y; transform.localScale = scale; } if( GUI.Button( new Rect( 10, 210, 100, 50 ), "YATAY ÇEVİR" ) ) { Vector3 scale = transform.localScale; scale.x = -scale.x; transform.localScale = scale; } // Eğer varsa başka kameralara geçmek için buton ekle if( webcamCihazlari.Length > 1 ) { if( GUI.Button( new Rect( 120, 10, 100, 50 ), "KAMERA DEĞİŞ" ) ) WebcamDegistir( ( mevcutWebcam + 1 ) % webcamCihazlari.Length ); } // Eğer cihazda ön kamera varsa ilk ön kameraya geçiş yapmayı sağlar if( GUI.Button( new Rect( 230, 10, 120, 50 ), "ÖN KAMERA" ) ) { for( int i = 0; i < webcamCihazlari.Length; i++ ) { // Eğer bu webcam öne bakıyorsa mevcut kamerayı buna ayarla if( webcamCihazlari[i].isFrontFacing ) { WebcamDegistir( i ); return; } } } // Eğer cihazda arka kamera varsa ilk arka kameraya geçiş yapmayı sağlar if( GUI.Button( new Rect( 360, 10, 120, 50 ), "ARKA KAMERA" ) ) { for( var i = 0; i < webcamCihazlari.Length; i++ ) { // Eğer bu webcam arkaya bakıyorsa mevcut kamerayı buna ayarla if( !webcamCihazlari[i].isFrontFacing ) { WebcamDegistir( i ); return; } } } } private void WebcamDegistir( int yeniWebcam ) { // Mevcut webcam'den görüntü almayı bırak webcam.Stop(); // Artık kullanmayacağımız webcam görüntüsünü yok ederek hafızayı boşalt Destroy( webcam ); // Yeni webcam'e geçiş yap mevcutWebcam = yeniWebcam; webcam = new WebCamTexture( webcamCihazlari[mevcutWebcam].name ); GetComponent<Renderer>().material.mainTexture = webcam; // Yeni webcam'i çalıştır webcam.Play(); } }
Merhabalar unityi yeni kurdum youtubedaki bir çok videyu izleyerek ekrana AR camera ekliyorum.Fakat run yaptığımda kamera çalışmıyor.Şöyle bir hata alıyorum:
Exception in callback: Failed to create ImageTargetObserver: DATABASE_LOAD_ERROR.
UnityEngine.Debug:LogErrorFormat (string,object[])
Vuforia.Internal.Utility.UnityLogger:LogError (string,object[])
Vuforia.Internal.Utility.Log:Error (string,object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeDelegate (System.Delegate,object[])
Vuforia.Utility.ExtensionMethods.DelegateHelper:InvokeWithExceptionHandling (System.Action`1,Vuforia.VuforiaInitError)
Vuforia.Internal.Core.Engine:InitOnCameraReady ()
Vuforia.WebCam:HandleFirstWebCamFrame ()
Vuforia.WebCam:b__33_0 (bool)
Vuforia.Internal.Utility.VuforiaCoroutineUtility/d__1:MoveNext ()
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
PC webcami AR kamerayı desteklemiyor olabilir mi?
PC webcam’inin sorun çıkarmaması lazım. Hatayı arattığımda Vuforia’yı yeniden kurunca düzeldiğini söyleyen de buldum, Vuforia sürümünü 10.0’dan 9.8‘e çekince düzeldiğini söyleyen de. Maalesef daha fazla yardımcı olamıyorum çünkü Vuforia ile en son çalışalı çok uzun zaman oldu.
Hocam merhaba bir uygulama yaptım pc için build aldım ama .exe açıyorum açılıyor sıkıntı yok. Fakat uygulamanın bir kısmın da kameranın açılması gerekiyor ama açılmıyor. Büyük ihtimal build alırken kamera izni falan vermem gerekiyor ama bulamadım. Fikriniz varsa yardımcı olur musunuz?
Derste paylaştığım örnek kod .exe alınca çalışıyor mu?
Merhaba. Görüntüyü istediğim gibi alıyorum. Texture olarak maretiale verip ekrana verebiliyorum sorun yok. Bir kaç gündür bu materiali bayt a çevirip İnternette bir mssql veritabanına yazdırıp, başka cihazdan almayı deniyorum. Fakat başaramadım. Yani yapmaya çalıştığım karşılıklı iki kişi canlı bir şekilde görüntü paylaştırmak, sonraki adımda sesi paylaştırmaya çalışacağım. Bu sistem Veritabanı yöntemi ile sağlıklımı? Değilse firmalar hangi yöntemi kullanıyor? Eğer sağlıklı ise nasıl yapabilirim? Bir fikriniz var mı?
WebCamTexture’u byte[]’a çevirerek yollamayın çünkü bu çok yavaş olur ve byte[]’ta bir sıkıştırma işlemi yapılmadığı için, çok fazla veri aktarımı anlamına gelir (15 fps’te yollasanız ve her frame 100KB olsa, saniyede 1.5 MB oluyor). Onun yerine, hazır plugin’ler kullanın. “unity video chat” şeklinde arama yaparak birkaç alternatif plugin görebilir ve bunları kendiniz kıyaslayabilirsiniz (benim tecrübem olmadığından bir öneride bulunamıyorum).
Cevabınız için teşekkür ederim. Pluginleri inceleyeceğim. Peki farklı bir alternatif olarak, resim olarak kayıt etsem servera sonrada sadece karşı cihazın resmini mevcut cihaza yükleyip ekrana bassam sizce şişme veya perfonmans açısından sorun yaratır mı? Tabi denemek lazım ama sadece mantık ve tecrübe açısından düşünürsek diye mantık yürütüyorum.
Resimden kastınız WebCamTexture’u her saniye 15 kere JPEG veya PNG’e çevirip karşıya yollamaksa, cevabımda bahsettiğim sıkıştırma işlemi olmaması olayı bu; yani yine çok şişer. MP4 videolar nasıl sıkıştırılıyor bilmiyorum ama her frame ayrı bir resim olarak sıkıştırılmıyordur diye düşünüyorum, öyle olsa videolar aşırı yer kaplardı.
Haklısınız. Bir eklenti buldum. 10.000 dakika ücretsiz veriyor. Onu bir deneyeceğim. Yardımlarınız için teşekkür ederim.
Merhaba hocam. Kodları bir plane bağladım görüntü alıyorum fakat ön kamerada sağa yatırınca sola sola yatırınca sağa dönüyor. Rotation ayarlarıyla oynadım ama bi sonuç alamadım. Yardımcı olabilir misin?
Derste webcam.videoRotationAngle’dan faydalanıyorum. Eğer bu sizde bir işe yaramadıysa, plane’i elle 90 derece döndürmekten başka bir seçenek olmayabilir.
hocam hayırlı akşamlar,
ben bir objenin üzerindeki dokuyu slider ile nasıl kontrol ederek döndürebilirim?
daha anlaşılır olsun diye şu şekilde örnek vereyim; Duvara tuğla dokusunu ekledim ve duvara tıkladığımda tuğla dokusunu duvar oynamadan istediğim gibi nasıl döndürebilirim.
Materyalin mainTextureOffset değerini değiştirebilirsiniz: https://docs.unity3d.com/ScriptReference/Material-mainTextureOffset.html
UV Rotation değerini nasıl değiştirebilirim? Ve bunu bir slidere nasıl bağlayabilirim.
Kendi shader’ınızı yazmadan bunu yapmanız mümkün değil diye biliyorum, örnek shader’lar için: https://forum.unity.com/threads/rotation-of-texture-uvs-directly-from-a-shader.150482/
çok teşekkür ederim halletmeye çalışırım
Properties
{
_MainTex(“Texture”, 2D) = “white” {}
_UvRotation(“UV Rotation”, float) = 0
}
SubShader
{
Tags { “Queue” = “Transparent” “RenderType” = “Transparent” }
Blend SrcAlpha OneMinusSrcAlpha
ZTest on
ZWrite off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include “UnityCG.cginc”
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _UvRotation;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
fixed cosr = cos(_UvRotation);
fixed sinr = sin(_UvRotation);
fixed2x2 uvrotation = fixed2x2(cosr, -sinr, sinr, cosr);
float2 uv = mul(UNITY_MATRIX_M, v.vertex).xz * _MainTex_ST.xy;
o.uv = mul(uvrotation, uv);
o.color = v.color;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return fixed4(col.rgb, i.color.a);
}
ENDCG
}
}
//Bu şekilde shader kullandıktan sonra bunun UV Rotation değerine bir slider ile değişken nasıl yaratabilirim,?
Slider’ın On Value Changed’inde materyal.SetFloat(“_UvRotation”, sliderDegeri); kodunu çağırabilirsiniz.
(mevcutWebcam + 1 ) % webcamCihazlari.Length );
Hocam ben bunu tam anlamadım
mevcutWebcam değişkeni, webcamCihazlari array’inde kaçıncı sıradaki webcam cihazının şu anda aktif olduğunu belirtmekte. Bir sonraki webcam’i çalıştırırken mevcutWebcam’in değerinin, webcamCihazlari’nın sınırları dışına taşmadığından emin olmamız lazım. Koddaki % işareti “bölümden kalan” anlamına geliyor, yani “4 % 3” yazarsak bu 4’ün 3’e bölümünden kalanı döndürür. 4 yerine ne yazarsak yazalım sonuç [0,2] aralığında olur. Yazdığım kodda ise, %’un döndürdüğü değer daima [0,webcamCihazlari.Length-1] aralığında oluyor, yani webcamCihazlari’nın sınırları dahilinde oluyor.