修正音频异步取消语义
This commit is contained in:
@@ -211,6 +211,10 @@ namespace FlowScope.Audio
|
|||||||
var handle = await _resources.LoadAsync<AudioClip>(key, cancellationToken);
|
var handle = await _resources.LoadAsync<AudioClip>(key, cancellationToken);
|
||||||
return ValidateLoadedClip(key, handle);
|
return ValidateLoadedClip(key, handle);
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Failed to load audio clip '{key}'.", exception);
|
throw new InvalidOperationException($"Failed to load audio clip '{key}'.", exception);
|
||||||
|
|||||||
@@ -209,6 +209,34 @@ namespace FlowScope.Tests.PlayMode.Audio
|
|||||||
Assert.That(handle.IsPlaying, Is.True);
|
Assert.That(handle.IsPlaying, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public System.Collections.IEnumerator PlayBgmAsync_WhenCanceled_ThrowsOperationCanceledException()
|
||||||
|
{
|
||||||
|
var service = CreateService();
|
||||||
|
using var cts = new CancellationTokenSource();
|
||||||
|
cts.Cancel();
|
||||||
|
var sourceCountBeforePlay = Object.FindObjectsOfType<AudioSource>().Length;
|
||||||
|
|
||||||
|
yield return ThrowsAsync<OperationCanceledException>(
|
||||||
|
service.PlayBgmAsync("bgm-a", cancellationToken: cts.Token));
|
||||||
|
|
||||||
|
Assert.That(Object.FindObjectsOfType<AudioSource>().Length, Is.EqualTo(sourceCountBeforePlay));
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public System.Collections.IEnumerator PlaySfxAsync_WhenCanceled_ThrowsOperationCanceledException()
|
||||||
|
{
|
||||||
|
var service = CreateService();
|
||||||
|
using var cts = new CancellationTokenSource();
|
||||||
|
cts.Cancel();
|
||||||
|
var sourceCountBeforePlay = Object.FindObjectsOfType<AudioSource>().Length;
|
||||||
|
|
||||||
|
yield return ThrowsAsync<OperationCanceledException>(
|
||||||
|
service.PlaySfxAsync("sfx", cts.Token));
|
||||||
|
|
||||||
|
Assert.That(Object.FindObjectsOfType<AudioSource>().Length, Is.EqualTo(sourceCountBeforePlay));
|
||||||
|
}
|
||||||
|
|
||||||
private AudioService CreateService(AudioServiceConfig config = null)
|
private AudioService CreateService(AudioServiceConfig config = null)
|
||||||
{
|
{
|
||||||
var gameObject = new GameObject("AudioServiceTest");
|
var gameObject = new GameObject("AudioServiceTest");
|
||||||
@@ -249,6 +277,27 @@ namespace FlowScope.Tests.PlayMode.Audio
|
|||||||
onCompleted(task.Result);
|
onCompleted(task.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static System.Collections.IEnumerator ThrowsAsync<TException>(Task task)
|
||||||
|
where TException : Exception
|
||||||
|
{
|
||||||
|
while (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsFaulted && task.Exception?.GetBaseException() is TException)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.IsCanceled && typeof(TException) == typeof(OperationCanceledException))
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Fail($"Expected {typeof(TException).Name}.");
|
||||||
|
}
|
||||||
|
|
||||||
private static AudioClip CreateClip(string name, float lengthSeconds)
|
private static AudioClip CreateClip(string name, float lengthSeconds)
|
||||||
{
|
{
|
||||||
var sampleCount = Mathf.CeilToInt(44100 * lengthSeconds);
|
var sampleCount = Mathf.CeilToInt(44100 * lengthSeconds);
|
||||||
@@ -285,6 +334,7 @@ namespace FlowScope.Tests.PlayMode.Audio
|
|||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
LoadRequests++;
|
LoadRequests++;
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
if (typeof(T) != typeof(AudioClip))
|
if (typeof(T) != typeof(AudioClip))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"missing resource: {key}");
|
throw new InvalidOperationException($"missing resource: {key}");
|
||||||
|
|||||||
Reference in New Issue
Block a user