Reputation: 742
I am using a WebCamTexture and I start it in my Start
method, then I run another method. I get the pixels using GetPixels()
, however, they all come up as (0, 0, 0)
. Is there any fix to this or way I can wait (Unity seems to crash using while
loops and WaitForSeconds
). Here is my current Start method:
void Start () {
rawImage = gameObject.GetComponent<RawImage> ();
rawImageRect = rawImage.GetComponent<RectTransform> ();
webcamTexture = new WebCamTexture();
rawImage.texture = webcamTexture;
rawImage.material.mainTexture = webcamTexture;
webcamTexture.Play();
Method ();
loadingTextObject.SetActive (false);
gameObject.SetActive (true);
}
void Method(){
print (webcamTexture.GetPixels [0]);
}
And this prints a (0, 0, 0)
color every time.
Upvotes: 3
Views: 1573
Reputation: 508
Two seconds might be quite alot of time spend waiting when you're grapping the size of the requested image.
The WebCamTexture has a requsted width/height that you can access and it will save the "real" width/height of the texture after calling GetPixels once. We've used the asset called CameraCaptureKit (https://www.assetstore.unity3d.com/en/#!/content/56673 ) in two projects where we share photos with the users.
The codes used there takes the WebCamTexture and Graps the frames every frame until it returns a width and height of the texture.
In an update function TryDummySnapshot was called until the size was returned properly.
// ANDREAS added this: In some cases we apparently don't get correct width and height until we have tried to read pixels
// from the buffer.
void TryDummySnapshot( ) {
if(!gotAspect) {
if( webCamTexture.width>16 ) {
if( Application.platform == RuntimePlatform.IPhonePlayer ) {
if(verbose)Debug.Log("Already got width height of WebCamTexture.");
} else {
}
gotAspect = true;
} else {
if(verbose)Debug.Log ("Taking dummy snapshot");
if( tmpImg == null ) {}
Color32[] c = webCamTexture.GetPixels32();
}
}
}
Upvotes: 0
Reputation: 508
If you don't want to wait until a size is reported or allocate and the target platform is iOS (iPhone/iPad) it's also possible to write a plugin that gets the size directly from the Camera code in Unity by extending CameraCapture.mm :
- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection
{
intptr_t tex = (intptr_t)CMVideoSampling_SampleBuffer(&self->_cmVideoSampling, sampleBuffer, &self->_width, &self->_height);
_staticWebCamTexWidth = self->_width;
_staticWebCamTexWidth = self->_height;
UnityDidCaptureVideoFrame(tex, self->_userData);
if( self.firstFrameCallback!=nil ) {
[self fireFirstFrame];
}
}
self->width / height can be returned in a method added as a plugin method like :
[DllImport("__Internal")]
private static extern int GetWebCamTextureWidth ();
[DllImport("__Internal")]
private static extern int GetWebCamTextureHeight ();
and then in the objc code
extern "C" int GetWebCamTextureWidth() { return _staticWebCamTexWidth; }
extern "C" int GetWebCamTextureHeight() { return _staticWebCamTexHeight; }
This is the solution i came up with for one of iOS social games that uses unity. On Android we fell back on the previously described approach.
Upvotes: 0
Reputation: 125245
Do your webcam stuff in a coroutine then wait for 2 seconds with yield return new WaitForSeconds(2);
before calling webcamTexture.GetPixels
.
void Start () {
rawImage = gameObject.GetComponent<RawImage> ();
rawImageRect = rawImage.GetComponent<RectTransform> ();
StartCoroutine(startWebCam());
loadingTextObject.SetActive (false);
gameObject.SetActive (true);
}
private IEnumerator startWebCam()
{
webcamTexture = new WebCamTexture();
rawImage.texture = webcamTexture;
rawImage.material.mainTexture = webcamTexture;
webcamTexture.Play();
//Wait for 2 seconds
yield return new WaitForSeconds(2);
//Now call GetPixels
Method();
}
void Method(){
print (webcamTexture.GetPixels [0]);
}
Or like Joe said in the comment section. Waiting for seconds is not reliable. You can just wait for the width to have something before reading it.Just replace the
yield return new WaitForSeconds(2);
with
while (webcamTexture.width < 100)
{
yield return null;
}
Upvotes: 3