見出し画像

UnityのWebCamTextureを使ってiOSのカメラから映像を取得してハマった

ハチャメチャにハマりました。
さくっとモックアップを作るためにUnityからiOSのカメラインプットを利用しようと思いましたが、半日近くを費やしてしまいました。

Unityを使ってデバイスのカメラインプットを利用する場合、大体検索にヒットする方法はCanvasにrawImageを置いて、そのtextureにWebCamTextureを流し込む方法です。たしかにラップトップでは問題なくサンプルコードも動きますが、iOSで動作させた瞬間にアスペクト比、オリエンテーション(向き)がむちゃくちゃになります。

これらのハンドリングには数年前から多くの人が苦しめられている様子です。

そして同スレッドに解決方法を提示してくれている方がいらっしゃいました。カメラの映像を見ると混乱しますが、一つ一つ問題を切り分けて、淡々としたコードで解決できています。以下はそのコードと追記した解説です。

using UnityEngine;
using UnityEngine.UI;

public class WebCamera: MonoBehaviour {
 public RawImage image; //canvas中のrawImage
 public RectTransform imageParent; //rawImageの親Panel
 public AspectRatioFitter imageFitter; //rawImageにaddしたARFコンポーネント

 // Image rotationの初期値
 Vector3 rotationVector = new Vector3(0f, 0f, 0f);

 // 画像自体の向き
 Rect defaultRect = new Rect(0f, 0f, 1f, 1f);
 Rect flipedRect = new Rect(0f, 1f, 1f, -1f);

 // 画像の親要素の向き
 Vector3 defaultScale = new Vector3(1f, 1f, 1f);
 Vector3 mirroredScale = new Vector3(-1f, 1f, 1f);

 WebCamTexture webCamTexture;

 void Start () {
   //端末によって検出されるカメラの数が変わるので、要ハンドリング
   webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name,Screen.width,Screen.height,60);
   image.texture = webCamTexture;
   webCamTexture.Play();
 }

 void Update (){
   // カメラがreadyではない状態だとテクスチャのsizeが16pxで返る
   if (webCamTexture.width <= 16) { return; }

   // 映像のz軸を反転させる(逆さまにする)
   rotationVector.z = -webCamTexture.videoRotationAngle;
   image.rectTransform.localEulerAngles = rotationVector;

   // テクスチャのサイズにaspectRatioをあわせる
   float videoRatio = (float)webCamTexture.width / (float)webCamTexture.height;
   imageFitter.aspectRatio = videoRatio;

   // 上下反転してしまっている画像はもとに戻す
   image.uvRect = webCamTexture.videoVerticallyMirrored ? flipedRect : defaultRect;

   // フロントフェイスカメラの場合、鏡像にする
   imageParent.localScale = WebCamTexture.devices[0].isFrontFacing ? mirroredScale : defaultScale;
 }
}

https://answers.unity.com/questions/773464/webcamtexture-correct-resolution-and-ratio.html?childToView=1155328#answer-1155328

これだけ見るとなんのことはないコードですが、軸が反転しつつ、アス比が歪んだ映像のデバッグは脳が追いつかず、かなり疲弊しました。

しかし、最も支持を得ている解決方法は上記のものではなく、

「NatCamつかえ」

です。確かに上記のコードではフロント・リアカメラなどのハンドリングは抜けてますし、実用には不十分です。NatCamは現在、NatDeviceというアセットとして有料販売になっているようですが、各種デバイスに対応する労力を考えると、黙って購入したほうが良さそうですね、、、


この記事が気に入ったらサポートをしてみませんか?