在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;
}