所以,我已经待了好几天了,由于项目进展缓慢,我做出了艰难的决定来乞求互联网。 我正在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);
}
基于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这显然是没有意义的,因为球会飞到高尔夫球手后面在短时间内。我将向您报告最终的数字和计算结果,尽管它不会回答可能有助于将其指向正确方向的问题。