任何游戏都应该提供给用户交互的方式,可以想象一个没有任何交互的游戏是什么样的。如果没有输入系统带来的,用户与游戏的交互那么游戏将不再是游戏,因为玩家将不能进行任何操作,那还怎么玩呢?Unity作为一个号称跨平台性能最好的游戏引擎,那么它给我们提供了哪些输入呢?为了能够更好的整理Unity的输入系统,暂时将其分为移动平台的输入和传统的输入。

移动平台的输入

在手机和pad上主要的输入方式就是:触摸,重力加速器,虚拟键盘等。Unity将这些操作都封装到了UnityEngine.Input和UnityEngine.TouchScreenKeyboard这两个类里。

触摸

触摸相关的函数

在UnityEngine.Input类中为我们提供了触摸相关的函数,以及在UnityEngine命名空间中涉及到的类,相关函数和类如下表:

函数表:

函数名 作用
multiTouchEnabled 是否启用多点触摸
simulateMouseWithTouches 启用/禁用使用触碰仿真鼠标的操作
touchCount 在此帧中的触摸数量
touches 在上一帧中的触摸点(Touch)信息
touchSupported 标示当前运行此程序的设备是否支持触摸
GetTouch 根据触摸点的索引获取触摸点的信息

类表:

类名 作用
Touch 触摸点信息
TouchPhase 触摸点的状态信息

触摸的一个示例

此示例主要实现如下三个功能:

  1. 显示触摸点的属性信息
  2. 显示点击到的物体
  3. 测试仿真鼠标

示例代码,如下:

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功能:

  1. 实现一个Cube在场景中前后左右的走动,通过获取“Horizontal”和“Vertical”两个虚拟轴来控制
  2. 实现一个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中的输入的更多相关文章

  1. Unity的Input输入

    Unity中的输入管理器由Input类进行操控.官方文档地址:https://docs.unity3d.com/ScriptReference/Input.html 中文翻译的话可以在这里:http: ...

  2. 【unity shaders】:Unity中的Shader及其基本框架

    shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...

  3. 解读Unity中的CG编写Shader系列八(镜面反射)

    转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...

  4. 【转】Unity中的协同程序-使用Promise进行封装(三)

    原文:http://gad.qq.com/program/translateview/7170967 译者:崔国军(飞扬971)    审校:王磊(未来的未来) 在这个系列的最后一部分文章,我们要通过 ...

  5. Unity教程之再谈Unity中的优化技术

    这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体   这一步主要是为了针对性能瓶颈中的”顶点 ...

  6. 【Unity技巧】Unity中的优化技术

    http://blog.csdn.net/candycat1992/article/details/42127811 写在前面 这一篇是在Digital Tutors的一个系列教程的基础上总结扩展而得 ...

  7. 在Unity中高效工作(上)

    原地址:http://www.unity蛮牛.com/thread-19974-1-1.html 编的话:感谢做编程的IT朋友,帮我翻译文章,我又稍稍做了些修改.给点儿掌声哩.欢迎大家多多评论呦. 我 ...

  8. 【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则

    作者:Williammao, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/290.h ...

  9. 使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体

    今天在接入android支付宝 SDK时,打包运行时,发现使用Unity NGUI-InputField组件输入时发现显示为白色就是看不到字体,查找一下发现是与android交互存在的问题, 只需在A ...

随机推荐

  1. Google浏览器插件

    Scholarscope XPath Helper Web Scraper JSON-handle  User-Agent Swicher  Markdown Here

  2. 8、泛型程序设计与c++标准模板库4.标准c++库中的算法

    标准c++算法是通过迭代器和模板来实现的,其实算法本身就是一种函数模板. 算法从迭代器那里获得一个元素,而迭代器则知道一个元素在容器中的什么位置.迭代器查找元素的位置并将这些信息提供给算法以便算法能够 ...

  3. 6.5 Ubuntu中安装搜狗输入法

    传统的方式:http://www.cnblogs.com/zlslch/p/6943318.html 最简单的方式:

  4. sublime插件-OmniMarkupPreviewer浏览器打开报404解决办法

    Sublime Text > Preferences > Package Settings > OmniMarkupPreviewer > Settings - Default ...

  5. 理解setTimeout和setInterval

    setTimeout和setInterval,这两个js函数都是用来定时执行.setTimeout执行一次,setInterval执行多次. 问题出现在今天,使用setInterval是,设置执行速度 ...

  6. js常用util

    /** 日期格式化 */Date.prototype.Format = function(format) { var o = {  "M+" : this.getMonth() + ...

  7. 如何修改html中列表项li所显示的圆点的颜色?,以及相关样式的设定

    这是li标签自带的圆点的颜色改变,代码如下: .centerbt li{ content:"."; color:gray; } 在标签li后面加入“@”符号,这里都会使用posit ...

  8. Jmeter用BeanShell Sampler调用java写的jar包进行MD5加密

    [前言] 在工作中,有时候我们请求的参数可能需要加密,比如登录接口中的密码做了加密操作,今天我就给大家介绍一种方法:Jmeter用BeanShell Sampler调用java写的jar包进行MD5加 ...

  9. HTML基本标签问题总结

    一.常见的内联元素和块元素 块级元素: div, form, (列表相关ul,dl,ol,li,) h1-6,p,table 内联元素: a, br, u,(b , em, strong, i,) i ...

  10. PAT天梯赛L3-004 肿瘤诊断

    题目链接:点击打开链接 在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环.给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积. 输入格式: 输入第一行给出4个正整数:M.N.L.T,其中M和N是每 ...