Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by DanteOfAstora · Jan 23, 2020 at 11:22 AM · scripting problemphysicsshootingtrajectory

Calculate mortar parabolic trajectory knowing the shot angle but not velocity

The problem is that when I set the y position of the mortar to a different one to 0 the tajectories dont work. But it does work if the bullet I shoot has to impact on different altitudes.

I have two scripts Mortar Script:

 public class Projectile1: MonoBehaviour
 {
     // launch variables
     [Range(20.0f, 75.0f)] public float LaunchAngle;
     public float waitTime;
 
     public GameObject Bullet;
     public GameObject Canon;
     public GameObject Mark;
     
     // state
     private bool bTouchingGround;
     private bool Reloading = false;
 
     // cache
     public RaycastHit hit;
 
     //-----------------------------------------------------------------------------------------------
 
     // Use this for initialization
     void Start()
     {
         
     }
 
     // resets the projectile to its initial position
 
     // Update is called once per frame
     void Update()
     {
         if (Input.GetMouseButtonUp(0))
         {
             Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
             
 
             if (Physics.Raycast(ray, out hit, Mathf.Infinity))
             {
                 Debug.DrawLine(Camera.main.transform.position, hit.point, Color.red);
                 //Debug.Log(hit.transform.position.x);
                 if (hit.transform != null & Reloading == false)
                 {                                    
                     Instantiate(Mark, new Vector3(hit.point.x, hit.point.y+0.01f, hit.point.z), Quaternion.Euler(new Vector3(90,0,0)));
                     Instantiate(Bullet, Canon.transform.position, Quaternion.Euler(new Vector3(90, 0, 90)));
                     StartCoroutine(Reload(waitTime));
                 }
             }
             
         }
 
     }
     IEnumerator Reload(float waitTime)
     {
         Reloading = true;
         yield return new WaitForSeconds(waitTime);
         Reloading = false;
     }
    
 }

Bullet Script:

 public class Bullet: MonoBehaviour
 {
     Rigidbody rigid;
     public GameObject Mortar;
     private Quaternion initialRotation;
     
     // Start is called before the first frame update
     void Start()
     {
         Mortar = GameObject.FindGameObjectWithTag("Arma");
         
         //Debug.Log(Mortar.GetComponent<Projectile1>().hit.transform.position.x);
         rigid = GetComponent<Rigidbody>();
         initialRotation = transform.rotation;
         Launch(Mortar.GetComponent<Projectile1>().hit.point, Mortar.GetComponent<Projectile1>().LaunchAngle);
     }
 
     private void Update()
     {
         transform.rotation = Quaternion.LookRotation(rigid.velocity) * initialRotation;
     }
     void Launch(Vector3 hit, float LaunchAngle)
     {
         //GameObject Disparo = Instantiate(Bullet, Canon.transform.position, Quaternion.identity);
         
         // think of it as top-down view of vectors: 
         //   we don't care about the y-component(height) of the initial and target position.
         Vector3 projectileXZPos = new Vector3(transform.position.x, 0.0f, transform.position.z);
         Vector3 targetXZPos = new Vector3(hit.x, 0.0f, hit.z);
 
         // rotate the object to face the target
         transform.LookAt(targetXZPos);
 
         // shorthands for the formula
         float R = Vector3.Distance(projectileXZPos, targetXZPos);
         float G = Physics.gravity.y;
         float tanAlpha = Mathf.Tan(LaunchAngle * Mathf.Deg2Rad);
         float H = hit.y - transform.position.y;
         // calculate the local space components of the velocity 
         // required to land the projectile on the target object 
         float Vz = Mathf.Sqrt(G * R * R / (2.0f * (H - R * tanAlpha)));
         
         float Vy = tanAlpha * Vz;
 
         // create the velocity vector in local space and get it in global space
         Vector3 localVelocity = new Vector3(0f, Vy, Vz);
         Vector3 globalVelocity = transform.TransformDirection(localVelocity);
 
         // launch the object by setting its initial velocity and flipping its state
         rigid.velocity = globalVelocity;
         
     }
 
     private void OnTriggerEnter(Collider other)
     {
         if(other.tag == "Mark")
         {
             Destroy(other.gameObject);
             Destroy(this.gameObject);
         }
     }
 }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by lgarczyn · Jan 23, 2020 at 09:04 PM

A lot of code can be made a bit better

  Instantiate(Mark, new Vector3(hit.point.x, hit.point.y+0.01f, hit.point.z), Quaternion.Euler(new Vector3(90,0,0)));

can be

 Instantiate(Mark, hit.point + Vector3.up * 0.01f, Quaternion.Euler(-90, 0, 0));

You should also avoid using a rigidbody's transform, so

 transform.rotation = Quaternion.LookRotation(rigid.velocity) * initialRotation;

should be

 rigid.rotation = Quaternion.LookRotation(rigid.velocity) * initialRotation;


To avoid using FindObject, you can call Launch from the Mortar script:

 GameObject bulletGO = Instantiate(Bullet, Canon.transform.position, Quaternion.Euler(new Vector3(90, 0, 90)));
 bulletGO.GetComponent<Bullet>().Launch(hit.point + Vector3.up * 0.01f, LaunchAngle);

It's good to keep data transfer in one direction, usually from weapon to projectile


Now your math can be made a bit simpler. We know the shot direction, which can be calculated like so

 Vector3 xzdir = (hit - rigid.position);
 xzdir.y = 0f;

 Vector3 shotDir = Quaternion.LookRotation(xzDir) * Quaternion.AngleAxis(LaunchAngle, Vector3.right) * Vector3.forward;

But the velocity is a bit more complicated, I decided to figure out my own equation for fun. We know

 rigidbody.positon + shotDir * vel * time + Physics.gravity * time * time / 2 == hit;

or

 shotDir * vel * time - Physics.gravity * time * time / 2 == deltaPos

We can extract two equations:

 shotDir.y * vel * time + Physics.gravity.y * time * time / 2 == deltaPos.y
 shotDir.x * vel * time == deltaPos.x

Using the second, we can find the confusing

 vel * time == deltaPos.x / shotDir.x

And if we use it the first equation, we get

 shotDir.y * deltaPos.x / shotDir.x + Physics.gravity.y * time * time / 2 == deltaPos.y

After further refining, we get a negative a positive solution for time (we discard the negative)

 float time = Mathf.Sqrt((shotDir.y * deltaPos.x / shotDir.x - deltaPos.y) / -Physics.gravity.y * 2);

And by reversing the second equation we get:

  float vel = deltaPos.x / shotDir.x / time;


And thus the code

 void Launch(Vector3 hit, float LaunchAngle)
 {
         Vector3 deltaPos = hit - rigid.position;
         Vector3 xzDelta = deltaPos;
         xzDelta.y = 0f;
         Vector3 shotDir = Quaternion.LookRotation(xzDelta) * Quaternion.AngleAxis(-LaunchAngle, Vector3.right) * Vector3.forward;
 
         float time = Mathf.Sqrt((shotDir.y * deltaPos.x / shotDir.x - deltaPos.y) / -Physics.gravity.y * 2);
         float vel = deltaPos.x / shotDir.x / time;
 
         if (float.IsNaN(vel))
         {
             Debug.Log("Impossible Trajectory")
         }
         rigid.velocity = vel * shotDir;
 }
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image DanteOfAstora · Jan 24, 2020 at 07:36 AM 0
Share

First of all thanks for the help. Im gonna try to make the changes you recommend and lets see if it gets solved. Thanks again

avatar image DanteOfAstora · Jan 24, 2020 at 07:47 AM 0
Share

Dude Thanks so much it works!!!

Now Ive gotta understand why yours works and $$anonymous$$e doesnt. But thanks so much I was breaking my head trying to figure it out.

avatar image lgarczyn DanteOfAstora · Jan 24, 2020 at 10:16 PM 0
Share

Honestly, I'm not sure exactly how $$anonymous$$e works. The steps to get the formula make perfect sense, but the result is a bit absurd.

avatar image lgarczyn DanteOfAstora · Jan 29, 2020 at 02:18 AM 0
Share

Can you mark the question as solved?

avatar image lodendsg · Dec 08, 2021 at 11:08 PM 0
Share

Not sure why this should work

Your time calculation ignores the z axis The shot direction looks confusing ... wouldn't it be Auaternion.LookRotaiton(deltaPos) * Vecto3.Forward; ?

If this works at all it would only work when the target is along the X axis such as in 2D ... unless I have missed something here

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

342 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Swipe Power Limit in a ball 0 Answers

Is there a way to set the mass of a gameobject without using the Rigidbody component?? 2 Answers

Basic FPS help! 2 Answers

Projectile trajectory based on angle 0 Answers

Making a pivot focused game 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges