第一人称射击游戏实战——按键输入封装
知识储备
1.KeyCode是键盘事件的原始键代码,可以直接映射到键盘上的物理键,可以使用Input.GetKeyUp和Input.GetKeyDown来检测按键按下事件和上抬事件。
Input.GetKey(KeyCode key):bool
Returns true while the user holds down the key identified by the key KeyCode enum parameter.
Input.GetKeyUp( KeyCode key):bool
Returns true during the frame the user releases the key identified by the key KeyCode enum parameter.
Input.GetKeyDown( KeyCode key):bool
Returns true during the frame the user starts pressing down the key identified by the key KeyCode enum parameter.
GetKey和GetKeyDown的主要区别在于,GetKey会一直返回true,但是GetKeyDown是在按下的那一帧返回true,之后不返回。
2.获取轴
Input.GetAxis(axisName:string):float
根据坐标轴名称返回虚拟坐标系的值
Input.GetAxisRaw(axisName:string):float
根据坐标轴名称返回一个不使用平滑滤波器的虚拟坐标值(-1,0,1)
注意不论是否使用平滑滤波器,返回值都是float,不能是int,另外要注意与Input.GetKey系列的bool类型返回值区分开
3.Hashtable可以来储存自定义轴与已有按键,以键值对的形式存储下来。关于Hashtable的操作回顾一下:
Hashtable.count
Returns how many elements are in the hashtable.
Hashtable.Add(object, object)
Adds an element with the specified key and value into the Hashtable.
Hashtable.Contains(object)
Determines whether the Hashtable contains a specific key.This method is an O(1) operation.
该方法与Hashtable.ContainsKey(object)作用是一样的,不过其源码是
public virtual bool Contains(object key)
{
return this.ContainsKey(key);
}
因此用Hashtable.ContainsKey(object)会快一些。
4.List的一些操作
Add(T);
Contains(T);
知识点
用户输入脚本可以分为三种:1.按键:包括了鼠标和键盘
2.自定义轴:一般包括正向和负向两个键值;3.Unity为我们提供的轴
轴在Edit->Project Settings->Input->Axis中可以查找和添加
那么按键输入封装主要从这三方面考虑,用三个集合来存储。
可以考虑用Hashtable的键值对的形式存储自定义轴和按键,而Unity为我们提供的轴只需要存储名字即可,因此用List存储。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class fps_Input:MonoBehaviour
{
public Dictionary<string,KeyCode> buttons=new Dictionary<string,KeyCode>();//存储技能名和对应按键
public Dictionary<string,fps_InputAxis> axis=new Dictionary<string,fps_InputAxis>();//存储控制行走的自定义轴
public List<string> unityAxis = new List<string>();
public class fps_InputAxis
{
public KeyCode positive;
public KeyCode
}//辅助类,用来帮助我们定义自定义轴中的正向和负向两个键值
private void AddButton(string n,KeyCode k)
{
if(buttons.ContainsKey(n))
button[n]=k;
else
button.Add(n,k);
}
private void AddAxis(string n,KeyCode pk,KeyCode nk)
{
if(axis.ContainsKey(n))
axis[n]= new fps_InputAxis(positive=pk,negative=nk);
else
axis.Add(n,new fps_InputAxis(positive=pk,negative=nk));
}
private void AddUnityAxis(string n)
{
if(!unityAxis.Contains(n))
unityAxis.Add(n);
}
private void SetupDefaults(string type="")
{
if(type==""||type=="buttons")
{
if(buttons.Count==0)
{
AddButton("Fire",KeyCode.Mouse0);//开火是鼠标左键
AddButton("Reload",KeyCode.R);//装弹药是R
AddButton("Jump",KeyCode.Space);//跳跃是空格
AddButton("Crouch",KeyCode.C);//蹲伏是C
AddButton("Sprint",KeyCode.LeftShift);//冲刺是左边Shift
}
}
if(type==""||type=="Axis")
{
AddAxis("Horizontal",KeyCode.W,KeyCode.S);
AddAxis("Vertical",KeyCode.A,KeyCode.D);
}
if(type==""||type=="Unity")
{
AddUnityAxis("Mouse X");//对应鼠标X方向上的移动
AddUnityAxis("Mouse Y");//对应鼠标Y方向上的移动
AddUnityAxis("Horizontal");//对应键盘上←→
AddUnityAxis("Vertical");//对应键盘上↑↓
}
}//按键初始化程序
void Start()
{
SetupDefaults();//
}
//注意,以上是用到的子函数的封装,因此用的是private,但是一些需要与外界交换信息的,例如有Input.GetKey,为了外界可以调用按钮事件,并返回参数做反馈,是否成功调用按钮事件。
public bool GetButton(string button)
{
if(buttons.ContainsKey(buttons[button]))
return Input.GetKey(buttons[button]);
else
return false;
}//根据按键名查找Hashtable中是否有该功能,然后检测是否处于按下状态。
public bool GetButtonDown(string button)
{
if(buttons.ContainsKey(buttons[button]))
return Input.GetKeyDown(buttons[button]);
else
return false;
}
public float GetAxis(string axis)//鼠标的移动坐标
{
if(this.unityAxis.Contains(axis))
return Input.GetAxis(axis);
else
return 0;
}
public float GetAxisRaw(string axis)//控制WSAD和←→↑↓方向键的检测
{
if(this.axis.ContainsKey(axis))
{
if(Input.GetKey(this.axis[axis].positive))
return 1;
if(Input.GetKey(this.axis[axis].negative))
return -1;
return 0;
}
else if(unityAxis.Contains(axis))
{
return Input.GetAxisRaw(axis);
}
else
return 0;
}
}