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 ...
随机推荐
- swift中的类拓展 extension
以添加颜色为例,new 一个swift文件夹 不是cocoa类 也不需要继承什么. 然后 import UIKit protocol ColorDalegate{ class func mainCol ...
- ProtoBuf练习
环境设置 项目地址 https://github.com/silvermagic/ProtoBufDev.git 操作系统 64位 Fedora 24 安装protobuf $ git clone h ...
- CodeForces 114B 【STL应用】
思路: 原来string类能sort 和 swap....太强了.... 注意:字典序最小输出,因为某个地方写挫了,sort了n发,代码挫. #include <bits/stdc++.h> ...
- python 数组学习
2 NumPy-快速处理数据 标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针.这样为了保存一个简单的[1, ...
- 《OD大数据实战》Spark入门实例
一.环境搭建 1. 编译spark 1.3.0 1)安装apache-maven-3.0.5 2)下载并解压 spark-1.3.0.tgz 3)修改make-distribution.sh VER ...
- 洛谷P1065 作业调度方案
P1065 作业调度方案 题目描述 我们现在要利用m台机器加工n个工件,每个工件都有m道工序,每道工序都在不同的指定的机器上完成.每个工件的每道工序都有指定的加工时间. 每个工件的每个工序称为一个操作 ...
- 2017-10-4 清北刷题冲刺班p.m
P102zhx a [问题描述]你是能看到第一题的 friends 呢.——hja两种操作:1.加入一个数.2.询问有多少个数是?的倍数.[输入格式]第一行一个整数?,代表操作数量.接下来?行,每行两 ...
- 大融合——LCT维护子树信息
题目 [题目描述] 小强要在 $N$ 个孤立的星球上建立起一套通信系统.这套通信系统就是连接 $N$ 个点的一个树.这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树 ...
- Java基础笔记(十五)——封装(续)static关键字
static 静态的,用static修饰的成员叫静态成员或类成员.类实例化的所有对象都会共用同一块静态空间.一个对象将值改变,其它对象的值也就随之改变了. 如:public static int pr ...
- PAT甲级——1096 Consecutive Factors (数学题)
本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/91349859 1096 Consecutive Factors ...