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 commands = new List(); public readonly ExecutionMode mode; /// /// 包含了指令组执行过程中产生的所有上下文信息。不论是内部还是外部的上下文皆可获取。 /// public readonly CommandContext groupContext; public CommandGroup(params CommandBase[] commands) { this.mode = ExecutionMode.Sequential; this.groupContext = new CommandContext(); this.commands.AddRange(commands); } 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; } /// /// 获取所有子指令,包含嵌套的指令组中的指令。 /// /// 是否也包含CommandGroup,false则不会将CommandGroup返回 /// public List GetAllCommands(bool alsoIncludeGroups = false) { //CommandBase可能也是CommandGroup,需要递归获取 List allCommands = new List(); 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 GetAllCommands() where T : CommandBase { return GetAllCommands(true).OfType().ToList(); } protected override IObservable OnExecute(CommandContext outerContext) { // --- 核心修正 --- // 我们不再直接调用 cmd.Execute(context)。 // 而是创建一个“延迟执行”的 Observable 序列。 // Defer 会将对 Execute 的调用推迟到 Concat/WhenAll 真正订阅它的时候。 var lazyCommandObservables = commands.Select(cmd => Observable.Defer(() => { IObservable result = cmd.Execute(outerContext); groupContext.Merge(outerContext); groupContext.Merge(cmd.selfContext); return result; }) ); IObservable 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) 会自动应用到这里返回的流上,所以无需重复添加。 } } }