修改:《Unity API解析》一书中关于SetFromRotation应该有点问题,这里使用transform.rotation = q1就实现了将GameObject对象自身坐标系中向量v1指向的方向旋转到v2方向了??
下面的部分写于8.13号
创建一个fromDirection到toDirection的旋转。
这里需要注意的是,是将GameObject自身坐标系中的向量v1指向的方向旋转到v2。是自身坐标系上的向量旋转,这样就可以让GameObject旋转了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QuaternionTest : MonoBehaviour
{
public Transform A, B, C;
Quaternion q1 = Quaternion.identity;
// Update is called once per frame
void Update()
{
//不可直接使用C.rotation.SetFromToRotation()
q1.SetFromToRotation(A.position, B.position);
C.rotation = q1;
Debug.DrawLine(Vector3.zero, A.position, Color.red);
Debug.DrawLine(Vector3.zero, B.position, Color.green);
Debug.DrawLine(C.position, C.position + new Vector3(0f, 1f, 0f) , Color.black);
Debug.DrawLine(C.position, C.TransformPoint( Vector3.up*1.5f ), Color.yellow);
}
}
这里物体A坐标为(0,1.58, 0), B(0, 1.58, 3.42), C( 4.18, 1.58, 0 )。
q1.SetFromToRotation(A.position, B.position);
C.rotation = q1;
让C自身坐标系上的向量A.position 转向 B.position. 因此这里就是让C自身向量(0,1.58,0)归一化后的(0,1,0)转向 B.postion向量。可以看到黄色线条与 起点指向B的向量平行。
参考《unity API解析》
8.14号发现了《unity API解析》一书对函数SetFromRotation的解释应该有点问题。
SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
这个函数官方解释如下:
Returns or sets the euler angle representation of the rotation.
A rotation that rotates euler.z degrees around the z axis, euler.x degrees around the x axis, and euler.y degrees around the y axis (in that order). The euler can be set for, or read from, the quaternion.
这里返回一个表示旋转的欧拉角度, 是的,这里返回的角度是用来表示一种旋转方式的,并不是游戏对象旋转后的结果。
如果要将返回的旋转角度看成最终的旋转结果,可以这样考虑:
该函数返回的是对 世界坐标系下 无任何旋转的游戏对象 旋转后的结果
下面看个例子:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationTest : MonoBehaviour
{
public bool isMul = true;
public bool useRotation = true;
// Start is called before the first frame update
void Start()
{
Quaternion q = Quaternion.identity;
q.SetFromToRotation(Vector3.up, Vector3.forward);
if (useRotation)
{
if (isMul)
{
transform.rotation *= q;
}
else
{
transform.rotation = q;
}
}
}
// Update is called once per frame
void Update()
{
Debug.DrawLine(transform.position, transform.TransformPoint(Vector3.up*0.7f ), Color.cyan);
Debug.DrawLine(transform.position, transform.TransformPoint(Vector3.right*0.7f), Color.red);
Debug.DrawLine(transform.position, transform.TransformPoint(new Vector3(0,0,1)*0.7f), Color.blue);
}
}
赋值的话,就是 将世界空间下一个没有旋转的游戏对象的 up向量旋转到forward向量 的最终结果
还可以这样写:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotationTest : MonoBehaviour
{
public bool isMul = true;
public bool useRotation = true;
// Start is called before the first frame update
void Start()
{
if (useRotation)
{
if (isMul)
{
transform.rotation *= Quaternion.FromToRotation(Vector3.up, Vector3.forward);
}
else
{
transform.rotation = Quaternion.FromToRotation(Vector3.up, Vector3.forward);
}
}
}
// Update is called once per frame
void Update()
{
Debug.DrawLine(transform.position, transform.TransformPoint(Vector3.up*0.7f ), Color.cyan);
Debug.DrawLine(transform.position, transform.TransformPoint(Vector3.right*0.7f), Color.red);
Debug.DrawLine(transform.position, transform.TransformPoint(new Vector3(0,0,1)*0.7f), Color.blue);
}
}