質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • Unity

    3386questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1133questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

  • Unity2D

    692questions

UnityWebRequestでDLしたmp3を再生する時に画面表示が若干固まってしまう

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 108

buibui80

score 941

外部サーバーに配置されたmp3ファイルをDLして再生する仕組みを作りたく、
AudioClip用のUnityWebRequestであるUnityWebRequestMultimediaを使用してみました。

DL自体は問題なく完了しAudioClipの再生まではできたのですが、
再生時に画面表示が若干固まることに気づきました。

どこで固まるかソースを1行ごとに確認したところ、以下の行で固まっていることを確認できました。
※検証用全ソースは下部にあります。

audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip; // ここで若干固まる

調べたところ、
UnityWebRequestで得られた結果はメインスレッドからしかアクセスできないらしく、
固まる原因はプロパティaudioClipへのアクセス時にメインスレッド上で
AudioClipが動的に作成されていることだと想定できました。

ログ出力の"[AudioClip] downloadHandler: Before" と "[AudioClip] downloadHandler: After" 間の
経過時間を確認してもらえると状況が把握できると思います。
Android実機で確認したところ1秒ほどかかっていました。

そこで質問ですが、
audioClipへのアクセス時に画面表示の固まりなく再生する方法は無いでしょうか?
VideoPlayerで外部サーバーのmp4を再生した際は問題なく再生できたので何か方法があるのでは思っております。

どうぞよろしくお願いいたします。

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
//using System.Threading;

public class MainController : MonoBehaviour
{
    public AudioSource audioSource;

    void Start ()
    {
        if (audioSource == null)
            audioSource = this.gameObject.AddComponent<AudioSource>();

        OnClick1();
    }


    // ログ出力用の時間文字列を返す
    private string GetNow()
    {
        return "[" + DateTime.Now.ToString("HH:mm:ss.fff") + "]";
    }


    public void OnClick1()
    {
        // 遅延発生するケース
        StartCoroutine(DownloadAudio1());
    }
    public void OnClick2()
    {
        // 別スレッドで試すケース(エラー発生します)
        StartCoroutine( DownloadAudio2() );
    }


    /// <summary>
    /// 音声ファイルのダウンロード後に DownloadHandlerAudioClip の audioClip へアクセスする際に遅延が発生する。
    /// メインスレッド上の遅延の為、UIが固まる不具合となってしまう。
    /// PCでは気にならない程度だがAndroid実機では1秒程度の固まりが発生して困る。
    /// </summary>
    protected IEnumerator DownloadAudio1()
    {
        audioSource.Stop();
        audioSource.clip = null;

        string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
        using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
        {
            Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
            yield return uwr.SendWebRequest();
            if (uwr.isNetworkError || uwr.isHttpError)
            {
                Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
            }
            else if (uwr.isDone)
            {
                Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
                yield return null;

                Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
                audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
                Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");
                yield return null;

                Debug.Log(GetNow() + " Audio Play: Before" + "\n");
                audioSource.Play();
                Debug.Log(GetNow() + " Audio Play: After" + "\n");
                yield return null;

                yield return new WaitForSeconds(5f);
                audioSource.Stop();
                audioSource.clip = null;
            }
            uwr.Dispose();
        }
    }


    /// <summary>
    /// DownloadHandlerAudioClip の audioClip へアクセスする箇所をメインスレッド外にしてみる。
    /// しかし audioClip へのアクセス時にメインスレッドでないとエラーが発生する。
    /// スレッドを試すときはUnityでC#6.0を使用できる様に設定が必要になります。
    ///     https://qiita.com/divideby_zero/items/71a38acdbaa55e88e2d9
    /// </summary>
    protected IEnumerator DownloadAudio2()
    {
        audioSource.Stop();
        audioSource.clip = null;

        string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
        using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
        {
            Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
            yield return uwr.SendWebRequest();
            if (uwr.isNetworkError || uwr.isHttpError)
            {
                Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
            }
            else if (uwr.isDone)
            {
                Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
                yield return null;

                /* エラーになるのでコメントアウトしています
                // メインスレッドを確保
                var context = SynchronizationContext.Current;
                ThreadPool.QueueUserWorkItem((object state) =>
                {
                    // 別スレッドで処理
                    Debug.Log("[ThreadPool] Start");

                    Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
                    audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
                    Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");

                    Debug.Log(GetNow() + " Audio Play: Before" + "\n");
                    audioSource.Play();
                    Debug.Log(GetNow() + " Audio Play: After" + "\n");

                    // メインスレッドに処理を戻す
                    context.Post((d) => {
                        Debug.Log(GetNow() + "[ThreadPool] End");
                        audioSource.Stop();
                        audioSource.clip = null;
                    }, null);
                }, null);
                */
            }
            uwr.Dispose();
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Unity

    3386questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1133questions

    Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

  • Unity2D

    692questions