画面をタップしたときにパシャっと写真撮影し、撮影画像をPlaneなどに貼って表示するというのが意外と大変だったので、その手順をまとめました。
写真撮影する流れ
画面がタップされてからカメラを起動→撮影とすると時間がかかってしまうため、基本的にカメラはバックグラウンドで起動しておき、タップされたときにカメラに映っている映像を取得する、という流れになります。
これをふまえて、写真撮影をする流れは次のようになります。
- カメラの映像をWebCamTextureで取得
- 取得した映像をRawImageで表示
- タップされたらRawImageの映像をTexture2Dに変換
- マテリアルのテクスチャに設定
図にするとこんな感じになります。
プログラムを作る
WebCamControllerという名前でスクリプトを作成して、次のプログラムを入力してください。
using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(RawImage))] public class WebCamController : MonoBehaviour { WebCamTexture webcamTexture; RawImage rawImage; void Start() { WebCamDevice[] devices = WebCamTexture.devices; webcamTexture = new WebCamTexture(devices[0].name,1920, 1080, 30); this.rawImage = GetComponent<RawImage>(); this.rawImage.texture = webcamTexture; this.rawImage.enabled = false; webcamTexture.Play(); } void TakeShot() { Texture tex = this.rawImage.texture; int w = tex.width; int h = tex.height; RenderTexture currentRT = RenderTexture.active; RenderTexture rt = new RenderTexture(w, h, 32); Graphics.Blit(tex, rt); RenderTexture.active = rt; Texture2D result = new Texture2D(w, h, TextureFormat.RGBA32, false); result.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); result.Apply(); RenderTexture.active = currentRT; GetComponent<MeshRenderer>().material.mainTexture = result; } private void Update() { if(Input.GetMouseButtonDown(0)) { TakeShot(); } } }
Startメソッドの中では、WebCamTextureでカメラ映像を取得し、それをRawImageに設定しています。
具体的には、まずWebCamTexture.devicesでPCに接続されているカメラを取得し、カメラ名からWebCamTextureを作成します。作成したWebCamTexture をRawImageコンポーネントのテクスチャに設定することで、RawImageにカメラからの映像が表示されます。今回は写真を撮影したときにのみ画面表示を行いたいので、ここではRawImageのenableをfalseにしています。
画面がタップされるとTakeShotメソッドが呼ばれます。TakeShotメソッドではRawImageの映像をTexture2Dに変換しています。
RawImageからTexture2Dへは、単純にキャストするだけでは変換できません。いったんRawImageをRenderTextureに書き出し、それをReadPixelsメソッドでTexture2Dに書き込んでいます。
最後に、PlaneオブジェクトのMeshRendererコンポーネントを通してマテリアルを取得し、作成したTexture2D型の画像をマテリアルのmainTextureに設定しています。
Planeに設定する
ヒエラルキーウインドウの「+」をクリックして「3D Object」→「Plane」を選択してください。シーンビューにPlaneが表示されます。
作成したPlaneにWebCamControllerスクリプトドラッグ&ドロップしてアタッチします。スクリプト中でRequireComponent(typeof(RawImage))としているため、RawImageコンポーネントも自動的にアタッチされます。
実行してみる
ここまでできたら実行してみてください。画面をクリックするとクリックした時点での写真が表示されます。