Unity开发记录_4_安卓项目 手指操作物体旋转避免万向节死锁 手指控制物体缩放和旋转方案
问题描述
网上搜索了几篇手指控制物体旋转的代码 但是效果都不佳只好自己写了
但是在写的过程中发现,如果用手指在屏幕上下 和 左右 操作来控制物体 单轴
的旋转,总会有万向节死锁的问题,就想了个取巧的方案去实现-----每次旋转之前都新建一个父物体 完成旋转后父物体还原
先看结果
使用方式—支持PC和安卓
将代码挂在在要旋转的物体身上,在PC编辑器想查看效果 可以勾选 bool TurnOnRotationOnPC
我的代码中旋转的是X Y轴,如果实际感觉旋转的不对,需要你调整相机位置为正方向 或者 去修改代码是否你想要的旋转是Y Z轴。
完整代码:
@Override
using UnityEngine;
public class FingerController : MonoBehaviour
{
public bool TurnOnRotationOnPC = true;
public float RotationSpeed = 10f;
private GameObject m_parentObject;
private Transform m_target;
private bool m_isRotating = false;
private Transform m_initParent;
#if UNITY_ANDROID
public Vector2 BoundScale = new Vector2(0.1f, 10);
private float m_newdis;
private float m_olddis;
private float m_scalingSpeed = 2;
//缩放计时器---避免当缩放取消的时候 手指离开屏幕瞬间 导致物体旋转被触发
private bool m_isScaling;
private float m_ScalingTimeCount;//更改这个值可以控制间隔时间--初始0.2f
#endif
private void Start()
{
m_target = transform;
}
private void Update()
{
HandleRotationInput();
HandleScalingInput();
}
/// <summary>
/// 旋转控制
/// </summary>
private void HandleRotationInput()
{
#if UNITY_ANDROID && !UNITY_EDITOR
if (m_isScaling)
{
m_ScalingTimeCount -= Time.deltaTime;
if (m_ScalingTimeCount < 0)
{
m_ScalingTimeCount = 0;
m_isScaling = false;
}
return;
}
if (Input.touchCount == 1)
{
if (!m_isRotating)
{
StartRotation();
}
HandleRotation();
}
else if (m_isRotating)
{
StopRotation();
}
#endif
if (TurnOnRotationOnPC)
{
if (Input.GetMouseButtonDown(0))
{
StartRotation();
}
if (Input.GetMouseButton(0))
{
HandleRotation();
}
if (Input.GetMouseButtonUp(0))
{
StopRotation();
}
}
}
/// <summary>
/// 缩放控制
/// </summary>
private void HandleScalingInput()
{
StartScaling();
}
/// <summary>
/// 开始旋转
/// </summary>
private void StartRotation()
{
if (!m_isRotating)
{
m_initParent = transform.parent;
if (m_parentObject == null)
{
m_parentObject = new GameObject("RotationParent")
{
transform = { position = m_target.position }
};
m_target.SetParent(m_parentObject.transform);
}
m_isRotating = true;
}
}
/// <summary>
/// 旋转中
/// </summary>
private void HandleRotation()
{
if (!m_isRotating) return;
Vector2 deltaPos = Vector2.zero;
#if UNITY_ANDROID && !UNITY_EDITOR
if (Input.touchCount > 0)
{
deltaPos = Input.GetTouch(0).deltaPosition;
}
#endif
if (Input.GetMouseButton(0) && TurnOnRotationOnPC)
{
deltaPos = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
}
float rotationAmountY = -deltaPos.x * RotationSpeed;
float rotationAmountX = deltaPos.y * RotationSpeed;
m_parentObject.transform.Rotate(Vector3.up * rotationAmountY, Space.World);
m_parentObject.transform.Rotate(Vector3.right * rotationAmountX, Space.Self);
}
/// <summary>
/// 停止旋转
/// </summary>
private void StopRotation()
{
if (m_parentObject != null)
{
m_target.SetParent(m_initParent);
Destroy(m_parentObject);
m_parentObject = null;
}
m_isRotating = false;
}
/// <summary>
/// 开始缩放---安卓平台
/// </summary>
private void StartScaling()
{
#if UNITY_ANDROID
if (Input.touchCount > 1)
{
if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
{
m_newdis = Vector2.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
float scaleDelta = Mathf.Clamp01(m_newdis) * Time.deltaTime * m_scalingSpeed;
scaleDelta = m_newdis > m_olddis ? scaleDelta : -scaleDelta;
transform.localScale += new Vector3(scaleDelta, scaleDelta, scaleDelta);
float valScale = Mathf.Clamp(transform.localScale.x, BoundScale.x, BoundScale.y);
transform.localScale = new Vector3(valScale, valScale, valScale);
m_olddis = m_newdis;
m_isScaling = true;
m_ScalingTimeCount = 0.2f;
}
}
#endif
}
}