概念
命令是具现化的方法调用。
命令模式是一种回调的面向对象实现。
每条命令为1个类的实例,从而可以被传递、存储、重复利用。
例子
制作移动命令,按“wasd”时控制角色移动,按空格键时回退角色移动。
![](https://img.haomeiwen.com/i10492731/42850dea3edbbdfa.gif)
Command.cs
每个命令有2个方法:Execute、Undo。
当前实现1个具体的命令MoveCommand来控制IMoveExecutor移动(Move)
using UnityEngine;
public abstract class Command
{
public abstract void Execute(IExecutor executor);
public abstract void Undo(IExecutor executor);
}
public class MoveCommand : Command
{
private Vector3 _moveOffset;
public MoveCommand(Vector3 moveOffset)
{
_moveOffset = moveOffset;
}
public override void Execute(IExecutor executor)
{
if (executor is IMoveExecutor moveExecutor)
{
moveExecutor.Move(_moveOffset);
}
}
public override void Undo(IExecutor executor)
{
if (executor is IMoveExecutor moveExecutor)
{
moveExecutor.Move(_moveOffset * -1);
}
}
}
RoleMoveCtr.cs
实现IMoveExecutor,控制实际的transform移动。
using UnityEngine;
public interface IExecutor
{
}
interface IMoveExecutor : IExecutor
{
void Move(Vector3 offset);
}
// 控制角色移动,需挂在要移动的transform上。
public class RoleMoveCtr : MonoBehaviour, IMoveExecutor
{
private void Start()
{
Init();
}
private void OnDestroy()
{
MyDestroy();
}
private void Init()
{
}
private void MyDestroy()
{
}
public void Move(Vector3 offset)
{
transform.Translate(offset);
}
}
CommandTest.cs
测试流程:接收输入生成并执行命令、或反向执行已有命令(实现 撤销移动 的操作)
using System.Collections.Generic;
using UnityEngine;
public class CommandTest : MonoBehaviour
{
[SerializeField]
private RoleMoveCtr _mover;
[SerializeField]
private float _moveSpeed;
private Stack<Command> _commands;
private void Start()
{
Init();
}
private void Update()
{
MyUpdate();
}
private void OnDestroy()
{
MyDestroy();
}
private void Init()
{
_commands = new Stack<Command>();
}
private void MyUpdate()
{
if (Input.GetKey(KeyCode.Space))
{
if (_commands.Count > 0)
{
_commands.Pop().Undo(_mover);
}
}
else
{
Vector3 moveOffset = Vector3.zero;
if (Input.GetKey(KeyCode.W))
{
moveOffset = new Vector3(0, Time.deltaTime, 0);
}
else if (Input.GetKey(KeyCode.S))
{
moveOffset = new Vector3(0, -1 * Time.deltaTime, 0);
}
else if (Input.GetKey(KeyCode.A))
{
moveOffset = new Vector3(-1 * Time.deltaTime, 0, 0);
}
else if (Input.GetKey(KeyCode.D))
{
moveOffset = new Vector3(Time.deltaTime, 0, 0);
}
if (moveOffset != Vector3.zero)
{
Command cmd = new MoveCommand(moveOffset * _moveSpeed);
_commands.Push(cmd);
cmd.Execute(_mover);
}
}
}
private void MyDestroy()
{
_commands.Clear();
_commands = null;
}
}
网友评论