目录html
任何游戏都应该提供给用户交互的方式,能够想象一个没有任何交互的游戏是什么样的。若是没有输入系统带来的,用户与游戏的交互那么游戏将再也不是游戏,由于玩家将不能进行任何操做,那还怎么玩呢?Unity做为一个号称跨平台性能最好的游戏引擎,那么它给咱们提供了哪些输入呢?为了可以更好的整理Unity的输入系统,暂时将其分为移动平台的输入和传统的输入。ide
在手机和pad上主要的输入方式就是:触摸,重力加速器,虚拟键盘等。Unity将这些操做都封装到了UnityEngine.Input和UnityEngine.TouchScreenKeyboard这两个类里。函数
在UnityEngine.Input类中为咱们提供了触摸相关的函数,以及在UnityEngine命名空间中涉及到的类,相关函数和类以下表:性能
函数表:
|函数名 |做用
----|-----
multiTouchEnabled| 是否启用多点触摸
simulateMouseWithTouches| 启用/禁用使用触碰仿真鼠标的操做
touchCount| 在此帧中的触摸数量
touches|在上一帧中的触摸点(Touch)信息
touchSupported| 标示当前运行此程序的设备是否支持触摸
GetTouch|根据触摸点的索引获取触摸点的信息
类表:
类名 |做用
---|--
Touch| 触摸点信息
TouchPhase| 触摸点的状态信息测试
此示例主要实现以下三个功能:this
示例代码,以下:3d
public class TouchInputTest : MonoBehaviour { public Camera m_mainCamera = null; private bool m_isRatating = false; private GameObject m_objRatation = null; private float m_nSpeedRatation = 30.0f; private float m_nTotalAngle = 0; private const int nMaxSelectedSize = 5; private string[] m_strSelectedGameObject = new string [nMaxSelectedSize]{"", "", "", "", ""}; // Use this for initialization void Start () { } // Update is called once per frame void Update () { //将是否支持触碰 if (Input.touchSupported) { print("Number of touches:" + Input.touchCount); print("Length of touches:" + Input.touches.Length); print("---------------------------------------------"); for (int i = 0; i < Input.touches.Length; ++i ) { Touch tch = Input.touches[i]; //打印触摸点的信息 print("Index:" + tch.fingerId); print("State:" + tch.phase.ToString()); print("Positon:" + tch.position); print("TapCount:" + tch.tapCount); print("deltaPosition:" + tch.deltaPosition); print("deltaTime:" + tch.deltaTime); //经过射线拾取物体 if (m_mainCamera != null) { Ray ray = m_mainCamera.ScreenPointToRay(tch.position); RaycastHit rayHitInfo; Physics.Raycast(ray, out rayHitInfo); if (rayHitInfo.transform) { if (0 == i) m_objRatation = rayHitInfo.transform.gameObject; m_strSelectedGameObject[i] = rayHitInfo.transform.name; } else { m_strSelectedGameObject[i] = ""; } } else { print("Main camera is null."); } } for (int i = Input.touches.Length; i < nMaxSelectedSize; ++i) { m_strSelectedGameObject[i] = ""; } //检测是否支持使用触摸仿真鼠标操做。1个手指操做为左键,2个手指操做表明右键,3:个手指表明中键 //这你经过两个手指单机,来模仿鼠标右键单击,单两个手指单击时,选中的物体沿Y轴旋转360度。 if (Input.simulateMouseWithTouches) { if (Input.GetMouseButton(1) && !m_isRatating) { m_isRatating = true; } } } else { print("touch is not supported."); return; } if (m_isRatating) { float yRotation = m_nSpeedRatation * Time.deltaTime; if (m_nTotalAngle >= 360) { m_isRatating = false; m_nTotalAngle = 0; } m_nTotalAngle += yRotation; m_objRatation.transform.Rotate(0, yRotation, 0); } } void OnGUI() { if (GUILayout.RepeatButton("Enable/Disable MulitTouch(" + Input.multiTouchEnabled.ToString() + ")")) { Input.multiTouchEnabled = !Input.multiTouchEnabled; } if (GUILayout.RepeatButton("Enable/Disable simulateMouseWithTouches(" + Input.simulateMouseWithTouches.ToString() + ")")) { Input.simulateMouseWithTouches = !Input.simulateMouseWithTouches; } for (int i = 0; i < nMaxSelectedSize; ++i) { GUILayout.Label("Index(" + i + "):" + m_strSelectedGameObject[i].ToString()); } } }
当咱们垂直正对手机(手机屏幕对着咱们的脸)的时候,重力什么怎么样呢?它有哪些方向,以及在每一个方向上的加速度是多少呢?
如今的手机或者pad通常都能对三个方向的力进行采集,分别是X,Y和Z。X的正方向水平向左,Y的正方向垂直向上,Z的正方向面向本身。为了能更形象的说明这些问题,我简单的画了一个图,下图为咱们垂直正对手机时候的重力加速图:
上图中的两个圆都表示的是两个3D球体的前视图。由上图看,当咱们垂直正对手机时候,中间的蓝色球体受到了来自地球-9.8米/秒的二次方加速度,那么这时候咱们访问Input.acceleration.y的时候,其值就是一个接近-9.8的值,其余轴上都趋近于0。code
重力加速器的信息被放在了UnityEngine.Input中。具体函数或字段见下表:orm
函数名 | 做用 |
---|---|
acceleration | 存放当前3个轴上感应到的加速度 |
accelerationEvents | 在上一帧期间Unity引擎采集到的全部重力加速器信息(每一个方向上的加速度和时间增量) |
accelerationEventCount | 在上一帧期间Unity引擎采集到的全部重力加速度的次数 |
本示例就一个功能,咱们在场景中放一个Cube,当手机向指定方向偏转时,Cube就向指定方向移动。示例代码以下:htm
public class AccInputTest : MonoBehaviour { private float speed = 1.5f; //控制信息的打印时间 private float fInterval = 1000; private float fCurTime = 0; // Use this for initialization void Start () { } // Update is called once per frame void Update () { Vector3 dir = Vector3.zero; //unity的X轴的正方向是向左的 dir.x = -Input.acceleration.x; dir.y = Input.acceleration.y; dir.z = 0; if (fCurTime >= fInterval) { Debug.Log("X:" + Input.acceleration.x + " Y:" + Input.acceleration.y + " Z:" + Input.acceleration.z); fCurTime = 0; } dir *= Time.deltaTime; fCurTime += Time.deltaTime; transform.Translate (dir * speed); } }
在游戏中咱们点击输入框(NGUI或Unity自带控件)都会自动弹出虚拟键盘,固然咱们也能够手动的弹出虚拟键盘,下面主要介绍如何手动的弹出键盘。键盘的操做被Unity放在了UnityEngine.TouchScreenKeyboard中。键盘的操做很是简单,下面以一个简单的示例来讲明如何打开一个虚拟键盘,以及获取输入的数据。在一个脚本里的OnGUI函数中输入以下代码:
void OnGUI() { TouchScreenKeyboard.hideInput = true; if (GUILayout.Button ("KeyBoard:ASCIICapable")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.ASCIICapable, false, false, false, false); } if (GUILayout.Button ("KeyBoard:Default")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.Default, false, false, false, false); } if (GUILayout.Button ("KeyBoard:EmailAddress")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.EmailAddress, false, false, false, false); } if (GUILayout.Button ("KeyBoard:NamePhonePad")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NamePhonePad, false, false, false, false); } if (GUILayout.Button ("KeyBoard:NumberPad")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NumberPad, false, false, false, false); } if (GUILayout.Button ("KeyBoard:NumbersAndPunctuation")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NumbersAndPunctuation, false, false, false, false); } if (GUILayout.Button ("KeyBoard:PhonePad")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.PhonePad, false, false, false, false); } if (GUILayout.Button ("KeyBoard:URL")) { keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.URL, false, false, false, false); } GUILayout.Label(""); if (keyboard != null) { GUILayout.Label (keyboard.text); } else { GUILayout.Label ("keyboard is null."); } }
Ps:在移动平台的输入中,Unity还为咱们提供了诸如:位置,指南针,陀螺仪等设备的信息输入。在这里就不在详述了,详情参见官方文档
像鼠标,键盘,操做杆和手柄这样的输入设备。如今暂且将其定义为传统的输入设备,以便区分前面的移动平台的输入。在Unity中还为咱们抽象出来一个叫作虚拟轴或虚拟按钮的概念出来,在下面将分别介绍这两种(实际上是一种,后者是由前者虚拟出来的)输入方式。
因为操做杆和手柄没有设备,就不作介绍了,它跟其余的操做是同样的。
键盘
函数 |做用
---|----
GetKey|获取键盘指定键是否按下(只要按下就是True抬起就是False)
GetKeyDown|获取键盘指定键是否按下(按下那一刻是True)
GetKeyUp|获取键盘指定键是否按下(弹起那一刻是True)
anyKey|是否按住了“任意键”(只要按下就是True抬起就是False)
anyKeyDown|是按下了“任意键”(按下那一刻是True)
对应的按键枚举参见KeyCode
鼠标
函数| 做用
---|---
GetMouseButton| 获取鼠标指定键是否按下(只要按下就是True抬起就是False)
GetMouseButtonDown|获取鼠标指定键是否按下(按下那一刻是True)
GetMouseButtonUp|获取鼠标指定键是否弹起(弹起那一刻是True)
注:0对应于鼠标左键,1对应于与鼠标右键,2对应于鼠标中键。
虽然上面的函数可以直接获取到指定键是否按下,可是咱们通常不会直接这么使用。使用Untiy提供的虚拟轴和按键能更灵活的控制咱们的输入。好比我能够将空格定义攻击键,也能够随时改变这个键。虚拟轴还有一个好处,就是咱们能够同时接受多输入,好比我能够接受键盘的空格做为攻击,也可使用操做杆或手柄上的一个键做为攻击键,由于咱们获取的虚拟轴或按钮都是同样(“Fire1”)的。这里可能说的有点抽象,很差懂,下面我会经过一个例子来讲明这些。
下面对每一个参数简单的说明,在看说明时对应下图一块儿看。图以下:
参数名 | 做用 |
---|---|
Name | 虚拟轴的名字(获取虚拟轴时就须要传入这个名字) |
Descriptive Name | 正方向上的控制键的描述信息 |
Descriptive Negative Name | 反方向上的控制键的描述信息 |
Negative Button | 主控制键反方向上对应的控制键 |
Positive Button | 主控制键正方向上对应的控制键 |
Alt Negative Button | 副控制键反方向上对应的控制键 |
Alt Positive Button | 副控制键正方向上对应的控制键 |
Gravity | 向中间值归位时的速度 |
Dead | 中间值的阈值,就是小于这个值则被定义为是中间值了 |
Sensitivity | 向目标归位时的速度 |
Snap | 是否须要平滑,若是没有的话那么就只有-1,0(中间值),1这三个值 |
Invert | 将上面的正反方向颠倒 |
Type | 使用那些输入控制键,通常使用鼠标和键盘,若是你开发的是使用操做杆的那么就是操做杆做为输入控制 |
Axis | 抱歉不能理解 |
Joy Num | 抱歉不能理解 |
相关函数
函数名|做用
----|---
GetAxis|获取指定轴上当前采集的值,范围为[-1,1]
GetAxixRaw|获取指定轴上当前采集的值,这个函数获取的是没有平滑过渡的值,也就是只有-1,0,1这三个值
GetButton|获取指定虚拟按钮是否按下,当按下的是否为True,谈起的是否为:False
GetButtonDown|获取指定虚拟按钮是否按下,当按下那一刻为True
GetButtonUp|获取指定虚拟按钮是否抬起,当抬起那一刻为True
此示例主要实现2功能:
public class AxesTest : MonoBehaviour { private float m_nSpeed = 5.0f; private bool m_isRotating = false; private float m_nRotationSpeed = 30.0f; private float m_nCurRotationAngle = 0; private const float m_nMaxAngle = 360; // Update is called once per frame void Update () { if (Input.GetButtonDown("Rotation") && !m_isRotating) { m_isRotating = true; } if (m_isRotating) { float nRotation = Time.deltaTime * m_nRotationSpeed; transform.Rotate(0, nRotation, 0); m_nCurRotationAngle += nRotation; } if (m_nCurRotationAngle >= m_nMaxAngle) { m_nCurRotationAngle = 0; m_isRotating = false; } float nXDeltaDistance = Input.GetAxis("Horizontal") * m_nSpeed * Time.deltaTime; float nYDeltaDistance = Input.GetAxis("Vertical") * m_nSpeed * Time.deltaTime; if (nXDeltaDistance.Equals(0) && nYDeltaDistance.Equals(0)) return; print("X:" + Input.GetAxis("Horizontal").ToString() + " Y:" + Input.GetAxis("Vertical").ToString()); transform.Translate(-nXDeltaDistance, nYDeltaDistance, 0); } }
Unity将其主要的输入都放到了UnityEngine.Input类中,内部检查或采集到输入信息就将其结果放入Input中的对应字段,用于表示输入的状态。输入大体分为两类,一个是移动平台的输入,像触摸,虚拟键盘,重力加速感应器,罗盘,陀螺仪,GPS(位置)等,另外一类是传统的输入,像键盘,鼠标,操做杆和手柄等。
参考文献
Unity官方文档1:http://docs.unity3d.com/Manual/Input.html
Unity官方文档2:http://docs.unity3d.com/ScriptReference/Input.html