2015年7月18日 星期六

How to Access Android Camera in Unity (I): Using Unity WebCamTexture

Overview

    This article will show you how to access Camera in Android device by calling the Unity built-in class: WebCamTexture. This is simply the easiest way to access the native camera.
    However, there're not so much parameters (such as Exposure, Zoom Level) can be adjusted. But if none of those in your concern, WebCamTexture might be the best way to approach. Since you can combine it with other Unity utilities (such as UI, sound) with WebCamTexture easily.
    Moreover, there're many websites have discussed how to use WebCamTexture, but none of them use the new Unity feature UGUI till now, this article will also show you how to combine WebCamTexture with UGUI.

Background

    Our company want to develop a game in a device which use Android as its OS. During the game, the camera in the devices will take some snapshots of the Players' face and print the picture for them as a souvenir.

Solution

Note: This article is original combine WebCamTexture and UI.Image. However, it will create a big array to contain pixels each frame. The game will finally run out of memory. Fortunately, this website suggest the use of UI.RawImage. This article has been updated to use such RawImage.

1. Setup the Unity Editor by following arrangement:
    (1) A parent Game Object "WebCamModule" that has Canvas as its Component.
    (2) A child Game Object "VedioImage" that has RawImage component. The RawImage is used to
          preview the camera.
    (3) Attach the "WebCamModule" Game Object by the following script:
 public class WebCamModule : MonoBehaviour
 {
   private WebCamTexture webCameTexture;
   [SerializeField] private RawImage vedioImage;

   protected void Awake()
   {
    this.webCameTexture = new WebCamTexture(1280, 720);
    this.vedioImage.texture = this.webCameTexture;
   }

   public void Play()
   {
     this.webCameTexture.requestedWidth = 1280;
     this.webCameTexture.requestedHeight = 720;
     this.webCameTexture.Play();
   }
   public void Stop()
   {
     this.webCameTexture.Stop();
   }
   public Texture2D TakePhoto()
   {
    Texture2D photoShot = new Texture2D(this.webCameTexture.width, this.webCameTexture.height);
    photoShot.SetPixels32(this.webCameTexture.GetPixels32());
    photoShot.Apply();

    return photoShot;
   }
 }


    (4) The arrangement of Unity Editor will be:


Result

Build and run in the android device, you will find:
   As you can see, the resulting photo is too dark. This is due to the default exposure of the camera is too low (Unity just use the default camera parameters from devices). This might because we connect the android device with external WebCam. If you use the default camera that has been built-in your android phone, there might be no problem. Since the vendor of your phone may adjust the default parameters of the camera before it has been released...
   So, is there a way to fix this? The answer is no if you want to adjust the exposure by WebCamTexture, since it nearly provide nothing to adjust the camera settings.
    You can however, brighten the photo by some algorithms pixel by pixel. But it might be better if you can adjust the camera parameters directly (by invoke android API). In the next article, I will show you how.

Conclusion

Here are the conclusion of Unity built-in WebCamTexture:

Advantages: 

Easy to setup, and can be combined with UGUI, sounds, or other Unity utilities.

Disadvantages: 

You can not adjust camera parameters such as exposure, zoom level. Moreover, you get the picture just by screen shot, instead of requiring the camera to take picture by some command. This means that the camera will not adjust its focus when you take picture and will finally get a not-so-good photo.

In the next article, I will show you how to access native camera by calling the android camera API.

3 則留言:

  1. Hi, very nice article. As you said most of the WebCamTexture tutorials are outdated as they use GUITexture. I tried this out but it is not working for me. I think the problem is some mistake by me in the scene. Can you give me a unitypackage of this sample project so that I can debug. Thanks in advance!

    回覆刪除
  2. Hi, sorry for the late reply. I'm glad this article can help you. However, I abandon this method lately. Since in this method, we will create a large array (i.e. the image array) per frame (and you know Unity only call Garbage Collector when you change scene), your target device might be out of memory sooner or latter and the game will crash.
    After all, I still go back to use GUITexture. Although it is not as convenient as UI.Image, after some calculation by your self, you can still do the things that UI.Image can do.

    回覆刪除
  3. Recently, I found this website: http://answers.unity3d.com/questions/909967/getting-a-web-cam-to-play-on-ui-texture-image.html.

    If you want to display WebCamTexture as Unity.UI.Image, you can use RawImage instead.

    回覆刪除