質問編集履歴

4

修正

2018/06/21 02:32

投稿

buibui80
buibui80

スコア1033

test CHANGED
File without changes
test CHANGED
@@ -62,7 +62,7 @@
62
62
 
63
63
  using UnityEngine.Networking;
64
64
 
65
- using System.Threading;
65
+ //using System.Threading;
66
66
 
67
67
 
68
68
 

3

内容修正

2018/06/21 02:32

投稿

buibui80
buibui80

スコア1033

test CHANGED
@@ -1 +1 @@
1
- UnityWebRequestMultimedia.GetAudioClip取得したaudioClipへアクセスするとメインスレッド遅延する現象につい
1
+ UnityWebRequestでDLしたmp3を再生する時に画面表示若干固まっしまう
test CHANGED
@@ -1,323 +1,329 @@
1
- Unity 2018.1.1.f1
2
-
3
-
4
-
5
- 外部サーバーに配置されたmp3ファイルを任意のタイミングでDLして再生する仕組みを作りたく、
1
+ 外部サーバーに配置されたmp3ファイルをDLして再生する仕組みを作りたく、
6
-
2
+
7
- UnityWebRequestMultimedia.GetAudioClipを使用してaudioClipを再生てみのですが
3
+ AudioClip用のUnityWebRequestであるUnityWebRequestMultimediaを使用してみました
4
+
5
+
6
+
8
-
7
+ DL自体は問題なく完了しAudioClipの再生まではできたのですが、
8
+
9
- audioClipにアクセスした時にUIが若干固まることに気づきました。
9
+ 再生時に画面表示が若干固まることに気づきました。
10
+
11
+
12
+
10
-
13
+ どこで固まるかソースを1行ごとに確認したところ、以下の行で固まっていることを確認できました。
14
+
11
- (Android実機だと1秒ほどUI表示が固まります)
15
+ ※検証用全ソースは下部にあります
16
+
17
+ ```C#
18
+
19
+ audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip; // ここで若干固まる
20
+
21
+ ```
12
22
 
13
23
 
14
24
 
15
25
  調べたところ、
16
26
 
17
- UnityWebRequestで得られた結果はメインスレッドからしかアクセスできないとのことでたので
27
+ UnityWebRequestで得られた結果はメインスレッドからしかアクセスできない
18
-
28
+
19
- 遅延の原因はaudioClipへのアクセス時にメインスレッド上で動的にAudioClipが作成されていることと思われます。
29
+ 固まる原因はプロパティaudioClipへのアクセス時にメインスレッド上で
30
+
31
+ AudioClipが動的に作成されていることだと想定できました。
32
+
33
+
34
+
35
+ ログ出力の"[AudioClip] downloadHandler: Before" と "[AudioClip] downloadHandler: After" 間の
36
+
37
+ 経過時間を確認してもらえると状況が把握できると思います。
38
+
39
+ Android実機で確認したところ1秒ほどかかっていました。
40
+
41
+
42
+
43
+ そこで質問ですが、
44
+
45
+ audioClipへのアクセス時に画面表示の固まりなく再生する方法は無いでしょうか?
46
+
47
+ VideoPlayerで外部サーバーのmp4を再生した際は問題なく再生できたので何か方法があるのでは思っております。
48
+
49
+
50
+
51
+ どうぞよろしくお願いいたします。
52
+
53
+
20
54
 
21
55
  ```C#
22
56
 
57
+ using System;
58
+
59
+ using System.Collections;
60
+
61
+ using UnityEngine;
62
+
63
+ using UnityEngine.Networking;
64
+
65
+ using System.Threading;
66
+
67
+
68
+
69
+ public class MainController : MonoBehaviour
70
+
71
+ {
72
+
73
+ public AudioSource audioSource;
74
+
75
+
76
+
77
+ void Start ()
78
+
79
+ {
80
+
81
+ if (audioSource == null)
82
+
83
+ audioSource = this.gameObject.AddComponent<AudioSource>();
84
+
85
+
86
+
87
+ OnClick1();
88
+
89
+ }
90
+
91
+
92
+
93
+
94
+
95
+ // ログ出力用の時間文字列を返す
96
+
97
+ private string GetNow()
98
+
99
+ {
100
+
101
+ return "[" + DateTime.Now.ToString("HH:mm:ss.fff") + "]";
102
+
103
+ }
104
+
105
+
106
+
107
+
108
+
109
+ public void OnClick1()
110
+
111
+ {
112
+
113
+ // 遅延発生するケース
114
+
115
+ StartCoroutine(DownloadAudio1());
116
+
117
+ }
118
+
119
+ public void OnClick2()
120
+
121
+ {
122
+
123
+ // 別スレッドで試すケース(エラー発生します)
124
+
125
+ StartCoroutine( DownloadAudio2() );
126
+
127
+ }
128
+
129
+
130
+
131
+
132
+
133
+ /// <summary>
134
+
135
+ /// 音声ファイルのダウンロード後に DownloadHandlerAudioClip の audioClip へアクセスする際に遅延が発生する。
136
+
137
+ /// メインスレッド上の遅延の為、UIが固まる不具合となってしまう。
138
+
139
+ /// PCでは気にならない程度だがAndroid実機では1秒程度の固まりが発生して困る。
140
+
141
+ /// </summary>
142
+
143
+ protected IEnumerator DownloadAudio1()
144
+
145
+ {
146
+
147
+ audioSource.Stop();
148
+
149
+ audioSource.clip = null;
150
+
151
+
152
+
153
+ string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
154
+
155
+ using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
156
+
157
+ {
158
+
159
+ Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
160
+
161
+ yield return uwr.SendWebRequest();
162
+
163
+ if (uwr.isNetworkError || uwr.isHttpError)
164
+
165
+ {
166
+
167
+ Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
168
+
169
+ }
170
+
171
+ else if (uwr.isDone)
172
+
173
+ {
174
+
175
+ Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
176
+
177
+ yield return null;
178
+
179
+
180
+
181
+ Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
182
+
23
- audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip; // ここで遅延
183
+ audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
184
+
185
+ Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");
186
+
187
+ yield return null;
188
+
189
+
190
+
191
+ Debug.Log(GetNow() + " Audio Play: Before" + "\n");
192
+
193
+ audioSource.Play();
194
+
195
+ Debug.Log(GetNow() + " Audio Play: After" + "\n");
196
+
197
+ yield return null;
198
+
199
+
200
+
201
+ yield return new WaitForSeconds(5f);
202
+
203
+ audioSource.Stop();
204
+
205
+ audioSource.clip = null;
206
+
207
+ }
208
+
209
+ uwr.Dispose();
210
+
211
+ }
212
+
213
+ }
214
+
215
+
216
+
217
+
218
+
219
+ /// <summary>
220
+
221
+ /// DownloadHandlerAudioClip の audioClip へアクセスする箇所をメインスレッド外にしてみる。
222
+
223
+ /// しかし audioClip へのアクセス時にメインスレッドでないとエラーが発生する。
224
+
225
+ /// スレッドを試すときはUnityでC#6.0を使用できる様に設定が必要になります。
226
+
227
+ /// https://qiita.com/divideby_zero/items/71a38acdbaa55e88e2d9
228
+
229
+ /// </summary>
230
+
231
+ protected IEnumerator DownloadAudio2()
232
+
233
+ {
234
+
235
+ audioSource.Stop();
236
+
237
+ audioSource.clip = null;
238
+
239
+
240
+
241
+ string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
242
+
243
+ using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
244
+
245
+ {
246
+
247
+ Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
248
+
249
+ yield return uwr.SendWebRequest();
250
+
251
+ if (uwr.isNetworkError || uwr.isHttpError)
252
+
253
+ {
254
+
255
+ Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
256
+
257
+ }
258
+
259
+ else if (uwr.isDone)
260
+
261
+ {
262
+
263
+ Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
264
+
265
+ yield return null;
266
+
267
+
268
+
269
+ /* エラーになるのでコメントアウトしています
270
+
271
+ // メインスレッドを確保
272
+
273
+ var context = SynchronizationContext.Current;
274
+
275
+ ThreadPool.QueueUserWorkItem((object state) =>
276
+
277
+ {
278
+
279
+ // 別スレッドで処理
280
+
281
+ Debug.Log("[ThreadPool] Start");
282
+
283
+
284
+
285
+ Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
286
+
287
+ audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
288
+
289
+ Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");
290
+
291
+
292
+
293
+ Debug.Log(GetNow() + " Audio Play: Before" + "\n");
294
+
295
+ audioSource.Play();
296
+
297
+ Debug.Log(GetNow() + " Audio Play: After" + "\n");
298
+
299
+
300
+
301
+ // メインスレッドに処理を戻す
302
+
303
+ context.Post((d) => {
304
+
305
+ Debug.Log(GetNow() + "[ThreadPool] End");
306
+
307
+ audioSource.Stop();
308
+
309
+ audioSource.clip = null;
310
+
311
+ }, null);
312
+
313
+ }, null);
314
+
315
+ */
316
+
317
+ }
318
+
319
+ uwr.Dispose();
320
+
321
+ }
322
+
323
+ }
324
+
325
+ }
326
+
327
+
24
328
 
25
329
  ```
26
-
27
-
28
-
29
- 以下は検証用ソースです。
30
-
31
- エラーになりますがThreadを使用しているのでC#6が使用できるようUnityの設定が必要になります。
32
-
33
- 参考: [C#6.0時代のUnity](https://qiita.com/divideby_zero/items/71a38acdbaa55e88e2d9)
34
-
35
-
36
-
37
- ログ出力の"[AudioClip] downloadHandler: Before" と "[AudioClip] downloadHandler: After" 間の
38
-
39
- 経過時間を確認してもらえると遅延の状況が把握できると思います。
40
-
41
-
42
-
43
- 以下のDownloadAudio2()では別スレッドからアクセスしてみましたが、
44
-
45
- メインスレッドからアクセスしなさいとエラーになります。
46
-
47
-
48
-
49
- そこで質問ですが、
50
-
51
- audioClipへのアクセス時にメインスレッドの遅延(UIの遅延)なく再生する方法は無いでしょうか?
52
-
53
- VideoPlayerで外部サーバーのmp4を再生した際は遅延なく再生できたので何か方法があるのではと祈ってます。
54
-
55
-
56
-
57
- どうぞよろしくお願いいたします。
58
-
59
-
60
-
61
- ```C#
62
-
63
- using System;
64
-
65
- using System.Collections;
66
-
67
- using UnityEngine;
68
-
69
- using UnityEngine.Networking;
70
-
71
- using System.Threading;
72
-
73
-
74
-
75
- public class MainController : MonoBehaviour
76
-
77
- {
78
-
79
- public AudioSource audioSource;
80
-
81
-
82
-
83
- void Start ()
84
-
85
- {
86
-
87
- if (audioSource == null)
88
-
89
- audioSource = this.gameObject.AddComponent<AudioSource>();
90
-
91
- }
92
-
93
-
94
-
95
-
96
-
97
- // ログ出力用の時間文字列を返す
98
-
99
- private string GetNow()
100
-
101
- {
102
-
103
- return "[" + DateTime.Now.ToString("HH:mm:ss.fff") + "]";
104
-
105
- }
106
-
107
-
108
-
109
-
110
-
111
- public void OnClick1()
112
-
113
- {
114
-
115
- // 遅延発生するケース
116
-
117
- StartCoroutine(DownloadAudio1());
118
-
119
- }
120
-
121
- public void OnClick2()
122
-
123
- {
124
-
125
- // 別スレッドで試すケース(エラー発生します)
126
-
127
- StartCoroutine( DownloadAudio2() );
128
-
129
- }
130
-
131
-
132
-
133
-
134
-
135
- /// <summary>
136
-
137
- /// 音声ファイルのダウンロード後に DownloadHandlerAudioClip の audioClip へアクセスする際に遅延が発生する。
138
-
139
- /// メインスレッド上の遅延の為、UIが固まる不具合となってしまう。
140
-
141
- /// PCでは気にならない程度だがAndroid実機では1秒程度の固まりが発生して困る。
142
-
143
- /// </summary>
144
-
145
- protected IEnumerator DownloadAudio1()
146
-
147
- {
148
-
149
- audioSource.Stop();
150
-
151
- audioSource.clip = null;
152
-
153
-
154
-
155
- string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
156
-
157
- using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
158
-
159
- {
160
-
161
- Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
162
-
163
- yield return uwr.SendWebRequest();
164
-
165
- if (uwr.isNetworkError || uwr.isHttpError)
166
-
167
- {
168
-
169
- Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
170
-
171
- }
172
-
173
- else if (uwr.isDone)
174
-
175
- {
176
-
177
- Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
178
-
179
- yield return null;
180
-
181
-
182
-
183
- Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
184
-
185
- audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
186
-
187
- Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");
188
-
189
- yield return null;
190
-
191
-
192
-
193
- Debug.Log(GetNow() + " Audio Play: Before" + "\n");
194
-
195
- audioSource.Play();
196
-
197
- Debug.Log(GetNow() + " Audio Play: After" + "\n");
198
-
199
- yield return null;
200
-
201
-
202
-
203
- yield return new WaitForSeconds(5f);
204
-
205
- audioSource.Stop();
206
-
207
- audioSource.clip = null;
208
-
209
- }
210
-
211
- uwr.Dispose();
212
-
213
- }
214
-
215
- }
216
-
217
-
218
-
219
-
220
-
221
- /// <summary>
222
-
223
- /// DownloadHandlerAudioClip の audioClip へアクセスする箇所をメインスレッド外にしてみる。
224
-
225
- /// しかし audioClip へのアクセス時にメインスレッドでないとエラーが発生する。
226
-
227
- /// </summary>
228
-
229
- protected IEnumerator DownloadAudio2()
230
-
231
- {
232
-
233
- audioSource.Stop();
234
-
235
- audioSource.clip = null;
236
-
237
-
238
-
239
- string mediaUrl = "http://amachamusic.chagasi.com/mp3/suisounishizumutsuki.mp3";
240
-
241
- using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(mediaUrl, AudioType.MPEG))
242
-
243
- {
244
-
245
- Debug.Log(GetNow() + " [WebRequest] SendWebRequest \n");
246
-
247
- yield return uwr.SendWebRequest();
248
-
249
- if (uwr.isNetworkError || uwr.isHttpError)
250
-
251
- {
252
-
253
- Debug.Log("Error: " + uwr.responseCode + " : " + uwr.error + "\n");
254
-
255
- }
256
-
257
- else if (uwr.isDone)
258
-
259
- {
260
-
261
- Debug.Log(GetNow() + " [WebRequest] isDone" + "\n");
262
-
263
- yield return null;
264
-
265
-
266
-
267
- // メインスレッドを確保
268
-
269
- var context = SynchronizationContext.Current;
270
-
271
- ThreadPool.QueueUserWorkItem((object state) =>
272
-
273
- {
274
-
275
- // 別スレッドで処理
276
-
277
- Debug.Log("[ThreadPool] Start");
278
-
279
-
280
-
281
- Debug.Log(GetNow() + " [AudioClip] downloadHandler: Before" + "\n");
282
-
283
- audioSource.clip = ((DownloadHandlerAudioClip)uwr.downloadHandler).audioClip;
284
-
285
- Debug.Log(GetNow() + " [AudioClip] downloadHandler: After" + "\n");
286
-
287
-
288
-
289
- Debug.Log(GetNow() + " Audio Play: Before" + "\n");
290
-
291
- audioSource.Play();
292
-
293
- Debug.Log(GetNow() + " Audio Play: After" + "\n");
294
-
295
-
296
-
297
- // メインスレッドに処理を戻す
298
-
299
- context.Post((d) => {
300
-
301
- Debug.Log(GetNow() + "[ThreadPool] End");
302
-
303
- audioSource.Stop();
304
-
305
- audioSource.clip = null;
306
-
307
- }, null);
308
-
309
- }, null);
310
-
311
- }
312
-
313
- uwr.Dispose();
314
-
315
- }
316
-
317
- }
318
-
319
- }
320
-
321
-
322
-
323
- ```

2

内容修正

2018/06/21 02:06

投稿

buibui80
buibui80

スコア1033

test CHANGED
File without changes
test CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  UnityWebRequestで得られた結果はメインスレッドからしかアクセスできないとのことでしたので、
18
18
 
19
- audioClipへのアクセス時にメインスレッド上で動的にAudioClipが作成されていることが遅延の原因かと思われます。
19
+ 遅延の原因はaudioClipへのアクセス時にメインスレッド上で動的にAudioClipが作成されていることと思われます。
20
20
 
21
21
  ```C#
22
22
 

1

説明追加

2018/06/19 13:04

投稿

buibui80
buibui80

スコア1033

test CHANGED
File without changes
test CHANGED
@@ -28,6 +28,10 @@
28
28
 
29
29
  以下は検証用ソースです。
30
30
 
31
+ エラーになりますがThreadを使用しているのでC#6が使用できるようUnityの設定が必要になります。
32
+
33
+ 参考: [C#6.0時代のUnity](https://qiita.com/divideby_zero/items/71a38acdbaa55e88e2d9)
34
+
31
35
 
32
36
 
33
37
  ログ出力の"[AudioClip] downloadHandler: Before" と "[AudioClip] downloadHandler: After" 間の