Files
Continentis/Assets/Scripts/ScriptExtensions/CommandQueue/CommandGroup.cs
SoulliesOfficial 2906206f0c keyword + animation
2025-10-27 07:04:34 -04:00

125 lines
4.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UnityEngine;
namespace SLSFramework.General
{
public enum ExecutionMode { Sequential, Parallel }
public class CommandGroup : CommandBase
{
public readonly List<CommandBase> commands = new List<CommandBase>();
public readonly ExecutionMode mode;
/// <summary>
/// 包含了指令组执行过程中产生的所有上下文信息。不论是内部还是外部的上下文皆可获取。
/// </summary>
public readonly CommandContext groupContext;
public CommandGroup(ExecutionMode mode, params CommandBase[] commands)
{
this.mode = mode;
this.groupContext = new CommandContext();
this.commands.AddRange(commands);
}
public CommandGroup(ExecutionMode mode, CommandContext groupContext, params CommandBase[] commands)
{
this.mode = mode;
this.groupContext = groupContext;
this.commands.AddRange(commands);
}
public override CommandBase Clone()
{
CommandGroup newGroup = new CommandGroup(mode);
foreach (var cmd in commands)
{
newGroup.AddCommand(cmd.Clone());
}
return newGroup;
}
public CommandGroup AddCommand(CommandBase command)
{
commands.Add(command);
return this;
}
/// <summary>
/// 获取所有子指令,包含嵌套的指令组中的指令。
/// </summary>
/// <param name="alsoIncludeGroups">是否也包含CommandGroupfalse则不会将CommandGroup返回</param>
/// <returns></returns>
public List<CommandBase> GetAllCommands(bool alsoIncludeGroups = false)
{
//CommandBase可能也是CommandGroup,需要递归获取
List<CommandBase> allCommands = new List<CommandBase>();
if (alsoIncludeGroups)
{
allCommands.Add(this);
}
foreach (CommandBase cmd in commands)
{
if (cmd is CommandGroup group)
{
if (alsoIncludeGroups)
{
allCommands.Add(group);
}
allCommands.AddRange(group.GetAllCommands(alsoIncludeGroups));
}
else
{
allCommands.Add(cmd);
}
}
return allCommands;
}
public List<T> GetAllCommands<T>() where T : CommandBase
{
return GetAllCommands(true).OfType<T>().ToList();
}
protected override IObservable<Unit> OnExecute(CommandContext outerContext)
{
// --- 核心修正 ---
// 我们不再直接调用 cmd.Execute(context)。
// 而是创建一个“延迟执行”的 Observable 序列。
// Defer 会将对 Execute 的调用推迟到 Concat/WhenAll 真正订阅它的时候。
var lazyCommandObservables = commands.Select(cmd =>
Observable.Defer(() =>
{
IObservable<Unit> result = cmd.Execute(outerContext);
groupContext.Merge(outerContext);
groupContext.Merge(cmd.selfContext);
return result;
})
);
IObservable<Unit> executionFlow;
if (mode == ExecutionMode.Sequential)
{
// Concat 现在会按顺序地、一个一个地订阅 lazyCommandObservables 中的 Defer 对象。
// 每订阅一个,对应的 cmd.Execute() 才会被真正调用。
executionFlow = lazyCommandObservables.Concat();
}
else
{
// WhenAll 同样能很好地处理延迟的 Observable 序列。
executionFlow = Observable.WhenAll(lazyCommandObservables).AsUnitObservable();
}
return executionFlow;
// 注意:基类中的 TakeUntil(forceCompleteSubject) 会自动应用到这里返回的流上,所以无需重复添加。
}
}
}