用一个异步方法来播放一个动画,正常情况是:动画播放结束时,异步方法宣告结束。那如果我提前取消这个异步任务,那在这个异步方法里面,我要怎么停止播放呢?!
一、播放animation动画的异步实现
- 1、用play播放动画片段
- 2、await一段时间,等动画播放结束
- 3、用stop停止动画播放
二、两种实现方式
1 、纯多任务模式的实现
实现原理:
定义了两个结束的事件(或者Task):
(1)第一个是播放时长到点了
(2)第二个是用户取消了异步任务
(3)用whenAny等待
/// <summary>
/// 等待一个动画播放完毕
/// 中间如果任务被取消,则停止播放动画
/// </summary>
/// <param name="Anim"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <param name="speed"></param>
/// <param name="ctk">任务取消标志</param>
/// <returns></returns>
public static async UniTask<bool> PlayAnim(Animation Anim, float startTime, float endTime, float speed, CancellationToken ctk)
{
Debug.Log($"当前Time.timeScale = {
Time.timeScale}");
float t = (endTime - startTime) * Time.timeScale; //考虑到动画时间倍率
Debug.Log($"动画的时长为:{
t}秒");
Anim[Anim.clip.name].time = startTime;//跳过第几帧
Anim[Anim.clip.name].speed = speed;
Anim.Play(Anim.clip.name); //Play()
//如果时间到点,结束,并停止动画
Func<UniTask> timeFn = async () =>
{
await UniTask.Delay(TimeSpan.FromSeconds(t), cancellationToken: ctk);
Anim.Stop();
};
//用户取消任务,结束,并停止动画
Func<UniTask> cancelFn = async () =>
{
Debug.Log("开始执行cancelFn的循环:");
while (true)
{
Debug.Log($"ctk.IsCancellationRequested = {
ctk.IsCancellationRequested}");
if (ctk.IsCancellationRequested)
{
Debug.Log($"任务取消:{
ctk.IsCancellationRequested}");
Anim.Stop();
break;
};
await UniTask.Yield(); //注意,这里不能随意加ctk,不然不能停,直接跳出了
//await UniTask.Yield(ctk);
}
Debug.Log("结束cancelFn的循环");
};
//等待结束
var idx = await UniTask.WhenAny(timeFn(), cancelFn()).AttachExternalCancellation(ctk);
Debug.Log($"任务结束:结束方式为:{
idx} 备注:0 = 动画播放结束,1 = 用户取消任务");
return true;
}
2 、手工启动一个循环,每帧检查结束条件
/// <summary>
/// 等待一个动画播放完毕
/// 中间如果任务被取消,则停止播放动画
/// 改进了结束的判断方式
/// </summary>
/// <param name="Anim"></param>
/// <param name="startTime"></param>
/// <param name="endTime"></param>
/// <param name="speed"></param>
/// <param name="ctk">任务取消标志</param>
/// <returns></returns>
public static async UniTask<bool> PlayAnim2(Animation Anim, float startTime, float endTime, float speed, CancellationToken ctk)
{
Debug.Log($"当前Time.timeScale = {