UnityでWebカメラの切断を検知する


はじめに

前回の記事に続いて,Webカメラの切断を検知したときのメモを残しておく.

環境

  • Unity2019.2.9f1
  • Webカメラ1台(Logicool)

要点

本当は判定用のメソッド等があるのかもしれないが,分からなかったので自分なりに作った.

手法としては単純にWebCamTexture.devicesの中に現在表示しているWebCamTextureのインスタンスがあるかどうかで判定している.
この記事ではWebCamTextureの.nameが一致するか否かで判定を行う.

手順

前準備

今回もとりあえず適当なプロジェクトを作成して,表示用のPlaneを配置する.

テスト用スクリプト

このコードは0番目のカメラを初期値として読み込み,接続・切断を毎秒ログに吐き出す.
WebCamTest.csの名前でこのコードを記述して,先ほどのPlaneオブジェクトにセットする.

WebCamTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WebCamTest : MonoBehaviour
{
    private WebCamTexture wct;
    private Renderer renderer;
    // Start is called before the first frame update
    void Start()
    {
        this.renderer = this.GetComponent<Renderer>();
        this.SetCamera(0);
    }

    // Update is called once per frame
    void Update()
    {
        if (Time.frameCount % 60 == 0)
            Debug.Log(this.IsConnecting() ? "接続中" : "切断済");
    }

    //前回の記事を参照
    private void SetCamera(int idx) {
        int len = WebCamTexture.devices.Length;

        try {
            wct.Stop();
        } catch { }
        this.wct = new WebCamTexture(WebCamTexture.devices[idx % len].name);
        this.wct.Play();
        this.renderer.material.mainTexture = this.wct;
    }

    bool IsConnecting() {
        if (wct == null) return false;
        //現在接続中のカメラの中に使用中のカメラはあるかを判定する
        for (int i = 0; i < WebCamTexture.devices.Length; i++)
            if (this.wct.deviceName == WebCamTexture.devices[i].name) return true;
        //無ければカメラは切断されているのでnullを代入してfalseを返す.
        this.wct.Stop();
        this.wct = null;
        return false;
    }
}

上のコードを実行中にカメラを引き抜くと実際に切断済みと表示されているのが確認できる.

スクリプトの概要

1秒に1度WebCamTexuture.devicesを全探索して今使用中のカメラが接続中カメラの中に存在しているかどうかを判定している.
これでは瞬間的な切断に対応できないかもしれないが,今回の用途においては問題なかったためこの方法を採用した.

また,一度切断されたwctは再利用できないのようなので.Stop()で停止させたのちにnullを代入している.もし再接続する機能を作りたいのであれば,wctがnullの間は毎秒カメラを探索する等の処理を記述すればいい.

SetCamera関数については前回の記事で作成しているので,そちらを参照.

おわりに

今回も,できるだけ単純な例にするために例外判定など色々省略しています.
なので実行中のログに赤文字が出るかもしれないですが,とりあえず動作はするはずです.

もっと賢い方法がありそうな気がしますが,苦肉の策として紹介させていただきました.