主要有单指移动3D物体、单指旋转3D物体、双指缩放3D物体。
基类
using UnityEngine; using System.Collections; /// <summary> /// 手势操作父类,并用于互斥三种手势 /// </summary> public class GestureControl : MonoBehaviour { //记录手势状态: //-1——没有任何手势在操作 //0——移动手势正在操作 //1——旋转手势正在操作 //2——缩放手势正在操作 public static int status = -1; //用于记录触碰物体的时间(区分同为单指时移动与旋转,详见相应代码) public static float TouchTime = 0; protected bool isSelected = false; //判断是否事先选择到了某物体 protected void onm ouseDown() { isSelected = true; } //手指抬起,记录归零 protected void onm ouseUp() { 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() { //将物体由世界坐标系转化为屏幕坐标系,由vector3 结构体变量ScreenSpace存储,以用来明确屏幕坐标系Z轴的位置 Vector3 ScreenPoint = Camera.main.WorldToScreenPoint(transform.position); //由于鼠标的坐标系是二维的,需要转化成三维的世界坐标系; Vector3 WorldPostion = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenPoint.z)); //三维的情况下才能来计算鼠标位置与物体的距离 Vector3 distance = transform.position - WorldPostion; //当鼠标左键按下时 while (Input.GetMouseButton(0)) { //得到现在鼠标的二维坐标系位置 Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, ScreenPoint.z); //将当前鼠标的2维位置转化成三维的位置,再加上鼠标的移动距离 Vector3 CurPosition = Camera.main.ScreenToWorldPoint(curScreenSpace) + distance; //CurPosition就是物体应该的移动向量赋给transform的position属性 transform.position = CurPosition; //鼠标释放前都起作用 yield return new WaitForFixedUpdate(); } } }
单指旋转3D物体
using UnityEngine; using System.Collections; using UnityEngine.EventSystems; using System; public class RotateControl : GestureControl { protected override void InputCheck() { #region 单点触发旋转(真实模型旋转) 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模拟旋转(真实模型旋转) 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() { //当检测到一直触碰时,会不断循环运行 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() { //当检测到一直触碰时,会不断循环运行 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; //函数返回真为放大,返回假为缩小 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; } } }