上一章节介绍过了命令模式,这一篇文章就简单的做一个小案例来巩固学习
搭建场景
简单的搭建一个场景就行 ,随便准备一个物体放在场景中位置Reset一下即可。
代码编写
- 定义接口(或者抽象类)ICommand 用来规范Command的行为。注意在命令模式中命令是桥接作用负责接受者和执行者之间的联调。所以一般会有很多的命令,每个命令都会有ICommand规范的方法同时也可以添加其他的方法。
public interface ICommand{void Execute();void UnExecute();
}
- 实现定义的接口(或者抽象类) 同时为了具有这种桥接的作用,MyCommand 需要持有Receiver
public enum Direction{Left,Down,Right,Up
}
public class MyCommand : ICommand{private Receiver _receiver;private Direction _direction;private GameObject _moveObj;private float _distance;public MyCommand(Direction direction,Receiver receiver,GameObject moveObj,float distance){this._receiver = receiver;this._direction = direction;this._moveObj = moveObj;this._distance = distance;}public void Execute(){_receiver.OperationDirection(_moveObj,_direction,_distance );}public void UnExecute(){_receiver.OperationDirection(_moveObj,InverseDirection(_direction),_distance );}private Direction InverseDirection(Direction direction){switch(direction){case Direction.Left:return Direction.Right;case Direction.Right:return Direction.Left;case Direction.Up:return Direction.Down;case Direction.Down:return Direction.Up;}}public override void ToString(){return $"{_moveObj.name}:{DirectionStr(_direction)}:{_distance.ToString()}";}private string DirectionStr(Direction dircteion) {switch (dircteion) { case Direction.Left:return "Left";case Direction.Right:return "Right";case Direction.Up:return "Up";case Direction.Down:return "Down";default:return default;}
}
}
3.接受者,接受者的意思是接受命令执行自身的函数
public class Receiver{public void OperationDirection(GameObject moveObj,Direction direction,float distance){switch(direction){case Direction.Left:MoveX(moveObj,-distance);break;case Direction.Right:MoveX(moveObj,distance);break;case Direction.Up:MoveY(moveObj,distance);break;case Direction.Up:MoveY(moveObj,-distance);break;}}private void MoveX(GameObject moveObj,float distance){var tempPos = moveObj.transform.position;tempPos .x+=distance;moveObj.transform.position = tempPos;}private void MoveY(GameObject moveObj,float distance){var tempPos = moveObj.transform.position;tempPos.y+=distance;moveObj.transform.position = tempPos;}
}
4.执行者,挂载在场景中的任意物体上(建议放空物体上)负责代码的执行 调度
public class InputHandler : MonoBehaviour{private Receiver _receiver;[SerializeField][Tooltip("移动距离")]private float distance = 1f;private List<ICommand> commands = new List<ICommand>(); // 存储命令方便回溯private int currentCommandNum = 0; // 当前执行的命令public GameObject moveObj; //控制的物体上面的那个Move直接拖到这里进行绑定 private void Start(){_receiver= new Receiver();// 空处理 可写可不写}private void Move(Direction direction){var command = new MyCommand(direction,_receiver,moveObj,distance);command.Execute();commands.Add(command);currentCommandNum++;}private void Undo(){if(currentCommandNum > 0 ){currentCommandNum--;MyCommand command= (MyCommand )commands[currentCommandNum];command.UnExecute();}}private void Redo(){if (currentCommandNum < commands.Count) { MyCommand command= (MyCommand )commands[currentCommandNum];currentCommandNum++;command.Execute();}}void OnGUI(){string label = " start";if (currentCommandNum == 0){label = ">" + label;}label += "\n";for (int i = 0; i < commands.Count; i++){if (i == currentCommandNum - 1)label += "> " + commands[i].ToString() + "\n";elselabel += " " + commands[i].ToString() + "\n";}GUI.Label(new Rect(0, 0, 400, 800), label);}private void Update(){if (Input.GetKeyDown(KeyCode.UpArrow)|| Input.GetKeyDown(KeyCode.W)) { moveUp(); }if (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)) { moveDown(); }if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)){ moveLeft(); }if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)) { moveRight(); }if (Input.GetKeyDown(KeyCode.R)){ Redo(); }if (Input.GetKeyDown(KeyCode.U)){ Undo(); }}void moveUp() { Move(Direction.Up); }void moveDown() { Move(Direction.Down); }void moveLeft() { Move(Direction.Left); }void moveRight() { Move(Direction.Right); }
}
现在就基本上已经做完了,是一个很简单的案例用来巩固学习命令模式