架构大更
This commit is contained in:
@@ -3,22 +3,24 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Continentis.MainGame.Card;
|
||||
using Continentis.MainGame.Character;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using DG.Tweening;
|
||||
using SLSFramework.General;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
|
||||
namespace Continentis.MainGame.Commands
|
||||
{
|
||||
public class Cmd_ExhaustCards : CommandBase
|
||||
{
|
||||
private bool isPlayer;
|
||||
private readonly bool isPlayer;
|
||||
private readonly DeckSubmodule deck;
|
||||
private readonly List<CardInstance> cardsToExhaust;
|
||||
private readonly float interval;
|
||||
private readonly float singleCardAnimationDuration = 0.5f; // 单张卡牌的动画时长
|
||||
|
||||
|
||||
private const float SingleCardAnimationDuration = 0.5f;
|
||||
|
||||
public Cmd_ExhaustCards(bool isPlayer, DeckSubmodule deck, List<CardInstance> cards, float interval)
|
||||
{
|
||||
this.isPlayer = isPlayer;
|
||||
@@ -26,76 +28,64 @@ namespace Continentis.MainGame.Commands
|
||||
this.cardsToExhaust = cards;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
protected override IObservable<Unit> OnExecute(CommandContext outerContext)
|
||||
{
|
||||
if (cardsToExhaust == null || cardsToExhaust.Count == 0)
|
||||
{
|
||||
return Observable.Return(Unit.Default);
|
||||
}
|
||||
|
||||
Func<CardInstance, IObservable<Unit>> exhaustAction = isPlayer ? PlayerExhaustCard : NpcExhaustCard;
|
||||
|
||||
// --- 情况1:并行丢弃 (所有卡牌动画同时开始) ---
|
||||
protected override async UniTask ExecuteAsync(CommandContext outerContext)
|
||||
{
|
||||
if (cardsToExhaust == null || cardsToExhaust.Count == 0) return;
|
||||
|
||||
if (interval <= 0f)
|
||||
{
|
||||
// 为每张卡牌创建一个“懒加载”的丢弃动画流。
|
||||
var allDiscardAnimations = cardsToExhaust.Select(card =>
|
||||
Observable.Defer(() => exhaustAction(card))
|
||||
);
|
||||
|
||||
// 使用 WhenAll 等待所有的并行任务都完成。
|
||||
// 只有当最后一个动画结束时,WhenAll 才会发出完成信号。
|
||||
return Observable.WhenAll(allDiscardAnimations).AsUnitObservable();
|
||||
await UniTask.WhenAll(cardsToExhaust.Select(card => ExhaustCardAsync(card)));
|
||||
}
|
||||
|
||||
// --- 情况2:交错丢弃 (按固定间隔开始动画) ---
|
||||
else
|
||||
{
|
||||
var cardStream = cardsToExhaust.ToObservable();
|
||||
var timerStream = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(interval));
|
||||
|
||||
return timerStream
|
||||
.Zip(cardStream, (_, card) => card)
|
||||
// 核心:不再使用 .Do(..).Subscribe(),而是使用 Select 将每个 card 转换为
|
||||
// 其对应的动画流。这样主流程就“知道”了每个动画的存在。
|
||||
.Select(card => exhaustAction(card))
|
||||
// 使用 Merge 将所有交错开始的动画流合并为一个流。
|
||||
// Merge 会同时运行所有这些动画,并在最后一个动画也完成时,它才会完成。
|
||||
.Merge()
|
||||
// 使用 Last 来确保我们只在整个 Merge 流全部结束后,才发出最终的完成信号。
|
||||
.Last()
|
||||
.AsUnitObservable();
|
||||
var tasks = new UniTask[cardsToExhaust.Count];
|
||||
for (int i = 0; i < cardsToExhaust.Count; i++)
|
||||
{
|
||||
CardInstance captured = cardsToExhaust[i];
|
||||
tasks[i] = ExhaustCardWithDelayAsync(captured, i * interval);
|
||||
}
|
||||
await UniTask.WhenAll(tasks);
|
||||
}
|
||||
}
|
||||
|
||||
private IObservable<Unit> PlayerExhaustCard(CardInstance card)
|
||||
{
|
||||
deck.TransferCard(deck.Pile(card.cardLocation.pileName), deck.ExhaustPile, card);
|
||||
card.eventSubmodule.onExhaust.Invoke();
|
||||
|
||||
card.handCardView.TransferCardView(CombatUIManager.Instance.combatMainPage.exhaustPile);
|
||||
|
||||
RectTransform cardTransform = card.handCardView.cardTransform;
|
||||
//Vector3 deltaMove = Vector3.zero - card.handCardView.cardTransform.localPosition;
|
||||
Vector3 randomLift = new Vector3(0, Random.Range(200f, 600f), 0);
|
||||
|
||||
//cardTransform.DOBlendableLocalMoveBy(deltaMove, singleCardAnimationDuration).Play();
|
||||
cardTransform.DOBlendableLocalMoveBy(randomLift, singleCardAnimationDuration * 0.5f).SetLoops(2, LoopType.Yoyo).Play();
|
||||
//cardTransform.DOLocalRotate(new Vector3(0, 0, 720f), singleCardAnimationDuration, RotateMode.FastBeyond360).Play();
|
||||
cardTransform.DOScale(Vector3.zero, singleCardAnimationDuration).SetEase(Ease.Linear).OnComplete(() =>
|
||||
{
|
||||
cardTransform.anchoredPosition = Vector2.zero;
|
||||
}).Play();
|
||||
|
||||
return Observable.Timer(TimeSpan.FromSeconds(singleCardAnimationDuration)).AsUnitObservable();
|
||||
private async UniTask ExhaustCardWithDelayAsync(CardInstance card, float delay)
|
||||
{
|
||||
if (delay > 0f)
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(delay));
|
||||
await ExhaustCardAsync(card);
|
||||
}
|
||||
|
||||
private IObservable<Unit> NpcExhaustCard(CardInstance card)
|
||||
private async UniTask ExhaustCardAsync(CardInstance card)
|
||||
{
|
||||
if (isPlayer)
|
||||
await PlayerExhaustCardAsync(card);
|
||||
else
|
||||
await NpcExhaustCardAsync(card);
|
||||
}
|
||||
|
||||
private async UniTask PlayerExhaustCardAsync(CardInstance card)
|
||||
{
|
||||
deck.TransferCard(deck.Pile(card.cardLocation.pileName), deck.ExhaustPile, card);
|
||||
card.eventSubmodule.onExhaust.Invoke();
|
||||
return Observable.Timer(TimeSpan.FromSeconds(singleCardAnimationDuration)).AsUnitObservable();
|
||||
card.handCardView.TransferCardView(CombatUIManager.Instance.combatMainPage.exhaustPile);
|
||||
|
||||
RectTransform cardTransform = card.handCardView.cardTransform;
|
||||
Vector3 randomLift = new Vector3(0f, Random.Range(200f, 600f), 0f);
|
||||
|
||||
cardTransform.DOBlendableLocalMoveBy(randomLift, SingleCardAnimationDuration * 0.5f)
|
||||
.SetLoops(2, LoopType.Yoyo).Play();
|
||||
cardTransform.DOScale(Vector3.zero, SingleCardAnimationDuration).SetEase(Ease.Linear)
|
||||
.OnComplete(() => cardTransform.anchoredPosition = Vector2.zero).Play();
|
||||
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(SingleCardAnimationDuration));
|
||||
}
|
||||
|
||||
private async UniTask NpcExhaustCardAsync(CardInstance card)
|
||||
{
|
||||
deck.TransferCard(deck.Pile(card.cardLocation.pileName), deck.ExhaustPile, card);
|
||||
card.eventSubmodule.onExhaust.Invoke();
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(SingleCardAnimationDuration));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user