指令模式
1.配置输入
所有游戏中都包含玩家输入指令的部分(这些部分通常写在游戏循环中 如unity中的UpData() ) 游戏会每一帧都进行一次读取,当玩家按下相应按键时 则会进行对应方法
为了可以时刻检测并记录玩家进行的操作,或者对某个对应的操作的指令进行更改,我们需要将这些输入封装为一个类似于变量的对象
- 定义一个基类代表游戏中可触发的行为
public Interface Command
{
public void excute(){}
}
- 为不同游戏行为定义相应子类
public class JumpCommand : Command
(
public void excute()
{
jump();
}
)
public class FireCommand : Command
{
public void excute()
{
Fire();
}
}
- 在代码部分对定义的子类进行实例化 并放入输入部分
public class InputHandler
{
JumpCommand jumpCommand;
jumpCommand = new JumpCommand(){};
FireCommand fireCommand;
fireCommand = new fireCommand(){};
if(Input.GetKeyDown(KeyCode.X))
{
jumpCommand;
}
else if(Input.GetKeyDown(KeyCode.Y))
{
fireCommand;
}
}
相比起直接将控制内容写入游戏循环 在新的代码中 玩家每进行一次输入 都会访问一次对应的指令类
2.用户类
当我们已经进行了一些操作时,需要对游戏中的某些对象进行操作 大部分情况是玩家所控制的角色,但有时需要改变角色类型或是更广泛的内容 在这种情况下 需要我们对游戏中的对象进行进一步封装,当玩家进行操作时,游戏内会对对象发出一定命令流 并找到接收命令的对象 再执行相关操作
public class Singleton<T>where T : MonoBehaviour
{
protected Singleton(){};
private static T _inst = null;
public static T instance => _inst ?? (_inst = new T());
public static void Clear()
{
_inst = null;
}
}
首先我们要单例化指令类
public class JumpCommand : Command , Singleton<JumpCommand>
{
void Excute()
{
//执行跳跃(执行的函数中包含对接收者的操作)
}
}
public class FireCommand : Command , Singleton<FireCommand>
{
void Excute()
{
//执行操作(执行的函数中包含对接收者的操作)
}
}
在用户类中引用指令类
public class User : MonoBehaviour
{
GameObject Player =new GameObject(); //实例化接收者类
public void Jump()
{
if(Input.GetKeyDown(KeyCode.R))
{
JumpCommand.instance.Excute();
}
}
public void Fire()
{
if(Input.GetKeyDown(KeyCode.F))
{
FireCommand.instance.Excute();
}
}
}
最后在游戏循环中检测玩家操作
public void Start()
{
User user1 = new User();
}
public void UpData()
{
user1.Jump();
user1.Fire();
}
通过这种方式,我们就可以更加灵活地更改玩家操作的内容和操作的对象 并且我们也可以使用AI代码对一些对象进行自动操作
3.指令撤销与重做
当玩家进行一个更改操作之后 需要回到更改之前的状况 如果我们每帧都记载一次游戏的状况 然后当玩家按下返回按键时回到上一次记载的状况时 会导致游戏中出现大量的内存占用 但当我们在指令类中记录玩家的每次操作 当玩家按下返回按键时 只需要返回上一次操作即可 就可以大大降低内存占用并且达到返回指令的效果
- 首先我们在指令类中加入返回操作
public Interface Command
{
public void Excute(){}
public void UnExcute(){}
}
- 在控制类中完成返回操作
public class JumpCommand : Command
{
void Excute()
{
//执行跳跃(执行的函数中包含对接收者的操作)
}
void UnExcute()
{
//返回操作(返回操作中包含玩家执行操作前的数据)
}
}
public class FireCommand : Command
{
void Excute()
{
//执行操作(执行的函数中包含对接收者的操作)
}
void UnExcute()
{
//返回操作(返回操作中包含玩家执行操作前的数据)
}
}
- 在用户类中进行返回操作
public class User : MonoBehaviour
{
GameObject Player =new GameObject(); //实例化接收者类
int jumpCurrent = 0; //记录操作的次数
int FireCurrent = 0; //记录操作的次数
List<JumpCommand> jumpList = new List<JumpCommand>();
//定义对应指令的列表 来储存当前指令的次数和本次指令中玩家的状态
List<FireCommand> fireList = new List<FireCommand>();
//定义对应指令的列表 来储存当前指令的次数和本次指令中玩家的状态
public void Jump()
{
if(Input.GetKeyDown(KeyCode.R))
{
jumpCurrent++;
JumpCommand newJump = jumpList[jumpCurrent];
newJump.Excute();
}
if(Input.GetKeyDown(KeyCode.Ctrl) && Input.GetKeyDown(KeyCode.R))
{
jumpCurrent--;
jumpCommand reJump = jumpList[jumpCurrent];
reJump.UnExcute();
}
}
public void Fire()
{
if(Input.GetKeyDown(KeyCode.F))
{
fireCurrent++;
FireCommand newFire = fireList[fireCurrent];
newFire.Excute();
}
if(Input.GetKeyDown(KeyCode.Ctrl) && Input.GetKeyDown(KeyCode.F))
{
fireCurrent--;
fireCommand reFire = fireList[fireCurrent];
reFire.UnExcute();
}
}
}
最后在游戏循环中检测玩家操作
void Start()
{
User user1 = new User();
}
void UpData()
{
user1.Jump();
user1.Fire();
}
标签:void,玩家,unity,指令,自用,操作,KeyCode,public
From: https://www.cnblogs.com/ShineLightYiyi/p/17872485.html