対象は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();