计算两个物体之间的倾斜角度

时间:2016-06-08 02:54:28

标签: vector unity3d

我有一架无人机跟随一条移动路径。也就是说,它不使用刚体,因此我无法获得速度或幅度等。它遵循路径就好了,但我想在向左或向右转时添加银行。我在无人机前面使用一个虚拟物体,以为我可以使用来自两个物体的变换矢量来计算倾斜/倾斜量。

由于我没有很多数学技能,因此我一直在研究这个问题。基本上我一直在复制代码试图让事情发挥作用。我没做什么工作来制造无人机银行。以下代码设法旋转(而不是银行)。

    // Update is called once per frame
void Update () {

    Quaternion rotation = Quaternion.identity;
    Vector3 dir = (dummyObject.transform.position - this.transform.position).normalized;
    float angle = Vector3.Angle( dir, transform.up );

    float rollAngle = CalculateRollAngle(angle);
    rotation.SetLookRotation(dir, transform.right);// + rollIntensity * smoothRoll * right);
    rotation *= Quaternion.Euler(new Vector3(0, 0, rollAngle));
    transform.rotation = rotation;
}

/// <summary>
/// Calculates Roll and smoothes it (to compensates for non C2 continuous control points algorithm) /// </summary>
/// <returns>The roll angle.</returns>
/// <param name="rollFactor">Roll factor.</param>
float CalculateRollAngle(float rollFactor)
{
    smoothRoll = Mathf.Lerp(smoothRoll, rollFactor, rollSmoothing * Time.deltaTime);
    float angle = Mathf.Atan2(1, smoothRoll * rollIntensity);
    angle *= Mathf.Rad2Deg;
    angle -= 90;

    TurnRollAngle = angle;

    angle += RollOffset;
    return angle;
}

1 个答案:

答案 0 :(得分:1)

假设您有无人机跟随的航路点,您应该计算出最后两个之间的角度(即您的“现在面向”和“将面向”方向)。简单的方法是使用Vector2.Angle 我会用这个角度来确定我将无人机的身体倾斜的数量:转弯越尖锐,银行越难。我会使用一个比率值(最初 public,所以我可以从编辑器中操作它) 接下来,我不依赖引擎为我做轮换 - 所以我会选择Transform.Rotate功能。
如果银行业务太高而且看起来很傻,我会设置最大值和Clamp我计算的归零角度在零和最大之间 如果不确切知道你做了什么以及如何做,那么提供完美的代码并不容易,但为了更好地理解上述内容,这里有一些(未经测试的,即伪的)代码,我想象的解决方案:

public float turnSpeed = 7.0f; //the drone will "rotate toward the new waypoint" by this speed

//bankSpeed+turnBankRatio must be two times "faster" (and/or smaller degree) than turning, see details in 'EDIT' as of why: public float bankSpeed = 14.0f; //banking speed public float turnBankRatio = .5f; //90 degree turn == 45 degree banking
private float turnAngle = 0.0f; //this is the 'x' degree turning angle we'll "Lerp" private float turnAngleABS = 0.0f; //same as turnAngle but it's an absolute value. Storing to avoid Mathf.Abs() in Update()! private float bankAngle = 0.0f; //banking degree private bool isTurning = false; //are we turning right now? //when the action is fired for the drone it should go for the next waypoint, call this guy private void TurningTrigger() { //remove this line after testing, it's some extra safety if (isTurning) { Debug.LogError("oups! must not be possible!"); return; } Vector2 droneOLD2DAngle = GetGO2DPos(transform.position); //do the code you do for the turning/rotation of drone here! //or use the next waypoint's .position as the new angle if you are OK //with the snippet doing the turning for you along with banking. then: Vector2 droneNEW2DAngle = GetGO2DPos(transform.position); turnAngle = Vector2.Angle(droneOLD2DAngle, droneNEW2DAngle); //turn degree turnAngleABS = Mathf.Abs(turnAngle); //avoiding Mathf.Abs() in Update() bankAngle = turnAngle * turnBankRatio; //bank angle //you can remove this after testing. This is to make sure banking can //do a full run before the drone hits the next waypoint! if ((turnAngle * turnSpeed) < (bankAngle * bankSpeed)) { Debug.LogError("Banking degree too high, or banking speed too low to complete maneuver!"); } //you can clamp or set turnAngle based on a min/max here isTurning = true; //all values were set, turning and banking can start! } //get 2D position of a GO (simplified) private Vector2 GetGO2DPos(Vector3 worldPos) { return new Vector2(worldPos.x, worldPos.z); } private void Update() { if (isTurning) { //assuming the drone is banking to the "side" and "side" only transform.Rotate(0, 0, bankAngle * time.deltaTime * bankSpeed, Space.Self); //banking //if the drone is facing the next waypoint already, set //isTurning to false } else if (turnAngleABS > 0.0f) { //reset back to original position (with same speed as above) //at least "normal speed" is a must, otherwise drone might hit the //next waypoint before the banking reset can finish! float bankAngle_delta = bankAngle * time.deltaTime * bankSpeed; transform.Rotate(0, 0, -1 * bankAngle_delta, Space.Self); turnAngleABS -= (bankAngle_delta > 0.0f) ? bankAngle_delta : -1 * bankAngle_delta; } //the banking was probably not set back to exactly 0, as time.deltaTime //is not a fixed value. if this happened and looks ugly, reset //drone's "z" to Quaternion.identity.z. if it also looks ugly, //you need to test if you don't """over bank""" in the above code //by comparing bankAngle_delta + 'calculated banking angle' against //the identity.z value, and reset bankAngle_delta if it's too high/low. //when you are done, your turning animation is over, so: }

同样,这段代码可能不完全符合您的需求(或编译:P),因此专注于想法和方法,而不是代码本身。很抱歉因为现在无法将某些东西放在一起并测试自己 - 但我希望我帮助过。干杯!



编辑:我试图用代码回答你的问题而不是文本墙(仍然不完美,但目标不是做这个工作,而是帮助一些片段和想法:)
所以。基本上,你拥有的是两个航路点之间的距离和“角度”。这个距离和无人机的飞行/步行/任何速度(我不知道)是最大可用时间:
1。转弯,所以无人机将面向新的方向
2. 银行到一边,然后回到零/“正常”
由于在银行方面的行动要多两倍,要么必须更快(bankSpeed),要么以更小的角度(turnBankRatio),或两者兼而有之,这取决于看起来不错和感觉真实的东西,你的偏好是什么,等等。所以它是100%主观的。如果无人机快速转向+银行并接近下一个航路点,或者做得很慢,如果有很多时间/距离则转动一点,并且只有在必要时才能快速行动,这也是你的号召。

截至isTurning
当无人机到达航路点并前往下一个 AND 变量到(转弯和)银行设置正确时,您将其设置为true。当你把它设置为假?这取决于你,但目标是在机动结束时这样做(这是第一次在片段中出现错误,因为无法达到这种“最佳状态”)所以无人机可以“重置银行业务”。
有关正在进行的操作的更多详细信息,请参阅代码注释。
同样,这只是一个代码段,可以为您提供可能的问题解决方案。给它一些时间,了解发生了什么。这真的很容易,你只需要一些时间来应对;)

希望这有帮助!享受和欢呼! :)