专门针对AR相机的手势操作脚本,包含旋转平移缩放功能。
有小伙伴们觉得可以优化的地方请把行数及优化代码一起留言至评论区。
废话不多说,直接上代码。
using System.Collections;
using UnityEngine;
public class ARFingerGestures : MonoBehaviour
{
public Transform ARCamera; //AR相机拖拽到这个上面
private float fingerActionSensitivity = Screen.width * 0.05f; //手指动作的敏感度,这里设定为 二十分之一的屏幕宽度.
private float fingerBeginX;
private float fingerBeginY;
private float fingerCurrentX;
private float fingerCurrentY;
private float fingerSegmentX;
private float fingerSegmentY;
private int fingerTouchState;
private int FINGER_STATE_NULL = 0;
private int FINGER_STATE_TOUCH = 1;
private int FINGER_STATE_ADD = 2;
private Touch oldTouch1; //上次触摸点1(手指1)
private Touch oldTouch2; //上次触摸点2(手指2)
float _最大缩放比例 = 1000f;
float _最小缩放比例 = 0.2f;
bool rot;
//是否允许位移,默认打开,在双指触控时关闭,手指挪开时再打开
// bool isOffset=true;
Vector2 deltaPos;
// private Vector3 offect;//偏移位置鼠标转世界坐标与transform.position的偏移量
public enum GestureStatus
{
def,
shrink,
move
}
private GestureStatus gesStatus = GestureStatus.def;
void Start()
{
fingerActionSensitivity = Screen.width * 0.05f;
fingerBeginX = 0;
fingerBeginY = 0;
fingerCurrentX = 0;
fingerCurrentY = 0;
fingerSegmentX = 0;
fingerSegmentY = 0;
fingerTouchState = FINGER_STATE_NULL;
}
/// <summary>
/// 双指平移
/// </summary>
/// <param name="arTarget"></param>
/// <param name="arCamera"></param>
Vector3 inputOffset;
void ARGestureMove(Transform arTarget, Camera arCamera)
{
if (Input.GetTouch(1).phase == TouchPhase.Began)
{
Vector3 pos = arCamera.WorldToScreenPoint(arTarget.position);
inputOffset = (Vector3)Input.GetTouch(1).position - pos;
}
if (gesStatus == GestureStatus.move)
{
if (Input.GetTouch(1).phase == TouchPhase.Moved)
{
Vector3 point = arCamera.ScreenToWorldPoint((Vector3)Input.GetTouch(1).position - inputOffset);
arTarget.position = GetPositonOnPlane(point, arCamera.transform.position, 0);
}
}
}
Vector3 GetPositonOnPlane(Vector3 point0, Vector3 cameraPos, float height)
{
if (point0.y == cameraPos.y || height == cameraPos.y || point0.y == height)
{
return point0;
}
float c = (height - point0.y) / (height - cameraPos.y);
Vector3 result;
result.x = (point0.x - c * cameraPos.x) / (1 - c);
result.z = (point0.z - c * cameraPos.z) / (1 - c);
result.y = height;
return result;
}
// Update is called once per frame
void Update()
{
//没有触摸
if (Input.touchCount <= 0)
{
// isOffset = true;
return;
}
if (1 == Input.touchCount)
{
Touch touch = Input.GetTouch(0);
deltaPos = touch.deltaPosition;
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
if (fingerTouchState == FINGER_STATE_NULL)
{
fingerTouchState = FINGER_STATE_TOUCH;
fingerBeginX = Input.mousePosition.x;
fingerBeginY = Input.mousePosition.y;
}
}
if (fingerTouchState == FINGER_STATE_TOUCH)
{
fingerCurrentX = Input.mousePosition.x;
fingerCurrentY = Input.mousePosition.y;
fingerSegmentX = fingerCurrentX - fingerBeginX;
fingerSegmentY = fingerCurrentY - fingerBeginY;
}
if (fingerTouchState == FINGER_STATE_TOUCH && Input.GetTouch(0).phase == TouchPhase.Moved)
{
float fingerDistance = fingerSegmentX * fingerSegmentX + fingerSegmentY * fingerSegmentY;
if (fingerDistance > (fingerActionSensitivity * fingerActionSensitivity))
{
rot = true;
}
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
fingerTouchState = FINGER_STATE_NULL;
rot = false;
}
}
if(Input.touchCount==2)
{
if (Input.GetTouch(1).phase==TouchPhase.Began)
{
StartCoroutine(GesProcessing()); }
ARGestureZoom();
ARGestureMove(transform,Camera.main);
if (Input.GetTouch(1).phase == TouchPhase.Ended)
gesStatus = GestureStatus.def;
}
if (rot)
{
toAddFingerAction(deltaPos);
}
}
public float num = 0;
IEnumerator GesProcessing() {
var touch0 = Input.GetTouch(0).position;
var touch1 = Input.GetTouch(1).position;
yield return new WaitForSeconds(0.1f);
var dir0 = touch0 - Input.GetTouch(0).position;
var dir1 = touch1 - Input.GetTouch(1).position;
var angle = Vector3.Angle(dir0, dir1);
Debug.Log("angle"+angle+"0"+dir0+"1"+dir1);
if (angle < 15)
gesStatus = GestureStatus.move;
else
gesStatus = GestureStatus.shrink;
}
private void ARGestureZoom() {
//多点触摸, 放大缩小
Touch newTouch1 = Input.GetTouch(0);
Touch newTouch2 = Input.GetTouch(1);
//第2点刚开始接触屏幕, 只记录,不做处理
if (newTouch2.phase == TouchPhase.Began)
{
oldTouch2 = newTouch2;
oldTouch1 = newTouch1;
return;
}
if (gesStatus == GestureStatus.shrink)
{
//计算老的两点距离和新的两点间距离,变大要放大模型,变小要缩放模型
float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);
float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);
//两个距离之差,为正表示放大手势, 为负表示缩小手势
float offset = newDistance - oldDistance;
//放大因子, 一个像素按 0.01倍来算(100可调整)
float scaleFactor = offset / (1000f / transform.localScale.x);
Vector3 localScale = transform.localScale;
Vector3 scale = new Vector3(localScale.x + scaleFactor,
localScale.y + scaleFactor,
localScale.z + scaleFactor);
scale = new Vector3(Mathf.Clamp(scale.x, _最小缩放比例, _最大缩放比例),
Mathf.Clamp(scale.y, _最小缩放比例, _最大缩放比例),
Mathf.Clamp(scale.z, _最小缩放比例, _最大缩放比例));
transform.localScale = scale;
//最小缩放到 0.3 倍
//if (scale.x > _最小缩放比例 && scale.y > _最小缩放比例 && scale.z > _最小缩放比例)
//{
// transform.localScale = scale;
//}
//记住最新的触摸点,下次使用
oldTouch1 = newTouch1;
oldTouch2 = newTouch2;
}
}
private void toAddFingerAction(Vector2 deltaPos)
{
fingerTouchState = FINGER_STATE_ADD;
if (Mathf.Abs(fingerSegmentX) > Mathf.Abs(fingerSegmentY))
{
fingerSegmentY = 0;
}
else
{
fingerSegmentX = 0;
}
//上下旋转
//if (fingerSegmentX == 0)
//{
// if (fingerSegmentY > 0)
// {
// Debug.Log("up");
// }
// else
// {
// Debug.Log("down");
// }
// transform.Rotate(Camera.main.transform.right * deltaPos.y * 0.2f, Space.World);
//}
//左右旋转
if (fingerSegmentY == 0)
{
if (fingerSegmentX > 0)
{
Debug.Log("right");
}
else
{
Debug.Log("left");
}
transform.Rotate(Vector3.down * deltaPos.x * 0.2f, Space.World);
}
}
}