Unity C#在围绕移动轴旋转的目标上射击抛射物

Chr*_*ris 6 c# physics projection kinematics unity-game-engine

我正在开发一个3D太空游戏,其中相机处于恒定的2D(自上而下)状态.我能够在以给定速度移动的目标上发射速度的射弹,并且每次击中它.大!那么如果那个目标在父母身边有一个角速度呢?我注意到如果目标有一个旋转的父对象,我的投影不正确,因为它没有考虑角速度.

我的初始代码是围绕以下假设构建的:

Position_target + Velocity_target * t = Position_shooter + Velocity_shooter * t + Bulletspeed * t
Run Code Online (Sandbox Code Playgroud)

我认为射手是静止的(或可能是移动的)并需要发射一个恒定大小的子弹.

我将上述内容简化为此

Delta_Position = Position_target - Position_shooter
Delta_Velocity = Velocity_target - Velocity_shooter

Delta_Position + Delta_Velocity * t = BulletSpeed * t
Run Code Online (Sandbox Code Playgroud)

平方双方我得到一个二次方程式,我可以求解给定的行列式结果或零.这很完美.我返回值,然后将目标的位置和当前速度投射到那个t,然后我有炮塔脚本,以给定的角速度朝着该点旋转.如果炮塔说它在所有轴上观察到的点在1%以内,它会以速度射击子弹,如果目标没有改变其航向或速度,它会100%命中.

我开始在我的船只/小行星上添加组件,这些组件是父对象的子项,就像连接到炮塔本身为目标的船只的炮塔.如果船围绕轴旋转(例如Y轴)并且炮塔不在x = 0且z = 0,则我的投影不再起作用.我认为使用r*sin(theta + omega*t)作为X位置的角速度分量和使用Z位置的r*cos(theta + omega*t)可以起作用.Theta是当前旋转(相对于世界坐标),omega是围绕y轴的eulerAngle旋转.

我很快就意识到这只适用于围绕y轴旋转,我不能将sin置于二次方程式中,因为我无法从中提取t因此我无法真正适当地投影.我尝试使用双曲线,但情况相同.我可以创建一个任意的t,假设t = 2,并计算对象在2秒内的位置.但我正在努力寻找一种方法来实现子弹速度投射.

Position_targetparent + Velocity_targetparent * t + [ANGULAR VELOCITY COMPONENT] = Position_shooter + Velocity_shooter * t + Bulletspeed * t

Delta_Position_X + Delta_Velocity_X * t + S * t = r * sin (theta + Omegay * t)
Delta_Position_Z + Delta_Velocity_Z * t + S * t = r * cos (theta + Omegay * t)
Run Code Online (Sandbox Code Playgroud)

从这里开始,我一直在不停地旋转我的车轮,试图找到一个可行的解决方案.我正在使用eulerAngle.y作为效果很好的欧米茄.最后,我只需要在空间中我需要射击的瞬间点,它是子弹速度和投影距离的乘积,然后我的炮塔瞄准脚本将照顾其余部分.

我一直在寻找基于父母位置(旋转中心)的球面坐标系

Vector3 deltaPosition = target.transform.position - target.transform.root.position;
r = deltaPosition .magnitude;
float theta = Mathf.Acos(deltaPosition.z / r);
float phi = Mathf.Atan2(deltaPosition.y,deltaPosition.x);

float xPos = r * Mathf.Sin(theta) * Mathf.Cos(phi)
float yPos = r * Mathf.Sin(theta) * Mathf.Sin(phi)
float zPos = r * Mathf.Cos(theta)

Vector3 currentRotation = transform.root.gameObject.transform.rotation.eulerAngles * Mathf.Deg2Rad;
Vector3 angularVelocity = transform.root.gameObject.GetComponent<Rigidbody>().angularVelocity;
Run Code Online (Sandbox Code Playgroud)

我可以根据这些角度计算物体的位置......但我正在努力将其转化为可以与omega*t(角速度)方法一起使用的东西.

我想知道是否有一个更优雅的方法解决这个问题,或者是否有人可以指出我正确的方向指导我帮助我思考这个问题?Quaternions和EulerAngles我不是最好的,但我慢慢学习它们.也许我能用那些聪明的东西做些什么?

Ada*_*m B 0

尽管数学可能仍然很困难,但我怀疑您可以通过让“目标”计算其在本地空间中的未来位置来大大简化数学。然后让它将该位置调用到其父级,在本地空间中计算它,依此类推,直到到达世界空间。一旦您确定了其在世界空间中的未来位置,您就可以将炮塔瞄准该目标。

例如,轨道飞船应该能够轻松计算其未来轨道。这是椭圆的方程。然后,它可以将该本地位置发送到其父(行星),该父(行星)可能也在轨道上运行并计算相对于自身的位置。然后,行星会将这个本地位置发送给它自己的父行星(恒星),依此类推。直到你到达世界空间。

您可以通过使子弹的行进时间恒定(灵活速度)来进一步简化这个数学计算,这样您就可以简化计算特定时间的未来位置。根据游戏的规模,速度的实际差异可能并没有那么不同。

另一个想法:您可以及时“模拟”目标对象,而不是通过蛮力进行所有计算。确保影响位置的所有代码都可以与实际更新循环分开运行。只需将时钟向前推进,即可看到其未来的位置,而无需实际移动它。然后回到现在,在未来的位置开枪。