यदि आप गणित करते हैं तो उत्तर वास्तव में बहुत आसान है। आपके पास Y की एक निश्चित दूरी और X की एक चर दूरी है (चित्र 1 देखें)। आपको जेड और एक्स के बीच के कोण का पता लगाने और अपने बुर्ज को और अधिक मोड़ने की आवश्यकता है।
चरण 1 - बुर्ज लाइन (वी) और बंदूक लाइन (डब्ल्यू) के बीच की दूरी प्राप्त करें जो वाई है (यह स्थिर है लेकिन गणना करने के लिए चोट नहीं करता है)। बुर्ज से लक्ष्य तक दूरी प्राप्त करें (जो कि X है)।
चरण 2 - वाई को एक्स से विभाजित करें और फिर मूल्य के हाइपरबोलेनिक साइन प्राप्त करें
double turnRadians = Mathf.Asin(Y/X);
double angle = Mathf.Rad2Deg * turnRadians;
//where B is the red dot, A is a point on the X line and C is a point on the Z line.
चरण 3 - बुर्ज को और अधिक मोड़ें (अक्ष के चारों ओर जो इसके ऊपर से नीचे तक जाता है, सबसे अधिक संभावना धुरी है लेकिन केवल आप उस हिस्से को जान सकते हैं)।
gameObject.transform.Rotate(Vector3.up, turnAngle);
बेशक, इस मामले में, आपको इसे वामावर्त चालू करने की आवश्यकता है, इसलिए आपको टर्नअंगल के सामने माइनस जोड़ने की आवश्यकता हो सकती है, जैसे कि अंदर -turnAngle
।
कुछ हिस्सों को संपादित किया। दूरी में अंतर को इंगित करने के लिए @ लेंस के लिए धन्यवाद।
ओपी ने कहा कि उनकी बंदूक में एक कोण है इसलिए हम यहां जाते हैं, पहले छवि, बाद में स्पष्टीकरण:
हम पिछली गणना से पहले से ही जानते हैं कि नीली रेखा के अनुसार लाल रेखा का लक्ष्य कहां है। तो पहले नीली रेखा के लिए लक्ष्य:
float turnAngle = angleBetweenTurretAndTarget - angleBetweenTurretAndGun;
turret.transform.Rotate(Vector3.up, turnAngle);
यहां जो एकमात्र गणना अलग है, वह "एक्स प्राइम" (एक्स ') की गणना है क्योंकि बंदूक और बुर्ज (कोण "ए") के बीच के कोण ने लाइनों के बीच की दूरी को बदल दिया है।
//(this part had a mistake of using previous code inside new variable names, YPrime and Y are shown as X' and X in the 2nd picture.
float YPrime = Cos(a)*Y; //this part is what @ens is doing in his answer
double turnRadians = Mathf.Asin(YPrime/X);
double angle = Mathf.Rad2Deg * turnRadians;
turret.transform.Rotate(Vector3.up, angle);
यदि आप बुर्ज बंदूकें मॉड्यूलर कर रहे हैं (यानी उपयोगकर्ता एक बुर्ज पर बंदूकें बदल सकते हैं और अलग-अलग कोणों में अलग-अलग कोण हैं) तो यह अगला भाग केवल आवश्यक है। यदि आप संपादक में ऐसा कर रहे हैं, तो आप पहले से ही देख सकते हैं कि बुर्ज के अनुसार बंदूक का कोण क्या है।
"ए" को खोजने के लिए दो विधियाँ हैं, एक है ट्रांसफॉर्म.अप विधि:
float angleBetween = Vector3.Angle(turret.transform.up, gun.transform.up);
उपरोक्त तकनीक 3 डी में गणना करेगी, इसलिए यदि आप एक 2 डी परिणाम चाहते हैं, तो आपको जेड अक्ष से छुटकारा पाने की आवश्यकता है (यह वही है जो मैं मानता हूं कि गुरुत्वाकर्षण कहां है, लेकिन यदि आपने कुछ भी नहीं बदला, तो एकता में यह वाई अक्ष है जो ऊपर या नीचे है) यानी गुरुत्वाकर्षण Y अक्ष पर है, इसलिए आपको चीजें बदलनी पड़ सकती हैं):
Vector2 turretVector = new Vector2(turret.transform.up.x, turret.transform.up.y);
Vector2 gunVector = new Vector2(gun.transform.up.x, gun.transform.up.y);
float angleBetween = Vector2.Angle(turretVector, gunVector);
दूसरा तरीका रोटेशन विधि है (मैं इस मामले में 2 डी में सोच रहा हूं):
double angleRadians = Mathf.Asin(turret.transform.rotation.z - gun.transform.rotation.z);
double angle = 2 * Mathf.Rad2Deg * angleRadians;
फिर से, ये सभी कोड आपको मान देंगे जो सकारात्मक हैं, इसलिए आपको कोण के आधार पर राशि को जोड़ना या घटाना हो सकता है (इसके लिए गणना भी होती है, लेकिन मैं उस गहराई में नहीं जा सकता हूं)। इस पर शुरू करने के लिए एक अच्छी जगह Vector2.Dot
एकता में विधि होगी ।
हम क्या कर रहे हैं, इसके अतिरिक्त विवरण के लिए कोड का अंतिम ब्लॉक:
//turn turret towards target
turretTransform.up = targetTransform.position - turretTransform.position;
//adjust for gun angle
if (weaponTransform.localEulerAngles.z <180) //if the value is over 180 it's actually a negative for us
turretTransform.Rotate(Vector3.forward, 90 - b - a);
else
turretTransform.Rotate(Vector3.forward, 90 - b + a);
यदि आपने सब कुछ सही किया है, तो आपको इस तरह का दृश्य मिलना चाहिए ( unitypackage के लिए लिंक ):
मुझे हमेशा सकारात्मक मूल्यों से क्या मतलब है:
Z विधि नकारात्मक मान दे सकती है:
एक उदाहरण के दृश्य के लिए, इस लिंक से एकता प्राप्त करें ।
यहाँ मैंने दृश्य में (बुर्ज पर) कोड का उपयोग किया है:
public class TurretAimCorrection : MonoBehaviour
{
public Transform targetTransform;
public Transform turretTransform;
public Transform weaponTransform;
private float f, d, x, y, h, b, a, weaponAngle, turnAngle;
private void Start()
{
TurnCorrection();
}
private void Update()
{
TurnCorrection();
}
void TurnCorrection()
{
//find distances and angles
d = Vector2.Distance(new Vector2(targetTransform.position.x, targetTransform.position.y), new Vector2(turretTransform.position.x, turretTransform.position.y));
x = Vector2.Distance(new Vector2(turretTransform.position.x, turretTransform.position.y), new Vector2(weaponTransform.position.x, weaponTransform.position.y));
weaponAngle = weaponTransform.localEulerAngles.z;
weaponAngle = weaponAngle * Mathf.Deg2Rad;
y = Mathf.Abs(Mathf.Cos(weaponAngle) * x);
b = Mathf.Rad2Deg * Mathf.Acos(y / d);
a = Mathf.Rad2Deg * Mathf.Acos(y / x);
//turn turret towards target
turretTransform.up = targetTransform.position - turretTransform.position;
//adjust for gun angle
if (weaponTransform.localEulerAngles.z < 180)
turretTransform.Rotate(Vector3.forward, 90 - b - a);
else
turretTransform.Rotate(Vector3.forward, 90 - b + a);
//Please leave this comment in the code. This code was made by
//http://gamedev.stackexchange.com/users/93538/john-hamilton a.k.a. CrazyIvanTR.
//This code is provided as is, with no guarantees. It has worked in local tests on Unity 5.5.0f3.
}
}
2 डी प्लेन के रूप में X और Z के साथ 3D अनुकूलित कोड:
public class TurretAimCorrection : MonoBehaviour
{
public Transform targetTransform; //drag target here
public Transform turretTransform; //drag turret base or turret top part here
public Transform weaponTransform; //drag the attached weapon here
private float d, x, y, b, a, weaponAngle, turnAngle;
private void Start()
{
TurnAdjustment();
}
private void Update()
{
TurnAdjustment();
}
void TurnAdjustment()
{
d = Vector2.Distance(new Vector2(targetTransform.position.x, targetTransform.position.z), new Vector2(turretTransform.position.x, turretTransform.position.z));
x = Vector2.Distance(new Vector2(turretTransform.position.x, turretTransform.position.z), new Vector2(weaponTransform.position.x, weaponTransform.position.z));
weaponAngle = weaponTransform.localEulerAngles.y;
weaponAngle = weaponAngle * Mathf.Deg2Rad;
y = Mathf.Abs(Mathf.Cos(weaponAngle) * x);
b = Mathf.Rad2Deg * Mathf.Acos(y / d);
a = Mathf.Rad2Deg * Mathf.Acos(y / x);
//turn turret towards target
turretTransform.forward = new Vector3(targetTransform.position.x, 0, targetTransform.position.z) - new Vector3(turretTransform.position.x, 0, turretTransform.position.z);
//adjust for gun angle
if (weaponTransform.localEulerAngles.y < 180)
turretTransform.Rotate(Vector3.up, - a +b-90);
else
turretTransform.Rotate(Vector3.up, + a+ b - 90);
//Please leave this comment in the code. This code was made by
//http://gamedev.stackexchange.com/users/93538/john-hamilton a.k.a. CrazyIvanTR.
//This code is provided as is, with no guarantees. It has worked in local tests on Unity 5.5.0f3.
}
}