指定した時間みたら視線入力を受け付ける③ imageを見ても視線入力を受け付ける エラーが出たけど解決

背景の前にあるimageを見ても視線入力を受け付けるようにしました。

 

まず、変数 image1mitaを作っておいて、

image1のupdateを

 

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

        if(flg)
        {
            image1mita = 1;
            

        }
        else
        {
            image1mita = 0;
            

        }

        StartCoroutine("sizehenko");

 

    }

 

としました。

 

次に背景である play.csの方で

 


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

        if (flg || image1.image1mita == 1 )    //もし見ているなら

 

・・・・

としました。

 

前は 

  if (flg)    //もし見ているなら

だったところに、

image1の方も「見たら数値が1になる変数」が1であるかどうかを

確認するようにしました。

 

直接、image1の方も 

if (image1.flg)とか出来るのかなと思いましたが、

いろいろ入れてみましたが、

今のところ分からず、変数を使うことにしました。

 

長々と見たときの処理を書かないといけないのかなと

一瞬思いましたが、大丈夫でした。

 

良かった。。。

 

ところで、プログラムを書き終わって起動すると

NullReferenceException: Object reference not set to an instance of an object

 

というエラーが出ました。

 

image1がアタッチされているCubeは今まで

視線入力をしなかったので

inspectorにGaze Aware が加わっていませんでした。

 

これを加えると解決しました。

 

 

 

 

 

 

 

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

例えば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();

    }

 

}

 

指定した時間みたら視線入力を受け付ける① 視線入力が厳密すぎる

目標を立てたのに、目標と違うことばかりしています。

 

さっきはxキーを押すまで視線入力を受け付けない仕様にしました。

 

今度は、こちらが指定した秒数だけ見たら視線入力を受け付けるようにします。

 

まず、

【Unity,C#】時間をカウントしたい! | アサマゲームズ

↑こちらがとてもシンプルで分かりやすく

参考にさせて頂きました。

 

 

一旦、こういうプログラムを書きました。

 

見たら背景がマゼンダになり

2秒間見続けたら

背景が赤になり、再生する

 

ですが、

一回もそらさずに

見続けるという行為の難しいこと難しいこと

 

まばたきも許されません。

マゼンダになったときをスクリーンショットに取りたかったのですが

スクショを取ろうとキーを押しかけると目線がブレて

取れない。

 

ということで、この厳密さをなんとかすることにします。

 

 

 

キーを押すまで視線入力を受け付けないようにした

いろいろテストしていて

少しでも画面を見たら鳴ってしまうのが

不便なときもあるので、

タイトルの内容のコードを作りたいと思いました。

 

できるかな?

 

・・・

 

出来ました。

 

まあまあ変わったところがあるのでplay.csだけですが

全コード載せます。

 

以下の赤いところが確か新たに変えたところですが、

赤くするのを忘れている個所があったら

前のコードに無い部分をみつけて加えて下さい。

 

Xキーを押すたびに視線入力を受け付けたり

受け付けなかったりします。

分かりやすさのため

受け付けないときは背景がグレーになるようにしています。

 

 

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;
   

    //オブジェクトをドラッグする処理
    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;


        ///////////////////////////////////////////
        //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)
        {

 

            //注視していたら赤色に
            gameObject.GetComponent<Renderer>().material.color = Color.red;


            if (!audioSource.isPlaying)  //再生中で無いなら
            {

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

                }

                //一時停止関数がもし1(一時停止中でない(起動したところだったり、停止中だったり))なら再生する。
                else
                {

                    audioSource.Play();


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

                }

            }


        }

        //注視して無かったら
        else
        {
            //注視していなければ青色に
            gameObject.GetComponent<Renderer>().material.color = Color.blue;
            //注視がそれただけでは一時停止にはしていない。視線がそれることはよくあると思うので。
            //一時停止にしたいならPauseを入れたら可能。

            //改訂として目をそらしたら止めるようにする
            // Pause();


        }


        // 停止

        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 (flg)
            {

                UnPause();

            }
        }


       

        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();

    }

 

}

 

とりあえず画像3枚バージョンを作ってから考える② mp3再生しなくなってる→解決

タイトルの通りのことが起きました。

 

音ファイルを入れるフォルダを3つ作ったのですが、

mp3が二つ以上入ると

どっちかが鳴らなくなりました。

 

これは簡単に解決しました。

 

play2.csのコードです。

 


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

 

mp3をwavに変換して保存するときのファイル名が

今まで全部

converted.wav

だったので、

converted2.wav

に変えました。

 

play3.csでは

converted3.wav

にしました。

 

 

逆に今まで、どうして鳴っていたのか不思議です。

たまたまテストするときに

二つのフォルダに同時にmp3を入れたことが無かったのかも知れません。

 

 

尚、

備忘録として再度converted2.wavの保存場所を書きます。

 

C:\Users\×××\AppData\Local\Temp\〇〇〇\musicPlay4_2

 

です。

〇〇〇のところは多分

Built Setting...の

player Setting...の中の

ここで付けた名前なんだと思います。

(Company Nameを途中で変更したのに、前の名前のフォルダの中ばかり

 探して、全くみつからず、全フォルダ内をファイル名で検索してしまいました。)

 

尚、Company Nameの下のProduct Nameでつけた名前が

パスの最後のフォルダ名になっているようです。

 

 

とりあえず画像3枚バージョンを作ってから考える① エラーが出ました

起動後に枚数を変えられるようになどしたいとは

思いますが、とりあえず一旦

3枚バージョンを作ってから考えることにしました。

 

これは簡単・・・

と思っていましたがエラーが起きました。

 

play2  と

image2 を

コピーペーストして

play3

image3

という名前にして、

 

2

と名前のついたところを全部

3

に変えたりなどすればいいと思っていました。

 

エラー文は以下です。

 

UnassignedReferenceException: The variable audioSource3 of play3 has not been assigned.
You probably need to assign the audioSource3 variable of the play3 script in the inspector.

 

DeepL様に翻訳してもらいます。

 

UnassignedReferenceException: play3 の変数 audioSource3 は割り当てられていません。
おそらくインスペクタでplay3スクリプトのaudioSource3変数を代入する必要があります。

 

なんて親切なのでしょう。

恐らく〇〇だと思います。

なんてことまで言ってもらえるなんて。

 

back2Cuのinspectorは

 

新たに作ったback3Cuのinspectorは

 

明らかに違う箇所があります。

すぐ下のAudio Sourceの文字辺りをつかんで矢印の枠内で離すとこうなりました。

 

これで起動しましたが、またエラーが起きました。

 

DirectoryNotFoundException: Could not find a part of the path 'C:\original glance app picture here\3'.

 

これは翻訳しなくてもなんとなく分かりました。

フォルダを作り忘れていました。

 

画像も音もフォルダ3を作りました。

 

起動します。

やっとエラーが消えました。

が、画像サイズを変えても、新しく

つくったCube(真ん中)だけサイズが変わりません。

 

後、新たに作った3つ目のCubeを見て曲を鳴らすと、

他の画像を見ても音が止まりません。

 

コードを見直してみます。

 

・・・

分かりました。

 

すべてのサイズ変更のもとはimage1なのですが、

そのスクリプト

 

こういうコードがあるのですが、新しく作ったCube等を入れていませんでした。

 

まあまあたくさん入れるところがありました。

 

まず最初のところ。

 

スタートのところ。

あと、 IEnumerator sizehenko() の中はいっぱい

ありました。

 

起動しました。

サイズは一緒に変わるようになりました。

 

それから、

 

音楽が鳴っていても、別のCubeを見たら音が止まる仕様にしたはずなのですが、

止まりません。

 

これもコードを見直してみます。

 

ここかな? playのスクリプトです。

 

この一番下のところに、

pl3のポーズを加えました。

後、ここの部分も


↓一番下に加えました。

 

これで万事うまく・・・

 

あれ?

新しく作ったCubeはwavしか再生してくれません。

 

長くなるので次に行きます。



  

フォルダが空だったときのことを考えていませんでした② 非表示はダメ。画像がないときは透明に

続くと思わず、前回タイトルの後に①を付けていませんでした。

 

今現在、画像フォルダが空だとこうなります。

 

あまり格好良くない。

白枠はいらない。

 

と、思って画像フォルダが空だと非表示にするにはどうすれば良いか調べました。

 

【Unity C#】オブジェクトの表示・非表示を切りかえる (futabazemi.net)

いつも、不思議なぐらい欲しい情報を

載せて下さっているこちらのサイト様を参考にしました。

 

が、このコードは

この画像のサイズを参考に別の画像も連動して変化させたり、

位置も背景と画像で連動させたり・・・

 

いろいろしてたので、非表示にしてしまうと

エラーになるようです。

 

 

そこで、透明にしてみることにしました。

これもまた

 

【Untiy C#】他のスクリプトから透明化させる - プログラミング教室 フタバゼミ (futabazemi.net)

同じこちらのサイト様に掲載されておりました。

 

ここから、

 

 this.GetComponent<Renderer>().material.color = new Color32(0, 0, 0, 0);

を、そのまま拝借し、

 

 if (!Pathmei.Any())                                  
        {
            Debug.Log($"{nameof(Pathmei)}画像フォルダ1は空です。");
            this.GetComponent<Renderer>().material.color = new Color32(0, 0, 0, 0);
        }

 

としました。

参考サイトではマテリアルを作って、

レンダリングモードをFadeに・・・

とあるのですが、今回はこのコードを貼り付けるだけで大丈夫でした。

 

最初は

 

image画像をくっつけるのに既にひとつ

マテリアルを作っていたから

マテリアルをもう一個作って、

レンダリングモードをFadeにして、

 

くっつけたいオブジェクトの

inspectorの↓ここを2にして

下に新しく出来たElement1に、新しく作った

マテリアルをドラッグしてくっつけていました。

つまり、ひとつのオブジェクトに二つマテリアルがくっついている状態。

 

が、いまいち必要そうにない?

ような気がして消しましたところ、

既に作ってあったマテリアルが仕事をしてくれたのか、

ちゃんと透明になりました。

 

 

良かったです。

 

ところで

レンダリングモードのFadeってなんでしょう?

Rendering Mode - Unity マニュアル (unity3d.com)

このように↑書いてありました。

 

最初のマテリアルはFadeにした記憶はないのですが、

どうして透明になったのか??

 

また時間があるときに調べたいと思います。