指定した時間みたら視線入力を受け付ける② 直さないとまずいことが発覚

例えば2秒見たら音楽を鳴らす。

 

とした場合、

 

まばたきも許されなくなりました。

 

それに、

視線は見ているつもりでも

まあまあ逸れている。

ということも分かりました。

 

だから、

視線の入力の厳密さを少し無くすプログラムを考えました。

 

結構苦労しました。

 

いらない変数の数値も多くありますが、

一旦やりたいことが出来たので

仮としてここに載せておこうと思います。

 

後でまた変えていきます。

 

ところで、すっごい今更ですが。。。

 

今までは一瞬でも見たら音楽が鳴る仕様だったので、

 

「あ、大丈夫なんだ」

 

と勝手に思っていたことが大丈夫じゃなかったことに気付きました。

 

背景のCubeの前に

imageのCubeが置いてあります。

 

背景のCubeを見たら視線入力の秒数カウントが始まるのですが、

imageをしっかり見て、背景に視線がもれていない場合

 

カウントしません!

 

これは絶対に直さないとまずい。

次回、頑張ります。

 

 

using System.Collections;
using System.IO;
using UnityEngine;
using Tobii.Gaming; //ライブラリの追加
using NAudio.Wave;  //← 見つからないとエラーが出たときは Import Settings を見直す
using System.Linq;

public class play : MonoBehaviour
{
    //キーをおしたら視線入力をうけつけるために必要
    public int keyoshitarastart;
    //キーをおしたら視線入力をうけつけるために必要


    //サイズと位置変更のため必要 この背景に乗っている画像の状態を知る
    public GameObject ima1Cu;
    image1 image1;
    //サイズと位置変更のため必要


    //隣を見たら音を止めるために必要 隣の背景の方の状態を知る
    public GameObject back2Cu;
    play2 pl2;
    //隣を見たら音を止めるために必要


    //隣を見たら音を止めるために必要 隣の背景の方の状態を知る
    public GameObject back3Cu;
    play3 pl3;
    //隣を見たら音を止めるために必要

 


    public AudioSource audioSource;


    ///////////////////////////////////////////

    string otoPath = "C:/オリジナル視線アプリ/音はここ/1";


    ///////////////////////////////////////////


    //注視情報
    private GazeAware gazeAware;

    //停止中か再生中かなど
    public int ichiziteishi;


    Vector3 screenPoint;
    Vector3 offset;


    //////+++++++++++++++注視する時間を変えるために必要
    float miterutime = 0f;         //視線がそれていない時間のカウント
    float notmiterutime = 0f;     //視線がそれている時間のカウント

    public int Miteimasu;       //見ていない0 見ているけど3秒未満 1 見ていたけど逸れている3 見ている 4 
    public int Notmiteimasu;  //視線逸れの許容時間中は1  完全にそれたと判断されたら0

    public int miterumitenai;   //gazeAware的に見てるなら1 見てないなら0


    //////+++++++++++++++注視する時間を変えるために必要


    //オブジェクトをドラッグする処理
    void OnMouseDown()
    {
        //カメラの座標を画面座標系で取得
        this.screenPoint = Camera.main.WorldToScreenPoint(transform.position);
        //アタッチしたオブジェクトの座標と画面内のタッチ座標との差分を求める(2つの座標の間のベクトルを求める)
        this.offset = transform.position
          - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
    }

    void OnMouseDrag()
    {
        //移動したマウスの座標を代入
        var currentScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
        //移動したマウス座標をワールド座標へ変換し,先ほど求めた offset を適用してアタッチしたオブジェクトの座標に直す
        var currentPosition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + this.offset;
        //セットする
        transform.position = currentPosition;

        ima1Cu.GetComponent<image1>().Posihenkoimage1();
    }

 

 


    //位置を変えるため必要
    public void Posihenkopl()
    {
        this.transform.position = image1.transform.position;        // image1.csのpositionを自分のpositionにする。
    }

 


    private void Start()
    {

        //サイズ変更、位置変更のため必要
        ima1Cu = GameObject.Find("ima1Cu");
        image1 = ima1Cu.GetComponent<image1>();
        //サイズ変更、位置変更のため必要

        //隣を見たら音を止めるために必要
        back2Cu = GameObject.Find("back2Cu");
        pl2 = back2Cu.GetComponent<play2>();
        //隣を見たら音を止めるために必要

        //隣を見たら音を止めるために必要
        back3Cu = GameObject.Find("back3Cu");
        pl3 = back3Cu.GetComponent<play3>();
        //隣を見たら音を止めるために必要


        //値を保持できるならスタート時に↓前の値を読むけど、保持できないから消しても良いか。。。
        this.transform.localScale = new Vector3(image1.xScale + 150, image1.yScale + 150, 1.0f);

        //視線入力をうけつける前はグレイ
        gameObject.GetComponent<Renderer>().material.color = Color.gray;

 

        //注視情報の取得
        gazeAware = GetComponent<GazeAware>();

        //一時停止が押されたかどうかを見るための変数。最初と再生中は1.一時停止中は2
        ichiziteishi = 1;

        //キーをおしたら視線入力をうけつけるための変数。うけつけないときは0。うけつけるときは1にする。
        keyoshitarastart = 0;


        //////+++++++++++++++注視する時間を変えるために必要
        miterutime = 0;
        notmiterutime = 0;
        Miteimasu = 0;
        Notmiteimasu = 0;
        //////+++++++++++++++注視する時間を変えるために必要
        ///

        ///////////////////////////////////////////
        //Stringの配列に音のファイルを入れていく。  Pathmei   string otoPath = "C:/sound/1" 拡張子* を入れる
        string[] Pathmei = System.IO.Directory.GetFiles(otoPath, "*", System.IO.SearchOption.AllDirectories);


        if (!Pathmei.Any())
        {
            Debug.Log($"{nameof(Pathmei)}音フォルダ1は空です。");
        }
        else
        {

 

            string file = Pathmei[0];   //配列の一個目(0番)をfileに入れる。

            //拡張子の出力
            Debug.Log(Path.GetExtension(file));  //配列の一個目(0番)、つまりfile の拡張子をLogに書き出す。

            //ファイル名の出力
            Debug.Log(Path.GetFileNameWithoutExtension(file));  //ついでに配列の一個目(0番)、つまりfile のFile名をLogに書き出す。いらないけど、後でいるかも知れないから書いた。

 

            if (Path.GetExtension(file).Contains("mp3"))  //もし、配列の一個目(0番)、つまりfile の拡張子がmp3なら
            {


                otoPath = Pathmei[0];       //otoPathにもし、配列の一個目(0番)、つまりfileを入れる。


            }
            else if (Path.GetExtension(file).Contains("wav"))  //もし、配列の一個目(0番)、つまりfile の拡張子がwavなら
            {

                var wavPath = Pathmei[0];    // 下の方の if (File.Exists(otoPath)) ・・・  により、Application.temporaryCachePath内にconverted.wavという名前で保存

                StartCoroutine(PlayWav(wavPath));       // 下の方のIEnumerator PlayWav(string path) ・・・より、PlayWavは関数名。これをここでスタートする。

            }
            else
            {
                Debug.Log($"どっちもないよ:{0}");      //mp3もwavも無いときのLog
            }

        }


        if (File.Exists(otoPath))   //Fileが存在しているか。もししているなら。
        {
            //wav 変換した一時ファイルを保存するパス
            var wavPath = Application.temporaryCachePath + "/converted.wav";    // Application.temporaryCachePath内にconverted.wavという名前で保存
            Mp3ToWAV(otoPath, wavPath);
            StartCoroutine(PlayWav(wavPath));
        }
        else
        {
            Debug.Log($"File not found : {otoPath}");
        }


    }

 

 

 

    //サイズ変更のため必要 image1のサイズを基準にしている。背景は画像より150大きい
    public void ScaleUp()
    {
        this.transform.localScale = new Vector3(image1.xScale + 150, image1.yScale + 150, 1.0f);
    }

    public void ScaleDown()
    {
        this.transform.localScale = new Vector3(image1.xScale + 150, image1.yScale + 150, 1.0f);
    }

 

 


    //mp3 → wav 変換して、保存したパスを返す
    public void Mp3ToWAV(string otoPath, string wavPath)
    {
        //ファイルを byte 配列で読み込み

        var bytes = File.ReadAllBytes(otoPath);     //File.ReadAllBytes:バイナリ ファイルを開き、ファイルの内容をバイト配列に読み取った後、ファイルを閉じます。

        //wav を一時ファイルとして保存
        using (var stream = new MemoryStream())     //MemoryStreamはFileには保存しないが、メモリにデータを読み書きするクラス
        {
            stream.Write(bytes, 0, bytes.Length);       //stream.Write で書き込み。bytes.Lengthで、bytesの配列全体を書き込み。
            stream.Position = 0;                        //ストリームの位置を先頭に。ここに10と入れたら10バイト目にセットすることになる。

            using (var reader = new Mp3FileReader(stream))  //Mp3FileReader:mp3Fileから読み込む Mp3FileReader(stream) でstreamのmp3Fileを読む。だと思う。
            {
                WaveFileWriter.CreateWaveFile(wavPath, reader);  //wav で書き出し(mp3なら「MediaFoundationEncoder」wavなら「WaveFileWriter」)
                Debug.Log($"Convert to wav successfully : {wavPath}");  //うまく行ったらwav保存先のパスを表示
            }
        }
    }
    ///////////////////////////////////////////

 

    void Update()
    {
        Debug.Log("スタートしてすぐのupdate" + keyoshitarastart);

        //xキーをおしたら視線入力をうけつける
        if (Input.GetKeyDown(KeyCode.X))
        {
            if (keyoshitarastart == 0)
            {
                Debug.Log("xおした" + keyoshitarastart);
                keyoshitarastart = 1;
            }
            else
            {
                Debug.Log("xおした" + keyoshitarastart);
                keyoshitarastart = 0;

                //視線入力をうけつけないとき
                gameObject.GetComponent<Renderer>().material.color = Color.gray;
                //鳴ってた曲も止める
                Pause();
            }

        }

        if (keyoshitarastart == 1)
        {

            keyoshita();
        }


        // マウスの左ボタンを推した場合も再生・・はやめた。画像移動のときにも鳴ってしまう。


        /*
        以下にあったコードはぜんぶ、
        public void keyoshita()の中に移動した
        */

 


    }

    //ストリーミング再生する
    IEnumerator PlayWav(string path)    //IEnumeratorはコルーチンを使うのに宣言するとき使う。PlayWavは関数名。
                                        //コルーチンは好きな場所で処理を止めたり再開したりできる機能
    {
        using (var www = new WWW("file://" + path))     //www(url)でURLにアクセスする
        {
            while (!www.isDone)     //while(条件式) 条件式が真である限りループする。www.isDoneはダウンロード終了したかどうかを読み取る。!がついているから「終了していない限り処理する」ということ。と思う。
                yield return null;  //1フレーム停止

            if (string.IsNullOrEmpty(www.error))    //string.IsNullOrEmptyは指定の文字列が、nullもしくは空の文字列かを判断
                                                    //www.errorはダウンロード中にエラーが起きたときのメッセージ
            {
                var clip = www.GetAudioClip(false, true);   //最初のはクリップを2Dにする(false)3Dは(true)だと思う。よく分かってない。後の真偽はtrueならダウンロード中も再生。falseならダウンロードしてから再生
                audioSource.clip = clip;
                //audioSource.Play();
                Debug.Log($"Play wav : {path}");
            }
            else
            {
                Debug.Log(www.error);
            }
        }
    }

 

    public void keyoshita()
    {
        //オブジェクトを注視していたらTrue
        bool flg = gazeAware.HasGazeFocus;

        if (flg)    //もし見ているなら
        {
            //////+++++++++++++++注視する時間を変えるために必要
            notmiterutime = 0;

            //見ている時間をカウント
            miterutime += Time.deltaTime;           //毎フレームの時間を加算.
            Debug.Log("見てますTime : " + miterutime);
            notmiterutime = 0;
            //////+++++++++++++++注視する時間を変えるために必要

        }
        else
        {
            
            //みていない時間をカウント
            notmiterutime += Time.deltaTime;
         //   Debug.Log("見てませんTime : " + notmiterutime);

          

        }

 

            

        if (notmiterutime == 0) //見ているあいだ (見ていない時間がカウントされていない)
        {


            if (miterutime < 1.5 && miterutime != 0)       //見ている時間が規定時間を超えてない
            {

                //+++++++++++++++++++++++++++++++++++++++++++++@@
                Miteimasu = 1;      //見ているが時間が足りてない
                //+++++++++++++++++++++++++++++++++++++++++++++@@
                gameObject.GetComponent<Renderer>().material.color = Color.magenta;


            }

            else if (miterutime >= 1.5)       //見ている時間が規定時間を超えた
            {
                //+++++++++++++++++++++++++++++++++++++++++++++@@
                Miteimasu = 4;      //見ていると判断されている
                //+++++++++++++++++++++++++++++++++++++++++++++@@
                gameObject.GetComponent<Renderer>().material.color = Color.red;

                //見ているタイムをリセット
                miterutime = 0;

            }

        }
        else if (notmiterutime > 1.0)      //見ていない時間が規定時間を超えたら                         
            {
          
                //+++++++++++++++++++++++++++++++++++++++++++++@@
                Miteimasu = 0;      //見てない
                //+++++++++++++++++++++++++++++++++++++++++++++@@
               gameObject.GetComponent<Renderer>().material.color = Color.blue;

              //見ているタイムをリセット
                 miterutime = 0;

        }
         else                 //見ていない時間が規定時間を超えていないなら

            {
                //+++++++++++++++++++++++++++++++++++++++++++++@@
                Miteimasu = 2;      //今見てないだけ
                //+++++++++++++++++++++++++++++++++++++++++++++@@
              gameObject.GetComponent<Renderer>().material.color = Color.magenta;
        }

        

 


        if (!audioSource.isPlaying && Miteimasu == 4)  //再生中で無い、かつ Miteimasu が 4(規定時間以上見たとき)なら
        {

            //一時停止関数がもし2(一時停止中)なら
            if (ichiziteishi == 2)
            {
                //再開してください(同時にichiziteisi変数は1になる)
                UnPause();
                
            }

            //一時停止関数がもし1(一時停止中でない(起動したところだったり、停止中だったり))なら再生する。
            else
            {
                    audioSource.Play();
                
                //++++playが再生されるときは、他のCubeの音は一時停止する++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                pl2.audioSource2.Pause();
                pl3.audioSource3.Pause();

            }
            Miteimasu = 0;
        }

 


        // 停止

        if (audioSource.isPlaying)  //再生中なら
        {

            //注視がそれているときのみ有効。テンキーの「2」を押して離したら停止
            if (Input.GetKeyUp(KeyCode.Keypad2))
            {

                Stop();


            }

        }


        // 注視がそれているときのみ有効。一時停止
        if (audioSource.isPlaying)  //再生中なら
        {

            //テンキーの「1」を押して離したら一時停止し、ichiziteishi変数を2に。
            if (Input.GetKeyUp(KeyCode.Keypad1))
            {
                Pause();

            }
        }


        // 再開
        if (!audioSource.isPlaying)  //停止中なら
        {

            //もう一回、注視したり左クリックしたりしたら再開し、ichiziteishi変数を1に。
            // if (flg || Input.GetMouseButtonDown(0))
            if (Miteimasu == 4)     //元は if (flg) だった。
            {

                UnPause();

            }
            Miteimasu = 0;
        }

 


        if (Input.GetKey(KeyCode.Escape))
        {
            Application.Quit();
        }

    }

 

    //再生、一時停止、停止、再開、完全に停止について

    /*
    // 再生 Play と、入力したら一回だけ再生
    private void Play(AudioClip audi)
        {
            audioSource.PlayOneShot(audi);
            
    }
    */

    //  一時停止 Pauseと、入力したらichiziteishi変数に2を入れて、一時停止
    private void Pause()
    {
        ichiziteishi = 2;
        audioSource.Pause();
    }

    // 停止  Stopと、入力したら停止
    private void Stop()
    {
        audioSource.Stop();
    }

    // 再開 UnPause と、入力したらichiziteishi変数に1を入れて、再開

    private void UnPause()
    {
        ichiziteishi = 1;
        audioSource.UnPause();

        //++++playが再生されるときは、他のCubeは一時停止する++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        pl2.audioSource2.Pause();
        pl3.audioSource3.Pause();

    }

 

}