当将Unity游戏运行到IOS或Android设备上时,桌面系统的鼠标左键可以自动变为手机屏幕上的触屏操作,但如多点触屏等操作却是无法利用鼠标操作进行的。Unity的Input类中不仅包含桌面系统的各种输入功能,也包含了针对移动设备触屏操作的各种功能,下面介绍一下Input类在触碰操作上的使用。
首先介绍一下Input.touches结构,这是一个触摸数组,每个记录代表着手指在屏幕上的触碰状态。每个手指触控都是通过Input.touches来描述的:
Touch touch = Input.GetTouch(0); 先获取到touch,再 touch.什么什么
***Touch.fingerId***
触摸的唯一索引,Touch.fingerId不同于“第一”触摸,“第二”触摸等等。它只是每个手势的唯一ID。您无法对fingerId和实际在屏幕上的手指数做任何假设,因为将引入虚拟触摸来处理整个结构中触摸结构恒定的事实(而实际上触摸数显然可能不正确,例如,如果在一个帧内发生多次敲击)
***touch.position***
触摸屏幕的位置,触摸的位置,以像素坐标表示。
***touch.deltatime***
从最后状态到目前状态所经过的时间,即自上次记录的Touch值更改以来经过的时间。各种触摸属性的值会定期更新。deltaTime值只是上一次更新和当前更新之间经过的时间。这主要用于参考deltaPosition确定触摸位置的移动速度
***Touch.tapCount***
从特定位置的手指中检测“双击”等的方式。在某些情况下,两个手指可能会交替轻敲,这可能会错误地记录为单指轻敲并同时移动。
点击数。Andorid设备不对点击计数,这个方法总是返回1
***deltaPosition***
自最后一帧所改变的屏幕位置
***phase*** Input.touches[0].phase
相位,也即屏幕操作状态
**TouchPhase.Began***
手指刚刚触摸屏
***TouchPhase.Moved***
手指在屏幕上移动
***TouchPhase.Stationary***
手指触摸屏幕,但自最后一阵没有移动
***TouchPhase.Ended***
手指离开屏幕
***TouchPhase.Canceled***
系统取消触控跟踪,原因如把设备放在脸上或同时超过5个触摸点
if (Input.touchCount > 0)
touchCount计算触摸的次数
下面通过一段代码来进行移动设备触摸操作的实现:
using UnityEngine;
using System.Collections;
public class AndroidTouch : MonoBehaviour {
private int isforward;//标记摄像机的移动方向
//记录两个手指的旧位置
private Vector2 oposition1=new Vector2();
private Vector2 oposition2=new Vector2();
Vector2 m_screenPos = new Vector2(); //记录手指触碰的位置
//用于判断是否放大
bool isEnlarge(Vector2 oP1, Vector2 oP2, Vector2 nP1, Vector2 nP2)
{
//函数传入上一次触摸两点的位置与本次触摸两点的位置计算出用户的手势
float leng1 = Mathf.Sqrt((oP1.x - oP2.x) * (oP1.x - oP2.x) + (oP1.y - oP2.y) * (oP1.y - oP2.y));
float leng2 = Mathf.Sqrt((nP1.x - nP2.x) * (nP1.x - nP2.x) + (nP1.y - nP2.y) * (nP1.y - nP2.y));
if (leng1 < leng2)
{
//放大手势
return true;
}
else
{
//缩小手势
return false;
}
}
void Start()
{
Input.multiTouchEnabled = true;//开启多点触碰
}
void Update()
{
if (Input.touchCount <= 0)
return;
if (Input.touchCount == 1) //单点触碰移动摄像机
{
if (Input.touches[0].phase == TouchPhase.Began)
m_screenPos = Input.touches[0].position; //记录手指刚触碰的位置
if (Input.touches[0].phase == TouchPhase.Moved) //手指在屏幕上移动,移动摄像机
{
transform.Translate(new Vector3( Input.touches[0].deltaPosition.x * Time.deltaTime, Input.touches[0].deltaPosition.y * Time.deltaTime, 0));
}
}
else if (Input.touchCount > 1)//多点触碰
{
//记录两个手指的位置
Vector2 nposition1 = new Vector2();
Vector2 nposition2 = new Vector2();
//记录手指的每帧移动距离
Vector2 deltaDis1 = new Vector2();
Vector2 deltaDis2 = new Vector2();
for (int i = 0; i < 2; i++)
{
Touch touch = Input.touches[i];
if (touch.phase == TouchPhase.Ended)
break;
if (touch.phase == TouchPhase.Moved) //手指在移动
{
if (i == 0)
{
nposition1 = touch.position;
deltaDis1 = touch.deltaPosition;
}
else
{
nposition2 = touch.position;
deltaDis2 = touch.deltaPosition;
if (isEnlarge(oposition1, oposition2, nposition1, nposition2)) //判断手势伸缩从而进行摄像机前后移动参数缩放效果
isforward = 1;
else
isforward = -1;
}
//记录旧的触摸位置
oposition1 = nposition1;
oposition2 = nposition2;
}
//移动摄像机
Camera.main.transform.Translate(isforward*Vector3.forward * Time.deltaTime*(Mathf.Abs(deltaDis2.x+deltaDis1.x)+Mathf.Abs(deltaDis1.y+deltaDis2.y)));
}
}
}
}
将这个脚本绑定在主摄像机上,发现单触摸操作可上下左右移动摄像机,双触摸操作可以缩放。
导出Android 在手机上运行,可以发现触摸起了效果。
Input.GetKey
当用户按住名称标识的键时,返回true。
Input.GetAxis
返回由axisName标识的虚拟轴的值。
Input.GetButtonDown
在用户按下由buttonName标识的虚拟按钮的帧期间,返回true。
Input.GetButtonUp
用户释放由buttonName标识的虚拟按钮的第一帧,返回true。
Input.GetKeyDown
在用户开始按下名称标识的帧期间,返回true。
Input.GetKeyUp
在用户释放由名称标识的密钥的帧期间,返回true。
Input.GetMouseButtonDown
在用户按下给定的鼠标按钮的帧期间返回true。
Input.GetMouseButtonUp
在用户释放给定鼠标键的帧期间,返回true。
***Input.GetAccelerationEven***t
返回在上一帧期间发生的特定加速度测量。(不分配临时变量)。
Input.GetAxisRaw
返回由axisName标识的虚拟轴的值,不应用任何平滑过滤。
Input.GetButton
按住buttonName标识的虚拟按钮时,返回true。
Input.GetJoystickNames
返回描述连接的操纵杆的字符串数组。
Input.GetMouseButton
返回是否按住给定的鼠标按钮。
*Input.GetTouch ***
调用Input.GetTouch以获取Touch结构。Input.GetTouch返回触摸用于选择的屏幕触摸(例如,手指或手写笔)。触摸描述屏幕触摸。所述索引参数选择屏幕触摸。
Input.touchCount提供当前的屏幕触摸数。如果Input.touchCount大于零,则GetTouch 索引设置要检查的屏幕触摸。触摸返回struct带有屏幕触摸详细信息的。每次额外的屏幕触摸都使用递增的Input.touchCount。
GetTouch返回一个Touch结构。使用零获取第一次屏幕触摸。举个例子,触摸包括以像素为单位的位置
C#的API文档 触摸的3个案例 https://docs.unity3d.com/ScriptReference/Input.GetTouch.html
public class ExampleClass : MonoBehaviour
{
private Vector3 position;
private float width;
private float height;
void Awake()
{
width = (float)Screen.width / 2.0f;
height = (float)Screen.height / 2.0f;
// Position used for the cube.
position = new Vector3(0.0f, 0.0f, 0.0f);
}
void OnGUI()
{
// Compute a fontSize based on the size of the screen width.
GUI.skin.label.fontSize = (int)(Screen.width / 25.0f);
GUI.Label(new Rect(20, 20, width, height * 0.25f),
"x = " + position.x.ToString("f2") +
", y = " + position.y.ToString("f2"));
}
void Update()
{
// Handle screen touches.
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
// Move the cube if the screen has the finger moving.
if (touch.phase == TouchPhase.Moved)
{
Vector2 pos = touch.position;
pos.x = (pos.x - width) / width;
pos.y = (pos.y - height) / height;
position = new Vector3(-pos.x, pos.y, 0.0f);
// Position the cube.
transform.position = position;
}
if (Input.touchCount == 2)
{
touch = Input.GetTouch(1);
if (touch.phase == TouchPhase.Began)
{
// Halve the size of the cube.
transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);
}
if (touch.phase == TouchPhase.Ended)
{
// Restore the regular size of the cube.
transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
}
}
}
}
}
//A third example:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public GameObject particle;
void Update()
{
for (int i = 0; i < Input.touchCount; ++i)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
// Construct a ray from the current touch coordinates
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
// Create a particle if hit
if (Physics.Raycast(ray))
{
Instantiate(particle, transform.position, transform.rotation);
}
}
}
}
}
Mathf.Sqrt
int Pin= Mathf.Sqrt(100) 平方根 结果 Pin=10,
Mathf.Clamp
Mathf.Clamp(float value,float min,float max); 限制 value的值在min,max之间,如果value大于max,则返回max,如果value小于min,则返回min,否者返回value;
例 Mathf.Clamp :
_rig.transform.position = new Vector3(transform.position.x, transform.position.y,
Mathf.Clamp(_rig.transform.position.z, -20.0f, 28.0f));
这里限制了刚体的Z轴方向的移动,刚体在-20.0到28.0范围内移动。
Mathf.Lerp
差值运算
Mathf .Ceil
返回大于或等于的最小整数f
Mathf .Infinity
正无穷大的表示形式(只读)
Vector3.Angle()
返回from和之间的角度(以度为单位)to。返回的角度是两个向量之间的无符号角度。这意味着使用两个向量之间的两个可能角度中的较小者。结果永远不会大于180度
Vector3.SignedAngle()
返回介于from和之间的符号角度(以度为单位)to。返回两个向量之间的两个可能角度中较小的一个,因此结果永远不会大于180度或小于-180度。如果您将from和to向量想象成一张纸上的线,两者都起源于同一点,那么axis向量将指向纸外。两个向量之间的测量角度在顺时针方向上为正,在逆时针方向上为负。
Vector3.Distance()
返回之间的距离a和b。Vector3.Distance(a,b) 与 (a-b).magnitude的结果相同。
Vector3.magnitude
Magnitude指向量的长度
Vector3 .sqrMagnitude Magnitude指向量的长度 sqrMagnitude向量长度的平方
返回此向量的平方长度(只读)。
向量的v大小计算为Mathf.Sqrt(Vector3.Dot(v,v))但是,Sqrt计算非常复杂
例:
Vector3 offset = other.position - transform.position;
float sqrLen = offset.sqrMagnitude;
Vector3.Dot()
两个向量的点积。点积是一个浮点值,等于两个向量的大小相乘在一起,然后乘以它们之间的夹角的余弦值。
Vector3.Cross
。两个向量的叉积。两个向量的叉积产生第三个向量,平行于法向量,等于两个输入的大小相乘在一起,然后再乘以两个输入之间的角度正弦值。您可以使用“左手定则”确定结果向量的方向。
Vector3.Lerp()
在两点之间线性插值。在点之间进行插值(就是方法自动插入值,形成一条完整的线性弧线),a并b通过插值进行插值t
Vector3.Slerp()
在两个向量之间进行球面插值运算(就是Vector3方法自动按球面插入值,形成一条完整的球面弧线)。之间进行内插a和b通过量t
Vector3.Normalize()
Vec4.mag
返回该向量的长度。
Vec3.mag
返回该向量的长度。
Vec2.mag
返回该向量的长度。
Vec4.magSqr
返回该向量的长度平方。
Vec3.magSqr
返回该向量的长度平方。
unity 中是 使用四元数是表示所有旋转的。
你可以使用 Quaternion.operator * 由另一个四元数来旋转一个旋转角度,或由一个旋转角度来旋转一个向量。
Quaternion.identity
public static Quaternion identity;
此四元数对应于“无旋转” ,对象与世界轴或父轴完全对齐。(只读)
Quaternion.Euler
public static Quaternion Euler(float x, float y, float z);
public static Quaternion Euler(Vector3 euler);
返回一个旋转角度,绕z轴旋转z度,绕x轴旋转x度,绕y轴旋转y度(像这样的顺序)