LoginSignup
13
16

More than 5 years have passed since last update.

Unityでカメラ(WebCamTexture)を使ってみた

Posted at

対象はiOSとAndroid。
わりとネイティブな領域の対応が必要だった。

すること

必須

  • 権限付与
  • 回転制御

任意

  • シャッター音
  • カメラフラッシュ的な何か

必要な権限

iOS

PBXProjectのNSCameraUsageDescriptionに何か書く。

Android

CAMERA
Assets/Plugins/Android/AndroidManifest.xml<uses-permission android:name="android.permission.CAMERA" />を書き足す。

ユーザーへの権限問合せ

カメラ起動のタイミングではなく事前に権限を確認する。

iOS

iOSのネイティブAPIを用いて、AVCaptureDevice authorizationStatusForMediaType:を利用して現状を確認、未確認の場合はAVCaptureDevice requestAccessForMediaType: completionHandler:を用いてユーザーに権限を確認する必要がある。

extern "C" bool _CameraPlugin_RequestPermission()
{
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType: AVMediaTypeVideo];

    switch (status) {
        case AVAuthorizationStatusAuthorized:
            return true;
        case AVAuthorizationStatusNotDetermined:
            {
                __block BOOL granted = NO;

                dispatch_semaphore_t sema = dispatch_semaphore_create(0);
                [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL _granted) {
                    granted = _granted;
                    dispatch_semaphore_signal(sema);
                }];
                dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

                return granted;
            }
        default:
            return false;
    }
}

Android

多くのアプリでは、アプリ起動時にAndroidManifest.xmlに記載しておいて、起動時にすべて許可しないとアプリを終了といった設計になっている事が多いが、稀に権限付与のタイミングを遅らせたい時がある。

その場合はAndroidのAPIでrequestPermissionsする。
戻りはUnityPlayerActivity.onRequestPermissionsResultで受け取って、UnityPlayer.UnitySendMessageでUnity側に戻す。

という諸々を対応してくれるUnityプラグインがあるので、基本的にはそれを使う。
https://github.com/sanukin39/UniAndroidPermission

カメラの起動

Unityの機能が使える。

currentWebcamTexture = new WebCamTexture(WebCamTexture.devices[0].name, Screen.width, Screen.height, (new AppSetting()).FrameRate);
screenTexture.mainTexture = currentWebcamTexture;
currentWebcamTexture.Play();

WebCamTexture.devicesにリアカメラ、フロントカメラ等が配列で入っているので、これのインデックスを変更することでカメラ切り替えができる。

カメラの回転

通常は端末の回転に合わせてカメラも回転させる必要がある。

void Awake()
{
    baseRotation = screenTexture.transform.rotation;
}

void Update()
{
    if (currentWebcamTexture != null)
    {
        screenTexture.transform.rotation = baseRotation * Quaternion.AngleAxis(currentWebcamTexture.videoRotationAngle, Vector3.forward);
    }
}

キャプチャ処理

Texture2Dに入れてからバイト列で持っておく。
その後で色々するのにこのやり方が便利だった。

var width = Screen.width;
var height = Screen.height;
var tex = new Texture2D(width, height, TextureFormat.RGB24, false);

yield return new WaitForEndOfFrame();

tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);

tex.Apply();
pngBytes = tex.EncodeToPNG();

ScreenCapture.CaptureScreenshotという一見便利そうなメソッドもあるが、ファイル保存固定だったり、保存先ディレクトリが固定されていたり、終了がフックできなかったりとわりと手間がかかる。

シャッター音

端末やOSによって異なるのと、ボリュームゼロ時に無音はダメなので、ネイティブのメソッドを呼び出す。

iOS

AudioServicesPlaySystemSound(1108);

Android

var mediaActionSound = new AndroidJavaObject("android.media.MediaActionSound");
mediaActionSound.Call("play", mediaActionSound.GetStatic<int>("SHUTTER_CLICK"));

カメラフラッシュ的なもの

無いのでそれっぽいものを自前で実装する。
なお例示は無い。

カメラの停止

カメラの利用を停止する場合は、Stopする。

currentWebcamTexture.Stop();
13
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
16