Unity中的输入
任何游戏都应该提供给用户交互的方式,可以想象一个没有任何交互的游戏是什么样的。如果没有输入系统带来的,用户与游戏的交互那么游戏将不再是游戏,因为玩家将不能进行任何操作,那还怎么玩呢?Unity作为一个号称跨平台性能最好的游戏引擎,那么它给我们提供了哪些输入呢?为了能够更好的整理Unity的输入系统,暂时将其分为移动平台的输入和传统的输入。
移动平台的输入
在手机和pad上主要的输入方式就是:触摸,重力加速器,虚拟键盘等。Unity将这些操作都封装到了UnityEngine.Input和UnityEngine.TouchScreenKeyboard这两个类里。
触摸
触摸相关的函数
在UnityEngine.Input类中为我们提供了触摸相关的函数,以及在UnityEngine命名空间中涉及到的类,相关函数和类如下表:
函数表:
| 函数名 | 作用 |
|---|---|
| multiTouchEnabled | 是否启用多点触摸 |
| simulateMouseWithTouches | 启用/禁用使用触碰仿真鼠标的操作 |
| touchCount | 在此帧中的触摸数量 |
| touches | 在上一帧中的触摸点(Touch)信息 |
| touchSupported | 标示当前运行此程序的设备是否支持触摸 |
| GetTouch | 根据触摸点的索引获取触摸点的信息 |
类表:
| 类名 | 作用 |
|---|---|
| Touch | 触摸点信息 |
| TouchPhase | 触摸点的状态信息 |
触摸的一个示例
此示例主要实现如下三个功能:
- 显示触摸点的属性信息
- 显示点击到的物体
- 测试仿真鼠标
示例代码,如下:
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。
在Unity中访问重力加速器的信息
重力加速器的信息被放在了UnityEngine.Input中。具体函数或字段见下表:
| 函数名 | 作用 |
|---|---|
| acceleration | 存放当前3个轴上感应到的加速度 |
| accelerationEvents | 在上一帧期间Unity引擎采集到的所有重力加速器信息(每个方向上的加速度和时间增量) |
| accelerationEventCount | 在上一帧期间Unity引擎采集到的所有重力加速度的次数 |
重力加速器示例
本示例就一个功能,我们在场景中放一个Cube,当手机向指定方向偏转时,Cube就向指定方向移动。示例代码如下:
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”)的。这里可能说的有点抽象,不好懂,下面我会通过一个例子来说明这些。
虚拟控制轴(Virtual Axes)
虚拟轴的编辑
下面对每个参数简单的说明,在看说明时对应下图一起看。图如下:
| 参数名 | 作用 |
|---|---|
| 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功能:
- 实现一个Cube在场景中前后左右的走动,通过获取“Horizontal”和“Vertical”两个虚拟轴来控制
- 实现一个Cube在场景中的旋转,通过自定义的控制轴“Rotation”实现,“Rotation”我们通过鼠标右键和键盘的空格键来控制。
示例代码如下:
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
Unity中的输入的更多相关文章
- Unity的Input输入
Unity中的输入管理器由Input类进行操控.官方文档地址:https://docs.unity3d.com/ScriptReference/Input.html 中文翻译的话可以在这里:http: ...
- 【unity shaders】:Unity中的Shader及其基本框架
shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...
- 解读Unity中的CG编写Shader系列八(镜面反射)
转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...
- 【转】Unity中的协同程序-使用Promise进行封装(三)
原文:http://gad.qq.com/program/translateview/7170967 译者:崔国军(飞扬971) 审校:王磊(未来的未来) 在这个系列的最后一部分文章,我们要通过 ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- 【Unity技巧】Unity中的优化技术
http://blog.csdn.net/candycat1992/article/details/42127811 写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得 ...
- 在Unity中高效工作(上)
原地址:http://www.unity蛮牛.com/thread-19974-1-1.html 编的话:感谢做编程的IT朋友,帮我翻译文章,我又稍稍做了些修改.给点儿掌声哩.欢迎大家多多评论呦. 我 ...
- 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则
作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...
- 使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体
今天在接入android支付宝 SDK时,打包运行时,发现使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体,查找一下发现是与android交互存在的问题, 只需在A ...
随机推荐
- Windows上python + selenium + Firefox浏览器的环境配置
1.python安装 我的电脑是32位的,安装了Python 3.5.4版本其它安装版本 2.python环境变量配置 将”C:\Program Files\Python35",”C:\Pr ...
- Entity Framework Code-First(10.2):Entity Mappings
Entity Mappings using Fluent API: Here, we will learn how to configure an entity using Fluent API. W ...
- Protocol Buffers官方文档(proto3语言指南)
本文是对官方文档的翻译,大部分内容都是引用其他一些作者的优质翻译使文章内容更加通俗易懂(自己是直译,读起来有点绕口难理解,本人英文水平有限),参考的文章链接在文章末尾 这篇指南描述如何使用protoc ...
- 飘逸的python - @staticmethod和@classmethod的作用与区别
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...
- 22. Generate Parentheses (recursion algorithm)
Given n pairs of parentheses, write a function to generate all combinations of well-formed parenthes ...
- CodeForces 104C【树特性】
题意: 判断这副图是否满足根是一个环的缩点,然后其余点都是一个点,满足树特性. 思路: 一开始就像无向图缩点乱搞,然后实在太烦搞不下去.... 一副图是满足结点和边数量相等,且连通,则一定有一个环. ...
- 【转】C# 使用正则表达式去掉字符串中的数字,或者去掉字符串中的非数字
源地址:http://www.cnblogs.com/94cool/p/4332957.html
- Linux查看系统位数
查看linux是多少位的几位方法 方法/步骤 方法一:getconf LONG_BIT 在linux终端输入getconf LONG_BIT命令 如果是32位机器,则结果为32 Linux ...
- Mol Cell Proteomics. |赵赟| 全面地分析个人尿蛋白质组学的变化揭示出不同的性别变化
大家好,本周分享的是发表在Molecular & Cellular Proteomics上的一篇关于人的尿蛋白质组学的文章,题目是Comprehensive analysis of indiv ...
- @Transactional之Spring事务深入理解
Spring支持两种事务方式: 编程式事务:使用的是TransactionTemplate(或者org.springframework.transaction.PlatformTransac ...