Unity手勢基本操作
主要有單指移動3D物體、單指旋轉(zhuǎn)3D物體、雙指縮放3D物體。
基類
using UnityEngine;
using System.Collections;
/// <summary>
/// 手勢操作父類,并用于互斥三種手勢
/// </summary>
public class GestureControl : MonoBehaviour
{
//記錄手勢狀態(tài):
//-1——沒有任何手勢在操作
//0——移動手勢正在操作
//1——旋轉(zhuǎn)手勢正在操作
//2——縮放手勢正在操作
public static int status = -1;
//用于記錄觸碰物體的時間(區(qū)分同為單指時移動與旋轉(zhuǎn),詳見相應代碼)
public static float TouchTime = 0;
protected bool isSelected = false;
//判斷是否事先選擇到了某物體
protected void OnMouseDown() {
isSelected = true;
}
//手指抬起,記錄歸零
protected void OnMouseUp() {
isSelected = false;
status = -1;
TouchTime = 0;
}
// Update is called once per frame
protected void Update()
{
if (!isSelected)
{
return;
}
else if(status == -1)
{
InputCheck();
}
}
/// <summary>
/// 之類相應操作
/// </summary>
protected virtual void InputCheck() { }
}
單指移動3D物體
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System;
public class MoveControl : GestureControl
{
protected override void InputCheck()
{
//單指移動
if (Input.touchCount == 1)
{
//觸碰按住3D物體不動1秒后物體隨手指一起移動
if (Input.GetTouch(0).phase == TouchPhase.Stationary)
{
TouchTime += Time.deltaTime;
if (TouchTime > 1)
{
status = 0;
}
}
if (status == 0)
{
StartCoroutine(CustomOnMouseDown());
}
}
}
IEnumerator CustomOnMouseDown()
{
//將物體由世界坐標系轉(zhuǎn)化為屏幕坐標系,由vector3 結(jié)構(gòu)體變量ScreenSpace存儲,以用來明確屏幕坐標系Z軸的位置
Vector3 ScreenPoint = Camera.main.WorldToScreenPoint(transform.position);
//由于鼠標的坐標系是二維的,需要轉(zhuǎn)化成三維的世界坐標系;
Vector3 WorldPostion = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenPoint.z));
//三維的情況下才能來計算鼠標位置與物體的距離
Vector3 distance = transform.position - WorldPostion;
//當鼠標左鍵按下時
while (Input.GetMouseButton(0))
{
//得到現(xiàn)在鼠標的二維坐標系位置
Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenPoint.z);
//將當前鼠標的2維位置轉(zhuǎn)化成三維的位置,再加上鼠標的移動距離
Vector3 CurPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + distance;
//CurPosition就是物體應該的移動向量賦給transform的position屬性
transform.position = CurPosition;
//鼠標釋放前都起作用
yield return new WaitForFixedUpdate();
}
}
}
單指旋轉(zhuǎn)3D物體
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System;
public class RotateControl : GestureControl
{
protected override void InputCheck()
{
#region 單點觸發(fā)旋轉(zhuǎn)(真實模型旋轉(zhuǎn))
if (Input.touchCount == 1)
{
//觸摸為移動類型
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
status = 1;
try
{
StartCoroutine(CustomOnMouseDown());
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
}
#endregion
#region 鍵盤A、D、W、S模擬旋轉(zhuǎn)(真實模型旋轉(zhuǎn))
if (Input.GetKeyDown(KeyCode.A))
{
transform.Rotate(Vector3.up, 45 * Time.deltaTime, Space.World);
}
if (Input.GetKeyDown(KeyCode.D))
{
transform.Rotate(Vector3.up, -45 * Time.deltaTime, Space.World);
}
if (Input.GetKeyDown(KeyCode.W))
{
transform.Rotate(Vector3.left, 45 * Time.deltaTime, Space.World);
}
if (Input.GetKeyDown(KeyCode.S))
{
transform.Rotate(Vector3.left, -45 * Time.deltaTime, Space.World);
}
#endregion
}
IEnumerator CustomOnMouseDown()
{
//當檢測到一直觸碰時,會不斷循環(huán)運行
while (Input.GetMouseButton(0))
{
//判斷是否點擊在UI上
#if UNITY_ANDROID || UNITY_IPHONE
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
#else
if (EventSystem.current.IsPointerOverGameObject())
#endif
{
Debug.Log("當前點擊在UI上");
}
else
{
float XX = Input.GetAxis("Mouse X");
float YY = Input.GetAxis("Mouse Y");
#region
//判斷左右滑動的距離與上下滑動距離大小
if (Mathf.Abs(XX) >= Mathf.Abs(YY))
{
//單指向左滑動情況
if (XX < 0)
{
transform.Rotate(Vector3.up, 45 * Time.deltaTime, Space.World);
}
//單指向右滑動情況
if (XX > 0)
{
transform.Rotate(-Vector3.up, 45 * Time.deltaTime, Space.World);
}
}
else
{
//單指向下滑動情況
if (YY < 0)
{
transform.Rotate(Vector3.left, 45 * Time.deltaTime, Space.World);
}
//單指向上滑動情況
if (YY > 0)
{
transform.Rotate(-Vector3.left, 45 * Time.deltaTime, Space.World);
}
}
#endregion
}
yield return new WaitForFixedUpdate();
}
}
}
雙指縮放3D物體
using UnityEngine;
using System.Collections;
public class ZoomControl : GestureControl
{
//記錄上一次手機觸摸位置判斷用戶是在左放大還是縮小手勢
private Vector2 oldPosition1;
private Vector2 oldPosition2;
//實時大小
Vector3 RealScale = new Vector3(1f, 1f, 1f);
//原始大小
float InitialScale = 0;
//縮放速度
public float ScaleSpeed = 0.1f;
//縮放比例
public float MaxScale = 2.5f;
public float MinScale = 0.5f;
void Start()
{
//獲取物體最原始大小
InitialScale = this.transform.localScale.x;
}
protected override void InputCheck()
{
#region 多點觸摸縮放(真實模型縮放)
if (Input.touchCount > 1)
{
status = 2;
StartCoroutine(CustomOnMouseDown());
}
#endregion
}
IEnumerator CustomOnMouseDown()
{
//當檢測到一直觸碰時,會不斷循環(huán)運行
while (Input.GetMouseButton(0))
{
//實時記錄模型大小
RealScale = this.transform.localScale;
if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
{
//觸摸位置
Vector3 tempPosition1 = Input.GetTouch(0).position;
Vector3 tempPosition2 = Input.GetTouch(1).position;
//函數(shù)返回真為放大,返回假為縮小
if (isEnlarge(oldPosition1, oldPosition2, tempPosition1, tempPosition2))
{
//判斷是否超過邊界
if (RealScale.x < InitialScale * MaxScale)
{
this.transform.localScale += this.transform.localScale * ScaleSpeed;
}
}
else
{
//判斷是否超過邊界
if (RealScale.x > InitialScale * MinScale)
{
this.transform.localScale -= this.transform.localScale * ScaleSpeed;
}
}
//備份上一次的觸摸位置
oldPosition1 = tempPosition1;
oldPosition2 = tempPosition2;
}
yield return new WaitForFixedUpdate();
}
}
//記錄手指位置與初始位置是縮小或放大
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;
}
}
}
聲明:文章內(nèi)容整理來源于網(wǎng)絡,版權(quán)屬于原作者,如有問題,請聯(lián)系我們!
來源:https://www.cnblogs.com/unity3ds/p/10983038.html
- 上一篇:HTC Vive 控制機械臂 2022/8/1
- 下一篇: HoloLens 2校準失敗的可能原因及解決辦法 2022/7/20


