簡體   English   中英

Unity C#在圍繞移動軸旋轉的目標上射擊拋射物

[英]Unity C# Firing a projectile at a target rotating around moving axis

我正在開發一個3D太空游戲,其中相機處於恆定的2D(自上而下)狀態。 我能夠在以給定速度移動的目標上發射速度的射彈,並且每次擊中它。 大! 那么如果那個目標在父母身邊有一個角速度呢? 我注意到如果目標有一個旋轉的父對象,我的投影不正確,因為它沒有考慮角速度。

我的初始代碼是圍繞以下假設構建的:

Position_target + Velocity_target * t = Position_shooter + Velocity_shooter * t + Bulletspeed * t

我認為射手是靜止的(或可能是移動的)並需要發射一個恆定大小的子彈。

我將上述內容簡化為此

Delta_Position = Position_target - Position_shooter
Delta_Velocity = Velocity_target - Velocity_shooter

Delta_Position + Delta_Velocity * t = BulletSpeed * t

平方雙方我得到一個二次方程式,我可以求解給定的行列式結果或零。 這很完美。 我返回值,然后將目標的位置和當前速度投射到那個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)

從這里開始,我一直在不停地旋轉我的車輪,試圖找到一個可行的解決方案。 我正在使用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;

我可以根據這些角度計算物體的位置......但我正在努力將其轉化為可以與omega * t(角速度)方法一起使用的東西。

我想知道是否有一個更優雅的方法解決這個問題,或者是否有人可以指出我正確的方向指導我幫助我思考這個問題? Quaternions和EulerAngles我不是最好的,但我慢慢學習它們。 也許我能用那些聰明的東西做些什么?

雖然數學可能仍然很難,但我懷疑你可以通過讓“目標”計算其在當地空間的未來位置來大大簡化數學。 然后讓它將該位置調用其父級,讓它在本地空間中計算,依此類推,直到達到世界空間。 一旦你擁有了未來在世界空間中的位置,你就可以將你的炮塔對准那個目標。

例如,軌道船應該能夠輕松地計算其未來軌道。 這是橢圓的方程。 然后,可以將該本地位置發送到其父級(行星),該父級(行星)可能也在軌道運行,並相對於自身計算該位置。 然后行星將這個本地位置發送給它自己的父母(Star),依此類推。 直到你到達世界空間。

您可以通過使子彈的行程時間保持恆定(靈活的速度)來進一步簡化此數學運算,這樣您就可以簡化在特定時間確定未來的位置。 根據游戲規模的不同,速度的實際差異可能不同。

另一個想法:您可以及時“模擬”目標對象,而不是通過強力進行所有計算。 確保影響位置的所有代碼都可以與實際更新循環分開運行。 簡單地推進時鍾前進,並在不實際移動它的情況下查看其未來位置。 然后回到現在,將槍射向未來的位置。

我建議大約解決這個問題。
如果你可以用函數描述你的目標在一段時間內的位置f(t),那么你可以使用這樣的分而治之策略來近似它:

算法(偽代碼):
f(t:float):Vector3是計算目標在時間t的位置的函數
g(p:Vector3):float是一個計算子彈達到p需要多長時間的函數

float begin = 0    // Lower bound of bullet travel time to hit the target
float end = g(target.position)    // Upper bound

// Find an upper bound so that the bullet can hit the target between begin and end time
while g(f(end)) > end:
    begin = end
    end = end * 2    // Exponential growth for fast convergence
    // Add break condition in case the target can't be hit (faster than bullet)
end    

// Narrow down the possible aim target, doubling the precision in every step
for i = 1...[precision]:
    float center = begin + (end - begin) / 2
    float travelTime = g(f(center))

    if travelTime > center:    // Bullet can't reach target
        begin = center
    else    // Bullet overtook target
        end = center
    end
end

float finalTravelTime = begin + (end - begin) / 2
Vector3 aimPosition = f(finalTravelTime)    // You should aim here...

您需要嘗試[precision]的值。 它應該盡可能小,但足夠大,以便子彈始終擊中目標。
您還可以使用另一個中斷條件,例如限制絕對誤差(在finalTravelTime處子彈到目標的距離)。
如果目標的行進速度比子彈快,則需要在上限循環中添加中斷條件,否則它可能成為無限循環。

為什么這很有用:
不是計算復雜的相等函數來確定影響的時間,而是可以使用相當簡單的位置函數和此方法來近似它。
該算法獨立於實際位置函數,因此只要可以計算未來位置,就可以處理各種敵人的運動。

缺點:
此函數多次計算f(t),對於復數f(t),這可能是CPU密集型的。
此外,它只是一種近似值,結果的精度越高,行程時間越長。

注意:
我從頭頂編寫了這個算法。
我不保證偽代碼的正確性,但算法應該有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM