在unity的左手坐标系系统中,一个物体有三个轴向,确定了两个轴向那物体的旋转就确定了,很多时候我们只需要指定物体的某个方向比如transform.forward= others.transform.forward,又或者指定物体的旋转transform.rotation = others.transform.rotation就可以满足需求,但是如果我们需要指定物体的A的z轴与b的z轴一致,但是y轴是b的x轴的反方向呢,这种时候上面的两种做法就不能满足情况了,不懂四元数的话又比较吃力,所以这里提供一个方法,可以实现一个物体的两个标准轴的方向与两个互相垂直的轴重合
具体思路是,先让物体的一个轴与目标轴重合,然后再让物体围绕已摆弄好的轴旋转从而让另一个轴与目标轴重合
/// <summary>
/// 让toChngTrn达到
/// firstVctrToOper代表的轴方向与firstVctrToReach一致并且
/// scndVctrToOper代表的轴方向与scndVctrToReach一致的时候
/// 的旋转
/// </summary>
/// <param name="firstVctrToOper"></param>
/// <param name="scndVctrToOper"></param>
/// <param name="toChngTrn"></param>
/// <param name="firstVctrToReach"></param>
/// <param name="scndVctrToReach"></param>
public static void AlignTransformWithTwoVctr(Vector3 firstVctrToOper,
Vector3 scndVctrToOper, Transform toChngTrn, Vector3 firstVctrToReach,
Vector3 scndVctrToReach)
{
if (firstVctrToOper == scndVctrToOper ||
firstVctrToReach == scndVctrToReach || toChngTrn == null)
{
Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr invalid Param ");
return;
}
Vector3 rotateAroundPivotVctr = Vector3.zero;
//第一次的时候直接设置值即可
if (firstVctrToOper == toChngTrn.forward)
{
//Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
// "firstVctrToOper == toChngTrn.forward");
toChngTrn.forward = firstVctrToReach;
rotateAroundPivotVctr = Vector3.forward;
}
else if (firstVctrToOper == toChngTrn.right)
{
//Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
// "firstVctrToOper == toChngTrn.right");
toChngTrn.right = firstVctrToReach;
rotateAroundPivotVctr = Vector3.right;
}
else if (firstVctrToOper == toChngTrn.up)
{
//Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
// "firstVctrToOper == toChngTrn.up");
toChngTrn.up = firstVctrToReach;
rotateAroundPivotVctr = Vector3.up;
}
Transform tempTrn1 = new GameObject("tempTrn1").transform;
tempTrn1.rotation = toChngTrn.rotation;
bool isFind = true;
if (!AlignScndPivot(scndVctrToReach, PivotEnum.Front, toChngTrn.forward,
rotateAroundPivotVctr, toChngTrn))
{
if (!AlignScndPivot(scndVctrToReach, PivotEnum.Right, toChngTrn.right,
rotateAroundPivotVctr, toChngTrn))
{
if (!AlignScndPivot(scndVctrToReach, PivotEnum.Up, toChngTrn.up,
rotateAroundPivotVctr, toChngTrn))
{
isFind = false;
}
else
{
Debug.LogError("ThreeDUtil PivotEnum.Up find");
}
}
else
{
Debug.LogError("ThreeDUtil PivotEnum.Right find");
}
}
else
{
Debug.LogError("ThreeDUtil PivotEnum.Front find");
}
if (!isFind)
{
Debug.LogError("ThreeDUtil AlignTransformWithTwoVctr notFind");
}
GameObject.Destroy(tempTrn1.gameObject);
}
static bool AlignScndPivot(Vector3 toReachVctr, PivotEnum matchPivot,
Vector3 toChngPivotVctr, Vector3 rotatePivotVctr, Transform toChngTrn)
{
float deltaDegree = 0;
Transform tempTrn2, tempTrn3;
deltaDegree = Vector3.Angle(toChngPivotVctr, toReachVctr);
//Debug.LogError("ThreeDUtil AlignScndPivot deltaDegree " +
// deltaDegree + " rotatePivotVctr " + rotatePivotVctr);
tempTrn2 = new GameObject("tempTrn2").transform;
tempTrn3 = new GameObject("tempTrn3").transform;
tempTrn2.rotation = toChngTrn.rotation;
tempTrn2.Rotate(rotatePivotVctr, deltaDegree, Space.Self);
tempTrn3.rotation = tempTrn2.rotation;
Vector3 tempTestPivot = Vector3.zero;
switch (matchPivot)
{
case PivotEnum.Right:
tempTestPivot = tempTrn3.right;
break;
case PivotEnum.Front:
tempTestPivot = tempTrn3.forward;
break;
case PivotEnum.Up:
tempTestPivot = tempTrn3.up;
break;
}
if (tempTestPivot == toReachVctr)
{
toChngTrn.rotation = tempTrn3.rotation;
GameObject.Destroy(tempTrn2.gameObject);
GameObject.Destroy(tempTrn3.gameObject);
return true;
}
else
{
//假如先顺时针旋转了一定角度, 逆时针旋转角度a还原成原先的样子
//再旋转角度a就可以了
tempTrn3.Rotate(rotatePivotVctr, -deltaDegree * 2, Space.Self);
if (tempTestPivot == toReachVctr)
{
toChngTrn.rotation = tempTrn3.rotation;
GameObject.Destroy(tempTrn2.gameObject);
GameObject.Destroy(tempTrn3.gameObject);
return true;
}
}
GameObject.Destroy(tempTrn2.gameObject);
GameObject.Destroy(tempTrn3.gameObject);
return false;
}