最近开始看《游戏设计模式》,理解之余,写点东西练练手。
命令模式核心思想:把一个命令看做一个对象。这样做就能让命令拥有所有对象所拥有的优势。
大概意思就是把命令具体化,实例化。这样就可以轻易实现很多的骚操作。比如:
按键自定义(这个就是本文内容)
回合制撤销或回退操作(把命令弄成一个队列,想怎么退怎么退)
宏指令(游戏里面有用这玩意吗?自动战斗组合技?)
新手引导操作(新手引导时响应就是在一个位置点点点,结束之后就改变为具体位置)
简单AI和噩梦AI(命令(技能)是一样的,但是高级AI的内部逻辑会更强大)
还有更多体现。详细解释就不赘述了,网上有很多资料
首先需要一个命令基类,所有命令都会继承这个基类,而命令的执行就是execute函数。
public abstract class Commend
{
public abstract void execute();
}
移动命令
public class MoveCommend : Commend
{
Unit unit;
public override void execute()
{
unit.move();
}
}
Unit就是拥有移动move()函数的角色,使用是需要unit赋值。
跳跃命令
public class JumpCommend : Commend
{
Unit unit;
public override void execute()
{
unit.jump();
}
}
同上
按钮响应
public class InputHandel : MonoBehaviour
{
Commend j;//J键
Commend k;//K键
private void Start()
{
j = new MoveCommend();//强制绑定移动命令
k = new JumpCommend();//强制绑定跳跃命令
}
private void Update()
{
inputListen();//每帧监听
}
void inputListen()
{
//如果按下J键就执行J键对应命令
if(Input.GetKey(KeyCode.J))
{
j.execute();
}
else if(Input.GetKey(KeyCode.K))
{
k.execute();
}
}
}
最后是Unit角色函数,拥有移动和跳跃命令,需要将这个函数绑定在角色物体上
public class Unit : MonoBehaviour
{
//移动动作
public void move()
{
gameObject.transform.position = gameObject.transform.position + new Vector3(1, 0, 0);
}
//跳跃动作
public void jump()
{
gameObject.transform.position = gameObject.transform.position + new Vector3(0, 1, 0);
}
}
以上就是全部命令模式的内容了(估计会被打死)
我们来加一点点细节
首先给基类函数execute加个传入参数GameObject go
public abstract class Commend
{
public abstract void execute(GameObject go);
}
对应的移动命令变成这样
//移动命令
public class MoveCommend : Commend
{
Unit unit;
public override void execute(GameObject go)
{
unit = go.GetComponent<Unit>();
unit.move();
}
}
之后在按钮响应InputHandel里面加个
//接受命令的物体
public GameObject go;
然后在Unit里面加个
//使被点击的物体接受命令
private void OnMouseDown()
{
GetComponentInParent<InputHandel>().go = gameObject;
}
恭喜你,你可以切换接受命令的物体了,只需要在两个物体上分别加上Unit组件,点击一下就对应物体,就会变成对应物体接受命令。当然这样的坏处就是两个物体必须是具有相同命令的。
点击小球,按下j键,小球会移动。再点击长方体,按下j键,就会变成长方体移动。
接下来的工作就是自定义按键。
Unit函数基本没变
因为键盘不可能全部用完,所以需要加一个空命令
public class NullCommend : Commend
{
public override void execute(GameObject go)
{
}
}
里面什么也不用写,当这个按键没有作用时,就把这个命令赋给它。
键盘响应函数
public class InputHandel : MonoBehaviour
{
//26键对应命令数组
public Commend[] keys = new Commend[26];
//接受命令的物体
public GameObject go;
//改变按钮绑定时关闭按钮响应
public bool changeTime;
private void Start()
{
//26键初始化
for(int i=0; i<26; i++)
{
keys[i] = new NullCommend();
}
keys[9] = new MoveCommend(); //j
keys[10] = new JumpCommend();//k
changeTime = true;
}
private void Update()
{
inputListen();
}
//按钮响应
void inputListen()
{
if (changeTime)
{
for (int i = 0; i < 26; i++)
{
//ASCII码转换成键盘对应按键
int x = 97 + i;
char y = (char)x;
string s = y.ToString();
if (Input.GetKey(s))
{
//调用对应按键命令
keys[i].execute(go);
}
}
}
}
}
1、需要一个changeTime来确定是否响应,因为输入字母的时候也算按钮响应。
2、start初始化是将j,k默认设置,其他按键就设置为空命令
3、update每帧监听
4、input里面需要将ASCII转化为键盘对应按键。一帧会循环26次,当按下了其中一个按钮时,就会执行对应的命令。
有人会问,在哪切换绑定呢?别急,新建一个UI输入需要的按键
点击改变按钮时,之前设置的changeTime就有用武之地了,将它毫不留情的设置为false。暂停按钮监听,然后在两个文本框里输入需要的按键。最后点击确定,大功告成。
UI函数
public class UI : MonoBehaviour
{
public GameObject move;
public GameObject jump;
public InputHandel inputHandel;
char[] moveButton;
char[] jumpButton;
//从文本框读取字母,并添加功能
public void change()
{
moveButton = move.GetComponent<InputField>().text.ToCharArray();
jumpButton = jump.GetComponent<InputField>().text.ToCharArray();
int i = (int)moveButton[0];
int j = (int)jumpButton[0];
if (i>=65 && i<=90)
{
i -= 65;
}
else
{
i -= 97;
}
if(j>=65 && j<=90)
{
j -= 65;
}
else
{
j -= 97;
}
//Debug.Log("i:" + i + "j:" + j);
//将命令赋予对应的keys[i]
for(int x=0; x<26; x++)
{
if(x == i)
{
inputHandel.keys[i] = new MoveCommend();
}
else if(x == j)
{
inputHandel.keys[j] = new JumpCommend();
}
else
{
inputHandel.keys[x] = new NullCommend();
}
}
inputHandel.changeTime = true;
}
//暂定按钮响应
public void startChange()
{
inputHandel.changeTime = false;
}
}
1、 Char存储对应的字母,因为ASCII限制所以只能绑定A-Z 26个按键,当然是大小写都能势识别的
2、 赋予命令的时候注意需要将有用的赋予功能,没有用的按键需要设置为空命令,否则会功能冲突,因为一开始已经全部都设置过空,所以不会报空错误。
以上就是基于命令模式的unity角色切换及按键绑定的全部内容了,第一次写这种技术向文章,不足之处还请见谅。
最后推荐一波资料出处游戏设计模式。再次感谢您的阅读。