通过马格努斯效应计算行进一定距离所需的角速度

时间:2018-11-10 23:59:48

标签: c# unity3d physics trigonometry

所以,我已经待了好几天了,由于项目进展缓慢,我做出了艰难的决定来乞求互联网。 我正在Unity中从事基于物理学的高尔夫游戏,并且正在实现Magnus效果。这是我根据扭矩计算出的切向力:

    void FixedUpdate()
        {
            float _BallRadius = .0427f;
            float _halfmass = Mathf.Sqrt(_BallRadius*.5f );
            float _vv = new Vector3(GetComponent<Rigidbody>().velocity.x, 0, 
            GetComponent<Rigidbody>().velocity.z).magnitude;
            //MAGNUS FORMULA (SIDESPIN ONLY)//
            float _mag = -((1.429f * Mathf.Abs(_vv)* (2 * Mathf.PI * _halfmass * 
            GetComponent<Rigidbody>().angularVelocity.y))) * (_BallRadius * .5f);
            Vector3 _xmagdir = new Vector3(GetComponent<Rigidbody>().velocity.x, 0, GetComponent<Rigidbody>().velocity.z);     
GetComponent<Rigidbody().AddForce(Vector3.Cross(_xmagdir.normalized,Vector3.up)*_mag, ForceMode.Acceleration);
        }

这已经足够好了,但是现在我需要找出正确的数量来使球达到这个结果: Diagram of Desired Curve

我尝试了几种不同的方法,得出的结论主要是三角学。这是我目前所在的位置(在将切线方向应用于最终速度矢量之前):

Vector3 GetMagnusTorque(float Distance, Vector3 V_BallForce, float xdir)
{
    float _BallRadius = .0427f;
    float _halfmass = Mathf.Sqrt(_BallRadius*.5f);
    Vector3 v = GO_Camera.transform.InverseTransformDirection(V_BallForce);
    float HorizontalRange = Distance;
    //THIS IS THE LATERAL DISTANCE WE NEED TO TRAVEL//
    float opposite = (Mathf.Abs(Mathf.Tan(Mathf.Deg2Rad * xdir))) * (HorizontalRange*.5f);
    //THIS IS THE TIME IT WILL NEED TO TAKE//
    float time = ((2 * v.magnitude * Mathf.Sin((2 * (v.normalized.y )))) / -Physics.gravity.y);
    //THIS IS THE SPEED THE MAGNUS EFFECT WILL NEED TO PRODUCE//
    float linearSpeed =Mathf.Abs((opposite/time))*Mathf.Sign(xdir)Mathf.Abs((opposite/time))*Mathf.Sign(xdir)*(Time.timeScale+Time.fixedDeltaTime);
    return GO_Camera.transform.TransformDirection((((linearSpeed /( 2 * Mathf.PI * _halfmass * (_BallRadius * .5f))) / 1.429f))*Mathf.Deg2Rad*GO_PGolfBall.transform.up);
}

Logic behind this

基于xdir和V_BallForce的结果非常不一致,有时会走得更远,有时几乎没有。发现我对数学很不好时,这是一次非常清醒的冒险。 如果有人对此问题有任何建议,我将永远背负着您的债。

更新:以下是该问题的一些可视化: visualization

更新:我认为我应该包括从中调用GetMagnusTorque函数的代码示例,以便将内容更好地放在上下文中:

 void BallApplyForce()
    {
        //_rmult is a [0,1] value that is dependent on the accuracy of the player's swing//
        float _rmult = GetRMult();
        //GETS BALL READY BY ENABLING PHYSICS AND SETTING ITS ROTATION TO THE CAMERA//
        GO_PGolfBall.transform.rotation = new Quaternion(0, GO_Camera.transform.rotation.y, GO_Camera.transform.rotation.z, GO_Camera.transform.rotation.w);
        GO_PGolfBall.GetComponent<SCR_GOLFBALLCONTROL>().B_PhysicsActive = true;
        //YDIR = PITCH, XDIR = YAW. V_ContactPoint is a [-1,1] Vector2 used similar to Mario Golf//
        Vector3 _vdir = Vector3.zero;
        float ydir = ((Mathf.Rad2Deg * DIC_Clubs[I_CurrentClub].LandAngle) + (-2.5f * (.1f) * (DIC_Clubs[I_CurrentClub].LoftAngle * Mathf.Rad2Deg)));
        float _xdir = Mathf.Rad2Deg * (-(V_ContactPoint.x) * (DIC_Clubs[I_CurrentClub].LoftAngle)*3f);

        _vdir.y = ydir;
        _vdir = _vdir.normalized;
        _vdir.y *= Mathf.Rad2Deg;

        //MAX DISTANCE OF THE CLUB BEING USED TO METERS//
        float _dist = ((DIC_Clubs[I_CurrentClub].MaxDistance * F_UPower) * _rmult) * .9144f;

        //GET FORWARD AND UPWARDS VELOCITIES BASED ON THE DISTANCE GIVEN, XDIR ISN'T FACTORED FOR NOW//
        float Vi = Mathf.Sqrt(_dist * -Physics.gravity.y / (Mathf.Sin(Mathf.Deg2Rad * _vdir.y * 2)));
        float Vy, Vz;
        Vy = Vi * Mathf.Sin(Mathf.Deg2Rad*_vdir.y);
        Vz = Vi * Mathf.Cos(Mathf.Deg2Rad*_vdir.y);
        GO_Camera.transform.eulerAngles = new Vector3(0, GO_Camera.transform.eulerAngles.y, 0);
        Vector3 _velo = GO_Camera.transform.TransformVector(new Vector3(0f, Vy, Vz));

        //CALCULATE VERTICAL ANGULAR VELOCITY, THIS DOESNT NEED TO FOLLOW ANY SORT OF PATTERN FOR NOW//
        float _verRoll = Mathf.Sign(V_ContactPoint.y - .1f) * ((.7135f) * _dist) * Mathf.Sin(DIC_Clubs[I_CurrentClub].LoftAngle +
            ((Mathf.Abs(V_ContactPoint.y + .1f)) * (DIC_Clubs[I_CurrentClub].LaunchAngle))) * 60 * Mathf.Deg2Rad;
        GO_PGolfBall.GetComponent<Rigidbody>().AddTorque(Vector3.Scale(GO_PGolfBall.transform.right, new Vector3(1, 0, 0)) * _verRoll, ForceMode.VelocityChange);
        //CALCULATE HORIZONTAL ANGULAR VELOCITY//
        Debug.Log("MAGNUS CALC:" + GetMagnusTorque(_dist, _velo, _xdir));
        GO_PGolfBall.GetComponent<Rigidbody>().AddTorque(GetMagnusTorque(_dist, _velo, _xdir), ForceMode.VelocityChange);

        //APPLY XDIR TO THE CAMERA ANGLE AND RECALCULATE VELOCITY//
        GO_Camera.transform.eulerAngles = new Vector3(0, GO_Camera.transform.eulerAngles.y+_xdir, 0);
        _velo = GO_Camera.transform.TransformVector(new Vector3(0f, Vy, Vz));

        //APPLY VELOCITY//
        GO_PGolfBall.transform.GetComponent<Rigidbody>().AddForce(_velo, ForceMode.VelocityChange);
    }

更新11/21:我目前正在通过反复试验来伪造它。但是对于仍然对解决这种异常感兴趣的人,我可能会发现我如何计算将侧旋衍生力应用于球的方向的问题。用最大距离为70码且杆面倾角为60度的球杆楔击球,所需的曲线如下所示:Lob Wedge这显然是没有意义的,因为球会飞到高尔夫球手后面在短时间内。我将向您报告最终的数字和计算结果,尽管它不会回答可能有助于将其指向正确方向的问题。

0 个答案:

没有答案