怎么用链接进自己做的网站吗,金坛做网站公司,wap网页开发,万家灯火网站建设文章目录 ⌨️ 命令模式#xff08;Command Pattern#xff09;深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码#xff08;可撤销的建造系统#xff09;1. 定义命令接口与接收者2. 实现具体命令3. 命令管理器#xff08;Invoker#xff09;4. 客户端使… 文章目录 ⌨️ 命令模式Command Pattern深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码可撤销的建造系统1. 定义命令接口与接收者2. 实现具体命令3. 命令管理器Invoker4. 客户端使用 四、模式进阶技巧1. 宏命令组合命令2. 异步命令执行3. 命令序列化 五、游戏开发典型应用场景六、性能优化策略七、模式对比与选择八、最佳实践原则九、常见问题解决方案 ⌨️ 命令模式Command Pattern深度解析
——以Unity实现可撤销操作与智能输入系统为核心案例 一、模式本质与核心价值
核心目标 ✅ 封装操作为对象支持撤销/重做功能 ✅ 解耦请求发送者与执行者提升系统扩展性 ✅ 支持请求队列与日志记录实现复杂操作管理
关键术语
Command命令接口定义执行操作的统一接口ConcreteCommand具体命令实现具体业务逻辑Invoker调用者触发命令执行如输入处理器Receiver接收者实际执行操作的对象
数学表达 操作历史H可表示为命令序列 H [C₁, C₂, …, Cₙ] 撤销操作为H.pop() → ExecuteInverse(Cₙ) 二、经典UML结构 #mermaid-svg-U5xyiEeaJOhLcRoq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-U5xyiEeaJOhLcRoq .error-icon{fill:#552222;}#mermaid-svg-U5xyiEeaJOhLcRoq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U5xyiEeaJOhLcRoq .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-U5xyiEeaJOhLcRoq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U5xyiEeaJOhLcRoq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U5xyiEeaJOhLcRoq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U5xyiEeaJOhLcRoq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U5xyiEeaJOhLcRoq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U5xyiEeaJOhLcRoq .marker.cross{stroke:#333333;}#mermaid-svg-U5xyiEeaJOhLcRoq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U5xyiEeaJOhLcRoq g.classGroup text{fill:#9370DB;fill:#131300;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-U5xyiEeaJOhLcRoq g.classGroup text .title{font-weight:bolder;}#mermaid-svg-U5xyiEeaJOhLcRoq .nodeLabel,#mermaid-svg-U5xyiEeaJOhLcRoq .edgeLabel{color:#131300;}#mermaid-svg-U5xyiEeaJOhLcRoq .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-U5xyiEeaJOhLcRoq .label text{fill:#131300;}#mermaid-svg-U5xyiEeaJOhLcRoq .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-U5xyiEeaJOhLcRoq .classTitle{font-weight:bolder;}#mermaid-svg-U5xyiEeaJOhLcRoq .node rect,#mermaid-svg-U5xyiEeaJOhLcRoq .node circle,#mermaid-svg-U5xyiEeaJOhLcRoq .node ellipse,#mermaid-svg-U5xyiEeaJOhLcRoq .node polygon,#mermaid-svg-U5xyiEeaJOhLcRoq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U5xyiEeaJOhLcRoq .divider{stroke:#9370DB;stroke:1;}#mermaid-svg-U5xyiEeaJOhLcRoq g.clickable{cursor:pointer;}#mermaid-svg-U5xyiEeaJOhLcRoq g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-U5xyiEeaJOhLcRoq g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-U5xyiEeaJOhLcRoq .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-U5xyiEeaJOhLcRoq .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-U5xyiEeaJOhLcRoq .dashed-line{stroke-dasharray:3;}#mermaid-svg-U5xyiEeaJOhLcRoq #compositionStart,#mermaid-svg-U5xyiEeaJOhLcRoq .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #compositionEnd,#mermaid-svg-U5xyiEeaJOhLcRoq .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #dependencyStart,#mermaid-svg-U5xyiEeaJOhLcRoq .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #dependencyStart,#mermaid-svg-U5xyiEeaJOhLcRoq .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #extensionStart,#mermaid-svg-U5xyiEeaJOhLcRoq .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #extensionEnd,#mermaid-svg-U5xyiEeaJOhLcRoq .extension{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #aggregationStart,#mermaid-svg-U5xyiEeaJOhLcRoq .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq #aggregationEnd,#mermaid-svg-U5xyiEeaJOhLcRoq .aggregation{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-U5xyiEeaJOhLcRoq .edgeTerminals{font-size:11px;}#mermaid-svg-U5xyiEeaJOhLcRoq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} «interface» ICommand Execute() Undo() MoveCommand -_unit: Unit -_from: Vector3 -_to: Vector3 Execute() Undo() InputHandler -_commandHistory: StackICommand HandleInput() Unit Move(Vector3) 三、Unity实战代码可撤销的建造系统
1. 定义命令接口与接收者
public interface ICommand {void Execute();void Undo();
}public class Builder : MonoBehaviour {public void BuildWall(Vector3 position) {Instantiate(wallPrefab, position, Quaternion.identity);}public void DestroyWall(Vector3 position) {var wall Physics.OverlapSphere(position, 0.5f).FirstOrDefault(c c.CompareTag(Wall));if(wall ! null) Destroy(wall.gameObject);}
}2. 实现具体命令
public class BuildCommand : ICommand {private Builder _builder;private Vector3 _position;private GameObject _builtWall;public BuildCommand(Builder builder, Vector3 pos) {_builder builder;_position pos;}public void Execute() {_builder.BuildWall(_position);_builtWall GameObject.FindWithTag(Wall);}public void Undo() {if(_builtWall ! null) {_builder.DestroyWall(_builtWall.transform.position);}}
}3. 命令管理器Invoker
public class CommandManager : MonoBehaviour {private StackICommand _commandHistory new();private StackICommand _redoStack new();public void ExecuteCommand(ICommand command) {command.Execute();_commandHistory.Push(command);_redoStack.Clear();}public void Undo() {if(_commandHistory.Count 0) return;var cmd _commandHistory.Pop();cmd.Undo();_redoStack.Push(cmd);}public void Redo() {if(_redoStack.Count 0) return;var cmd _redoStack.Pop();cmd.Execute();_commandHistory.Push(cmd);}
}4. 客户端使用
public class BuildController : MonoBehaviour {[SerializeField] private Builder builder;[SerializeField] private CommandManager cmdManager;void Update() {if(Input.GetMouseButtonDown(0)) {var ray Camera.main.ScreenPointToRay(Input.mousePosition);if(Physics.Raycast(ray, out var hit)) {var cmd new BuildCommand(builder, hit.point);cmdManager.ExecuteCommand(cmd);}}if(Input.GetKeyDown(KeyCode.Z)) cmdManager.Undo();if(Input.GetKeyDown(KeyCode.Y)) cmdManager.Redo();}
}四、模式进阶技巧
1. 宏命令组合命令
public class MacroCommand : ICommand {private ListICommand _commands new();public void Add(ICommand cmd) _commands.Add(cmd);public void Execute() {foreach(var cmd in _commands) cmd.Execute();}public void Undo() {foreach(var cmd in _commands.AsEnumerable().Reverse()) {cmd.Undo();}}
}2. 异步命令执行
public class AsyncMoveCommand : ICommand {public async Task ExecuteAsync() {await MoveCoroutine();}private IEnumerator MoveCoroutine() {// 移动动画协程}
}3. 命令序列化
[System.Serializable]
public class SaveCommand : ICommand {public string SaveData;public void Execute() {PlayerPrefs.SetString(Save, SaveData);}public void Undo() {PlayerPrefs.DeleteKey(Save);}
}五、游戏开发典型应用场景 输入映射系统 public class InputSystem {private DictionaryKeyCode, ICommand _keyBindings new();public void Update() {foreach(var binding in _keyBindings) {if(Input.GetKeyDown(binding.Key)) {binding.Value.Execute();}}}
}AI行为队列 public class AICommander {private QueueICommand _actionQueue new();public void ScheduleAction(ICommand cmd) {_actionQueue.Enqueue(cmd);}void Update() {if(_actionQueue.Count 0) {_actionQueue.Dequeue().Execute();}}
}网络命令同步 public class NetworkCommand : ICommand {public void Execute() {if(PhotonNetwork.IsMasterClient) {photonView.RPC(RpcExecute, RpcTarget.All);}}[PunRPC]private void RpcExecute() {// 实际执行逻辑}
}回放系统 public class ReplaySystem {private ListTimestampedCommand _commandLog new();public void Record(ICommand cmd) {_commandLog.Add(new TimestampedCommand(Time.time, cmd));}public void PlayReplay() {StartCoroutine(ReplayCommands());}
}六、性能优化策略
策略实现方式适用场景命令池重用命令对象高频命令创建批量处理合并相似命令大量小操作延迟执行分帧处理命令队列性能敏感场景二进制序列化优化存储空间回放/存档系统 七、模式对比与选择
维度命令模式策略模式目的封装操作替换算法状态管理支持撤销无状态执行时机可延迟执行立即执行典型应用输入处理AI决策 八、最佳实践原则
接口最小化保持命令接口简洁不可变状态命令参数应在构造时确定原子操作每个命令代表一个完整操作安全撤销确保Undo操作的幂等性public void Undo() {if(_isUndone) return;// 撤销逻辑_isUndone true;
}九、常见问题解决方案
Q1如何处理命令依赖 → 实现命令版本控制
public class VersionedCommand : ICommand {public int Version;public bool IsCompatibleWith(int currentVersion) {return Version currentVersion;}
}Q2如何优化大量命令存储 → 使用增量压缩
public class DeltaCommand : ICommand {private byte[] _deltaData;public void Compress(CommandState fullState) {// 计算差异并压缩}
}Q3如何处理网络延迟 → 实现预测回滚
public class PredictiveMoveCommand : ICommand {public void Execute() {_predictedPosition CalculatePrediction();_serverPosition NetworkSync();if(_predictedPosition ! _serverPosition) {RollbackAndResync();}}
}上一篇 【行为型之责任链模式】游戏开发实战——Unity灵活事件处理系统的架构核心 下一篇 【行为型之解释器模式】游戏开发实战——Unity动态公式解析与脚本系统的架构奥秘