Unity 双指旋转

思路都是:

每一帧以两指坐标生成一个向量Vector2,不同帧比较向量的角度变化Vector2.Angle()。

简化版:参考EasyTouch的实现

public class TouchTest : MonoBehaviour
{

	Touch oldTouch1;  //上次触摸点1(手指1)
	Touch oldTouch2;  //上次触摸点2(手指2)

	void Update()
	{
		if (Input.touchCount <= 1) {
			return;
		}

		Touch touch1 = Input.GetTouch(0);
		Touch touch2 = Input.GetTouch(1);

		//启用双指,尚未旋转
		if (touch2.phase == TouchPhase.Began) {
			oldTouch2 = touch2;
			oldTouch1 = touch1;
			return;
		}
		if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved) {
			Vector2 curVec = touch2.position - touch1.position;
			Vector2 oldVec = oldTouch2.position - oldTouch1.position;
			float angle = Vector2.Angle(oldVec, curVec);
			angle *= Mathf.Sign(Vector3.Cross(oldVec, curVec).z);

			transform.Rotate(new Vector3(0, 0, angle));

			oldTouch1 = touch1;
			oldTouch2 = touch2;
		}
	}
}



另一种写法,参考的博客已失效,这里贴一下

const float pinchTurnRatio = Mathf.PI / 2;
	//用这个数值来判定旋转的最小角度,自己决定大小
	const float minTurnAngle = 0;

	/// <summary>
	///   The delta of the angle between two touch points
	/// </summary>
	static public float turnAngleDelta;
	/// <summary>
	///   The angle between two touch points
	/// </summary>
	static public float turnAngle;

	/// <summary>
	///   Calculates Pinch and Turn - This should be used inside LateUpdate
	/// </summary>
	static public void Calculate()
	{
		//pinchDistance = pinchDistanceDelta = 0;
		turnAngle = turnAngleDelta = 0;

		// if two fingers are touching the screen at the same time ...
		if (Input.touchCount == 2) {
			Touch touch1 = Input.touches[0];
			Touch touch2 = Input.touches[1];

			// ... if at least one of them moved ...如果有一根手指有移动
			if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved) {
				// ... or check the delta angle between them ...
				//当前两手指与X轴的角
				turnAngle = Angle(touch1.position, touch2.position);
				//之前两手指与X的角度
				float prevTurn = Angle(touch1.position - touch1.deltaPosition,
									   touch2.position - touch2.deltaPosition);
				//旋转的偏移量, 增量角
				turnAngleDelta = Mathf.DeltaAngle(prevTurn, turnAngle);

				// ... if it's greater than a minimum threshold, it's a turn!
				//增量角如果大于设定值
				if (Mathf.Abs(turnAngleDelta) > minTurnAngle) {
					turnAngleDelta *= pinchTurnRatio;
				} else {
					turnAngle = turnAngleDelta = 0;
				}
			}
		}

		//鼠标判断事件,这个只是个测试
#if UNITY_EDITOR
		MouseRotateEvent();
#endif
	}

	/// <summary>
	/// 取两个向量之间的角度 与X轴
	/// </summary>
	/// <param name="pos1"></param>
	/// <param name="pos2"></param>
	/// <returns></returns>
	static private float Angle(Vector2 pos1, Vector2 pos2)
	{
		//取两个向量相减
		Vector2 from = pos2 - pos1;

		//X轴
		Vector2 to = new Vector2(1, 0);

		//与X轴夹角
		float result = Vector2.Angle(from, to);

		//向量的叉乘
		Vector3 cross = Vector3.Cross(from, to);
		//如果超出360度
		if (cross.z > 0) {
			//用360来减这个角度
			result = 360f - result;
		}

		return result;
	}

#if UNITY_EDITOR
	static bool isPress = false;
	static float preAngle = 0;

	/// <summary>
	/// 鼠标右键旋转事件,并非完美实现,因为没有判断角度为正还是为负。
	/// </summary>
	static public void MouseRotateEvent()
	{
		if (Input.GetMouseButton(1)) {
			//第一次按下
			if (!isPress) {
				//上一帧的角度
				preAngle = Angle(Input.mousePosition, Vector2.zero);
				isPress = true;
			} else {
				//转动的角度
				turnAngle = Angle(Input.mousePosition, Vector2.zero);
				//旋转的偏移量, 增量角
				turnAngleDelta = Mathf.DeltaAngle(preAngle, turnAngle);
				Log.log("增量角:"+turnAngleDelta);

				//增量角如果大于设定值
				if (Mathf.Abs(turnAngleDelta) > minTurnAngle) {
					turnAngleDelta *= pinchTurnRatio;
				} else {
					turnAngle = turnAngleDelta = 0;
				}

				//更新为这一帧
				preAngle = Angle(Input.mousePosition, Vector2.zero);
			}
		} else {
			isPress = false;
		}
	}
#endif






	/// <summary>
	/// 绕点旋转,或者是Z轴旋转?
	/// </summary>
	public bool isRotateAround = false;

	//目标
	public Transform target;

	//围绕点
	protected Vector3 axis {
		get {
			return new Vector3(target.position.x, transform.position.y, target.position.z);
		}
	}

	//void Start()
	//{
	//	if (target == null) {
	//		Debug.Log("target is null!");
	//		enabled = false;
	//	}
	//}

	void Update()
	{
		Calculate();

		if (Mathf.Abs(turnAngleDelta) > 0) {
			if (isRotateAround) {
				//围点旋转
				transform.RotateAround(axis, Vector3.up, -turnAngleDelta);
				//目视对方
				transform.LookAt(target);
			} else {
				Quaternion desiredRotation = transform.rotation;
				Vector3 rotationDeg = Vector3.zero;
				//z轴旋转
				rotationDeg.z = -turnAngleDelta;
				desiredRotation *= Quaternion.Euler(rotationDeg);
				transform.rotation = desiredRotation;
			}
		}
	}




### Unity中通过触摸实现物体旋转Unity中,可以通过检测多点触控的手势来实现物体的旋转功能。具体来说,可以利用`Input.touchCount`获取当前屏幕上存在的触摸数量,并结合`Touch.phase`判断触摸的状态。当有两个触摸点时,计算两个触摸点之间的角度变化量并将其映射到物体的旋转操作。 以下是基于触摸实现物体旋转的核心逻辑: #### 触摸旋转物体的代码示例 ```csharp using UnityEngine; public class RotateObject : MonoBehaviour { private Vector2 touchPosition1; private Vector2 touchPosition2; private float previousAngle = 0f; void Update() { if (Input.touchCount == 2) // 检测是否有两个触摸点 { Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); touchPosition1 = touchZero.position; // 获取第一个触摸位置 touchPosition2 = touchOne.position; // 获取第二个触摸位置 float currentAngle = CalculateAngle(touchPosition1, touchPosition2); // 计算两间的角度 float angleDifference = currentAngle - previousAngle; // 计算角度差值 transform.Rotate(Vector3.up * angleDifference); // 绕Y轴旋转物体 previousAngle = currentAngle; // 更新前一次的角度记录 } else { previousAngle = 0f; // 如果不是,则重置角度 } } /// <summary> /// 计算两点之间形成的夹角 /// </summary> /// <param name="pointA">触摸点A</param> /// <param name="pointB">触摸点B</param> /// <returns>返回两点形成的角度</returns> private float CalculateAngle(Vector2 pointA, Vector2 pointB) { Vector2 direction = pointB - pointA; return Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; // 将弧度转换为角度 } } ``` 上述脚本实现了通过拖动屏幕使物体绕其局部坐标系中的Y轴进行旋转的效果[^2]。其中的关键在于捕获两次触摸的位置,并通过向量运算得出两者间的相对角度变化。 #### 单触摸旋转物体的代码示例 对于单触摸的情况,也可以让物体随着手移动的方向而发生旋转。这种情况下主要依赖于手位移方向与物体中心的关系来进行旋转处理。 下面是单触摸旋转的一个简单例子: ```csharp using UnityEngine; public class SingleFingerRotate : MonoBehaviour { public float rotationSpeed = 180f; // 设置旋转速度 void Update() { if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved) { Touch touch = Input.GetTouch(0); Vector2 deltaMovement = touch.deltaPosition; // 手移动的距离 float horizontalRotation = deltaMovement.x * rotationSpeed * Time.deltaTime; // X轴上的水平旋转分量 float verticalRotation = deltaMovement.y * rotationSpeed * Time.deltaTime; // Y轴上的垂直旋转分量 transform.Rotate(verticalRotation, horizontalRotation, 0f); // 应用于物体的旋转 } } } ``` 此段代码展示了如何依据单一触摸点的运动轨迹改变对象的姿态。它会根据用户手划过的距离按比例调整目标物体会转多少圈数以及朝哪个方向转动。 ### 注意事项 - **性能优化**:频繁读取输入数据可能带来一定开销,在实际项目开发过程中应注意减少不必要的更新频率。 - **设备兼容性测试**:不同平台(iOS/Android)可能存在细微差异,建议充分验证各端表现一致性。 - **用户体验设计**:合理设置灵敏度阈值避免误触发动作;同时考虑加入边界约束防止过度扭曲模型外观等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值