Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 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 /
avatar image
1
Question by 8r3nd4n · Oct 24, 2011 at 12:36 PM · physicsvelocityangleprojectile

Projectile not firing right - simple angle and velocity problem?

Hi guys

I am having some trouble getting a projectile to fire how I am after. What I have is a crosshair that remains stationary in the center of the screen where the projectile will fire through (firePosition). By using the mouse, they can drag to an x,y point in the screen with a z position about 3 behind the crosshair (handPosition). Then when they fire, the projectile will go from the mouse position and through the crosshair using the 2 different positions to work out the angle of the shot.

 using UnityEngine;
 using System.Collections;

 public class ProjectileFire : MonoBehaviour {
 
 public float shootForce;
 public Transform target;
 Vector3 firePosition;
 Vector3 handPosition;
 public GameObject projectilePrefab;
 // Use this for initialization
 void Start () {
 
     firePosition = new Vector3(0,3,0);
 }
 
 // Update is called once per frame
 void Update () {
 
     transform.LookAt(target);
     
     if (Input.GetMouseButtonDown(0))
     {
         
     }
     
     if (Input.GetMouseButtonUp(0))
     {
             handPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x,Input.mousePosition.y,3.0f));
         Instantiate (projectilePrefab,handPosition,Quaternion.identity);
         projectilePrefab.rigidbody.AddForce(transform.forward * shootForce);
     }
 }

}

Any suggestions? Thanks

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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by aldonaletto · Oct 24, 2011 at 02:21 PM

There are some errors in the logic. You must get firePosition using ViewportToWorldPoint with (0.5, 0.5, hand distance + 3), and handPosition with (mouse pos X, mouse pos Y, hand distance), where hand distance is the distance from camera to hand (variable distFromCam added to the code to define this distance).
While the mouse button is pressed, calculate both, handPosition and firePosition, and when the mouse is released create and shoot the projectile - you must calculate the rotation to create the projectile in the shooting direction. Get a reference to the projectile instantiated and use it to add the shooting force in its forward direction:

... public GameObject projectilePrefab; public float distFromCam = 2.0f; // distance from camera to hand

void Update () {

 transform.LookAt(target);
 if (Input.GetMouseButton(0)) // aim while the mouse button is down
 {
      firePosition = Camera.main.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, distFromCam+3.0f)); // 3D point at screen center, 3 units ahead hand
      handPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, distFromCam));
      // draw a debug line just to see what's happening (click Gizmos to see the line)
      Debug.DrawLine(handPosition, firePosition, Color.green);
 }
 if (Input.GetMouseButtonUp(0)) // shoot in last aimed direction when button released
 { 
    Vector3 projDir = firePosition - handPosition; // calculate the projectile direction
    // calculate rotation to turn projectile's forward direction to the shooting direction
    Quaternion rot = Quaternion.FromToRotation(Vector3.forward, projDir);
    // create the projectile in a variable to access its rigidbody...
    GameObject projectile = Instantiate (projectilePrefab, handPosition, rot);
    // then add force in the projectile's forward direction
    projectile.rigidbody.AddForce(projectile.transform.forward * shootForce);
    Destroy(projectile, 10); // destroy projectile after 10 seconds
 }

}

EDITED: I think you can recycle the projectile forever: create the projectile only once, then bring it to the shooting position when firing again - but you must make the rigidbody forget about the past, or it will continue doing whatever it was doing before (rotating, moving to the old direction, etc.) I suppose it can be done by zeroing the rigidbody velocities.
This is the ecologically correct version of the script above - the projectile is created once and recycled each time you shoot:

... public GameObject projectilePrefab; public float distFromCam = 2.0f; // distance from camera to hand private GameObject projectile; // current projectile

void Update () {

 transform.LookAt(target);
 if (Input.GetMouseButton(0)) // aim while the mouse button is down
 {
      firePosition = Camera.main.ViewportToWorldPoint (new Vector3(0.5f, 0.5f, distFromCam+3.0f)); // 3D point at screen center, 3 units ahead hand
      handPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, distFromCam));
      // draw a debug line just to see what's happening (click Gizmos to see the line)
      Debug.DrawLine(handPosition, firePosition, Color.green);
 }
 if (Input.GetMouseButtonUp(0)) // shoot in last aimed direction when button released
 { 
    Vector3 projDir = firePosition - handPosition; // calculate the projectile direction
    // calculate rotation to turn projectile's forward direction to the shooting direction
    Quaternion rot = Quaternion.FromToRotation(Vector3.forward, projDir);
    // if projectile doesn't still exist, create it
    if (!projectile) projectile = Instantiate(projectilePrefab);
    // make sure the projectile is active:
    projectile.SetActiveRecursively(true);
    // bring it to the handPosition and set its rotation
    projectile.transform.position = handPosition;
    projectile.transform.rotation = rot;
    // make rigidbody forget the past by zeroing its velocities
    projectile.rigidbody.velocity = Vector3.zero;
    projectile.rigidbody.angularVelocity = Vector3.zero;       
    // then add force in the shooting direction
    projectile.rigidbody.AddForce(projDir * shootForce);
 }

} The projectile script usually have code to destroy the projectile when it hits something - for instance:

void OnCollisionEnter(Collision col){
    // do the usual projectile stuff - check what was hit, apply damage etc.
    // and finally destroy the projectile:
    Destroy(gameObject);
}
But if you are recycling the projectile, you must change the code to deactivate it instead:

void OnCollisionEnter(Collision col){
    // do the projectile stuff...
    // and deactivate the projectile:
    gameObject.SetActiveRecursively(false);
}
Comment
Add comment · 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
0

Answer by 8r3nd4n · Oct 25, 2011 at 01:00 AM

Thanks for the quick response, I had a feeling my logic was off but didnt know howso. ha.

I tried your script but the projectile is still not firing at the angle that the debug line is showing. It comes out of the point of the line (hand position) but does not take into consideration the angle I think. I have tried moving a lot of things around but its still not working as it should. Just so Im clear on things, the script should be attached to an empty gameObject? or should it be on the camera? on those, my empty GO projectile is at 0, 2.5, 0 and camera at 0, 3.2, -8.5 if that helps.

Comment
Add comment · Show 3 · 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 aldonaletto · Oct 25, 2011 at 12:22 PM 0
Share

You can add this script to the camera, or to an empty object.
The problem is an error in the last line - it uses transform.forward, but it should be projectile.transform.forward, like this:

 projectile.rigidbody.AddForce(projectile.transform.forward * shootForce);

I fixed the answer.
NOTE: An alternative - maybe a better one - would be to use projDir ins$$anonymous$$d:

 projectile.rigidbody.AddForce(projDir * shootForce);
avatar image 8r3nd4n · Oct 25, 2011 at 12:28 PM 0
Share

Thanks, I managed to get it all working right with some more playing around and by using projectile.rigidbody.AddRelativeForce(transform.forward * shootForce); ins$$anonymous$$d.

I do have another question relating to the script. Is it possible to use the same object over and over again without having to instantiate a prefab? Basically, the more clones that are on screen are starting to impact on performance and I want the player to only have the one projectile at a time to play with. I though about using transform.translate on the object whenever the mouse is clicked but it does not let me add the rotation values. Any suggestions? Thanks

avatar image aldonaletto · Oct 25, 2011 at 03:59 PM 0
Share

I edited my answer and included this projectile recycling idea. The usual way is to destroy the projectile after some time, or when it hits something. I included code to auto destroy the projectile in the Instantiate version too, and showed in the end how projectiles are destroyed when something is hit - in both versions.

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Projectile trajectory velocity and angle instead of force with a rigidbody 2 Answers

Projectile launch insufficient velocity 2 Answers

How to calculate the speed and direction to intercept with a target 1 Answer

how to get starting velocity of an object, which is thrown with a 45 degree angle and will pass some (x,y) point 0 Answers

Calculating a projectiles angle required to hit object. 2 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