写在前面
之前开了个坑,现在来填了。操作判断是个大问题,今天就来总结Unity里面常用的操作检测。根据我们开发的应用类型,可分为电脑和手机应用,因此在不同的平台上操作方式可以分为两大类:
- 电脑端
- 键盘按键控制
- 鼠标点击控制
- 手机端
- 触屏控制
- 手势控制
- 重力控制
- 陀螺仪控制
本文的限制:1 Unity也支持需要用到手柄或VR头盔的应用平台,但在这些平台上也只不过是对上述操作控制进行变种设计而已,这里就不展开说了。2 既然涉及到检测,就一定有对应的移动和转向等命令,命令的实现有很多种方法。如果讲到相关例子,并不代表最佳用法。
正文
绝大多数的输入判断,都需要用到Input类,而Keycode类则用来表示键盘上的按键
Unity - Scripting API: Inputdocs.unity3d.com1 按键输入
与按键相关的方法有两个,一是GetKey(),另一个是GetAxis()
GetKey()例子:
If (Input.GetKey(KeyCode.A))
{
Debug.Log("A pressed");
}
GetKey()方法检测的是这个按键是否被一直按住,GetKeyDown()检测按键被按下,GetKeyU()检测按键抬起。举个例子,一个推箱子游戏,每次按下一次按键才会向前推进,那么你就可以使用GetKeyDown。但是像一些即时战略的游戏则需要用到GetKey,玩家按住按键,自己的角色就会一直往前跑。
GetAxis()例子:
float v = verticalSpeed * Input.GetAxis("Horizontal");
float h = horizontalSpeed * Input.GetAxis("Vertical");
transform.Rotate(v, h, 0);
你可以去Project Settings -> Input中自定义自己的按键,比如你可以把空格键叫作Fire,使用Input.GetButton("Fire")检测Space按键。
2 鼠标点击输入
检测哪个鼠标按键被按下,可以使用Input.GetMouseButtonDown()方法,当传入值为0时,检测鼠标左键。当传入值为1时,检测鼠标右键。当传入值为2时,检测鼠标中键。
If (nput.GetMouseButtonDown(0))
{
Debug.Log("Primary Mouse Button Pressed");
}
当然你的手有没有按下去,这个好说,但是游戏里面,游戏界面上的鼠标到底有否按到东西呢?或者其他可以用鼠标实现的想法,例如枪有否打中人呢?这些需要使用到光线投射(Raycast)的物理概念来解释。在物理层面,如果我们给定一个光源和一个方向,那么光线就会一直向前跑(假设它在真空中),最后到达一个妨碍它继续前进的物体表面。
在Unity中,这个物体表面表现为一个带有碰撞体(Collider)信息的物体。如果发出的射线有穿过任意一个碰撞体,则回传碰撞体的资讯,其中包括该物件的名称、世界坐标等。如下图
要取得鼠标点击的位置,可以用Input.position。我们的Main Camera可以作为起点来创建一条Ray(射线),把摄像机到点击位置的的向量,当作射线方向。根据这条射线,参考上图,判断是否碰到碰撞体。当然,Input类返回的点击位置不能直接使用,需用Camera.main.ScreenPointToRay()方法将其转成可用参数
Camera.main其实就等同于GameObject.FindGameObjectWithTag("Main Camera").GetComponent<Camera>(); 这一句。很长对伐!你每次用Camera.main都会调用这么长一串东西哟!
Camera cam = Camera.main;
Ray ray = cam.ScreenPointToRay(Input.position); // 这是起点产生的Ray
RaycastHit hit; // 这是用来检测碰撞的Ray,如果有则存入hit内
if (Physics.Raycast(ray, out hit))
{
Debug.Log(hit.transform.name); // 输出点击物体名称
}
Raycast小技巧:
Raycast还可以传入Layermask来过滤一些你不感兴趣的碰撞事件,
Layermask layermask;
if (Physics.Raycast(ray, out hit,layermask))
{
Debug.Log(hit.transform.name); // 输出点击物体名称
}
没带有你所设定Layer的物件都会被这条Raycast无视,是不是非常惨。
电脑端完,热身完了,接下来会继续填坑的 ...