1.物体以中心点建立轴,绕轴旋转
/// <summary>
/// 将物体绕轴旋转,且始终朝向中心
/// </summary>
/// <param name="obj">旋转物体</param>
/// <param name="center">旋转中心</param>
/// <param name="axis">旋转轴</param>
/// <param name="angle">绕轴旋转角度</param>
public void MyRotateAround(Transform obj, Vector3 center, Vector3 axis, float angle)
{
Vector3 pos = obj.position; //要旋转物体的坐标
Quaternion rot = Quaternion.AngleAxis(angle, axis); //按照axis向量为轴,旋转angle角度的四元数
Vector3 dir = pos - center; //从圆心指向摄像头的朝向向量
dir = rot * dir; //旋转此向量(看来是这个意思,旋转后的四元数*旋转前朝向向量,即为最终朝向向量)
obj.position = center + dir;//移动摄像机位置
Quaternion myrot = obj.rotation; //旋转前的四元数
//transform.rotation *= Quaternion.Inverse(myrot) * rot *myrot;//设置角度另一种方法
obj.rotation = rot * myrot; //设置角度(看来是这个意思,旋转后的四元数*旋转前的四元数,即为最终朝向四元数)
}
2.物体以中心点默认的世界坐标轴x,y,z轴,三个轴同时旋转(注释同上)
public void MyRotateAround(Transform obj, Vector3 center, float xAngle = 0, float yAngle = 0, float zAngle = 0)
{
Vector3 pos = obj.position;
Quaternion rot = Quaternion.Euler(xAngle, yAngle, zAngle);
Vector3 offset = pos - center;
offset = rot * offset;
obj.position = center + offset;
Quaternion myrot = obj.rotation;
obj.rotation = rot * myrot;
}
1.Quaternion.AngleAxis(angle,axis);创建一个四元数,绕axis轴旋转angle角度
2.Quaternion.Euler(mX, mY, mZ);创建一个四元数,绕x轴旋转mX角度,绕y轴旋转mY角度,绕z轴旋转mZ角度
3.旋转矢量:旋转后的四元数*旋转前朝向向量,即为最终朝向向量
4.四元数叠加:四元数相乘,是四元数的叠加;pxq,是在q旋转量的基础上,叠加p
例子:
鼠标右键旋转相机,观测物体
if (Input.GetMouseButton(1))
{
mouseX = Input.GetAxis("Mouse X") * Time.deltaTime * leftrightRotateSpeed; //绕y轴旋转角度
mouseY = Input.GetAxis("Mouse Y") * Time.deltaTime * updownRotateSpeed; //绕x轴旋转角度
direc1 = camTrans.position - playerTrans.position; //中心点到相机向量
direc2 = new Vector3(direc1.x, direc1.y - 10, direc1.z); //中心点到相机下方10位置的向量
direc = Vector3.Cross(direc1, direc2); //上面两个向量确定了上下方向的旋转轴向量
Common.Instance.MyRotateAround(camTrans, playerTrans.position, mouseY * direc.x, mouseX, mouseY * direc.z);
}
例2:简易freecamera
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FreeCamera : MonoBehaviour {
Transform CamTrans;
[Range(0.1f,20)]
public float MoveSpeed = 1;
[Range(0.1f, 20)]
public float RotateSpeed = 1;
protected Vector2 m_Rotation;
private void Start()
{
CamTrans = GetComponent<Transform>();
}
private void Update()
{
CamTrans.position += (CamTrans.forward * Input.GetAxis("Vertical") + CamTrans.right * Input.GetAxis("Horizontal") + CamTrans.up * Input.GetAxis("Updown")) * MoveSpeed;
float UpAngle = Input.GetAxis("Mouse X");
float RightAngle = -Input.GetAxis("Mouse Y");
float XRightSeparateAngle = RightAngle * Vector3.Dot(CamTrans.right, Vector3.right);
float ZRightSeparateAngle = RightAngle * Vector3.Dot(CamTrans.right, Vector3.forward);
Quaternion rot = Quaternion.Euler(XRightSeparateAngle * RotateSpeed, UpAngle * RotateSpeed, ZRightSeparateAngle * RotateSpeed);
CamTrans.rotation = rot * CamTrans.rotation;
}
}
例3:物体绕自身轴旋转
public float RotateSpeed;
public rotateAxis RotateAxis = rotateAxis.Z;
public enum rotateAxis
{
X, Y, Z
}
Vector3 mousePos;
private void Update()
{
if(Input.GetKey(KeyCode.Mouse0))
{
float xDistance = Input.mousePosition.x - mousePos.x;
//float yDistance = Input.mousePosition.y - mousePos.y;
Vector3 rotAxis = Vector3.zero;
switch(RotateAxis)
{
case rotateAxis.X:
rotAxis = transform.right;
break;
case rotateAxis.Y:
rotAxis = transform.up;
break;
case rotateAxis.Z:
rotAxis = transform.forward;
break;
}
MyRotateAround(transform, transform.position, rotAxis, xDistance * RotateSpeed);
mousePos = Input.mousePosition;
}
}