今天解决了一个小白的问题。
说来惭愧,一直对四元数不是很理解,之前有一个滑动屏幕旋转球体的问题,使用欧拉角旋转来处理,万向锁的问题解决不了,尝试了很多方法都失败了,今天无意中看到一篇帖子(如上)说到如何将球体旋转到固定位置,看完代码突然感觉有了希望,于是,问题解决了,我把代码贴出来。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
public class SphereRotate : MonoBehaviour
{
public delegate void OnDragStartHandler();
public OnDragStartHandler onDragStartHandler;
[Tooltip("sphere target")]
public Transform target;
private bool _rotateable = false;
[Tooltip("sphere rotate speed")]
[Range(0, 10)]
public float speed = 1f;
private void Start()
{
if (target)
_rotateable = true;
}
void OnEnable()
{
EasyTouch.On_TouchDown += OnDragHandler;
EasyTouch.On_TouchStart += EasyTouch_On_DragStart;
}
void OnDisable()
{
EasyTouch.On_TouchDown -= OnDragHandler;
EasyTouch.On_TouchStart -= EasyTouch_On_DragStart;
}
private void OnDragHandler(Gesture gesture)
{
if (!_rotateable) return;
//屏幕向量
Vector2 deltaPos = gesture.deltaPosition;
float magnitude = deltaPos.magnitude;
//转换到世界空间的向量,默认高度
Vector3 moveDir = new Vector3(deltaPos.x, 0, deltaPos.y);
// 球进行旋转即以 moveDir和Vector3.up向量组成任意平面垂直的向量(法向量)为旋转轴
// moveDir 和 Vector3.up 叉乘,获取 moveDir、Vector3.up 组成平面的法向量
Vector3 cross = Vector3.Cross(moveDir, Vector3.up);
float angle = -magnitude * speed;
//Debug.Log("deltaPos:" + deltaPos + ",angle:" + angle);
Quaternion qua = Quaternion.AngleAxis(angle, cross);
target.transform.rotation = qua * target.transform.rotation;
}
//开始滑动
void EasyTouch_On_DragStart(Gesture gesture)
{
if (!_rotateable) return;
if (onDragStartHandler != null)
onDragStartHandler();
}
}