Search Unity

SOLVED: 2D Set bullet behavior

Discussion in 'Scripting' started by Dennooo, Feb 12, 2016.

  1. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    88
    Hey there,
    I'am stuck with a very basic problem: I want to implement a turret that instantiates bullets that fly towards the direction of the mouse input (which works). The problem is, that I can't get my bullets to have the correct rotation (whenever I tried to set the bullets rotation, the movement direction went wrong).

    The Shoot function is attached to the turret and transfers the "directionToTarget" towards the bullet (which is controlled via the "BulletBehavior" script):

    Code (CSharp):
    1. public void Shoot{
    2.                     GameObject bullet = (GameObject)Instantiate(bullet, transform.position, Quaternion.identity);
    3.                     BulletBehavior bulletBehavior = bullet.GetComponent<BulletBehavior>();
    4.                     bulletBehavior.directionToTarget = (new Vector3(Input.mousePosition.x, Input.mousePosition.y , 0) - Camera.main.WorldToScreenPoint(new Vector2(transform.position.x, transform.position.y))).normalized;
    5. }
    In the BulletBehavior Script (which is attached to each bullet), I control the bullets movement like this:
    Code (CSharp):
    1.  void Update()
    2.     {
    3. gameObject.transform.Translate(directionToTarget.normalized * Time.deltaTime * speed);
    4.     }
    I tried a lot regarding the bullet behavior and Iam stuck with the following questions/problems:

    1. What is the best way to set the bullets rotation according to it's moving direction?
    2. Is the movement via transform.Translate inefficient in terms of performance?
    3. The bullets I used for testing are kinematic, but I also plan to use non-kinematic rigidbodies for different collision behavior (bouncing bullets). Does that change the answer of one of the above questions?

    Bonus Question: Since all my objects have a transform.position.z = 0, I wonder why the bullet shows a transform.position.z != 0 when it is flying. Whats the reason for that?
     
  2. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    Pretty damn sure its something to do with the way you are determining the directionToTarget. you are subtracting a screen position from a world position. Its pretty much asking objects from 2 different dimensions to interact.

    Although there probably are other methods, my preferred method is converting the mouse position from a screen point to a world point instead. That way the bullet moves towards the cursor even if the screen changes position. Of course the object would be moving towards the camera with such a setup, but for a 2D game re-setting the z position is, simply set the z of your direction vector to 0.

    so lets go through this method step by step

    Code (CSharp):
    1. //Step 1, convert your mouse cursor point to a world point, and //cache it as a variable for manipulation
    2. Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    3.  
    4. //Step 2, set the z position to 0
    5. mousePos.z = 0;
    6.  
    7. //Step 3, normalize it so that the vector will be of magnitude 1
    8. mousePos.Normalize();
    9. //OR
    10. mousePos = mousePos.normalized;
    There is an added step to do in the 1st line, but would be a good learning journey to figure it out yourself.

    I don't quite understand the reason for your strange mixing of kinematic for 1 type of bullet and non-kinematic for another. wouldn't have setting isGravity to false and setting the rigibody velocity have been an easier method?
     
    Dennooo likes this.
  3. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    88

    Hi Laperen,
    thank you for taking your time :)

    I applied your code and it already greatly helped me with my general (yet very limited) understanding of unity's functionality. I changed the code to the following:

    Code (CSharp):
    1. public void Shoot(){
    2. //Step 1, convert your mouse cursor point to a world point, and //cache it as a variable for manipulation
    3.             Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    4.  
    5.             //Step 2, set the z position to 0
    6.             mousePos.z = 0;
    7.  
    8.             //Step 3, normalize it so that the vector will be of magnitude 1
    9.              mousePos = mousePos.normalized;
    10.  
    11.             Vector3 directionToTarget = mousePos - transform.position;
    12.  
    13.              GameObject bullet = (GameObject)Instantiate(CurrentLevel.bullet, transform.position, Quaternion.identity);
    14.               BulletBehavior bulletBehavior = bullet.GetComponent<BulletBehavior>();
    15.                bulletBehavior.directionToTarget = directionToTarget;
    16. }
    This already fixed that bullets went in wrong directions, when the camera changed. It also fixed that the bullets transform.position.z was != 0. I must admit that I don't know whats missing at Step1 :) Why do you normalize the mousePos? I used to normalize the direction like this: (mousePos - transform.position).normalize. Sorry it might be very obvious but Iam fairly new :)

    For the mix of kinematic and non-kinematic bullets: This is due to my inexperience. Your solution makes way more sense. I consequently changed the bullet behavior to the following and made the bullets non-kinematic and disabled gravity:

    Code (CSharp):
    1. Rigidbody2D rb2d = GetComponent<Rigidbody2D>();
    2. rb2d.velocity = new Vector2(0, speed);
    Of course the bullets fly now "upwards". I changed the rotation of the bullet to have the correct facing via [under the assumption that I don't normalize the mousePos]:
    Code (CSharp):
    1. float angle = Mathf.Atan2(directionToTarget.y, directionToTarget.x) * Mathf.Rad2Deg - 90;
    2. transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    but the bullet still flies upwards. I thought that "upwards" (in terms of y-coordinates) is relative to the objects rotation. Do you have a fix for this?
     
  4. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    The way we are using vector2 is a representation of a point in 2d space. X represents the horizontal, and Y represents the vertical.

    The same is true for vector3 as a representation of a point in 3d space, with the additional Z which represents depth.

    Normalize basically makes a vector have a magnitude of 1. The advantage this gives you is that you can multiply the normalized vector by an float amount.

    With this line
    Code (CSharp):
    1. rb2b.velocity = new Vector2(0, speed);
    You have used the Vector2 as a velocity, and the rigidbody2d handles the rest. So with the result you observed, obviously the problem is that the velocity is wrong. There should not be a need for you to do any sort of trigonometry to do what you intend to do.

    Factoring in your response, it seems this solution does not fit your level of understanding in scripting, so i will introduce another solution.

    Apply the following to the rotation of your bullet
    Code (CSharp):
    1. Quaternion.LookRotation(Vector3.forward, mousePos);
    and then use this to apply velocity to the bullet rigidbody :
    Code (CSharp):
    1. rb2d.velocity = transform.up * bulletSpeed
     
    Dennooo likes this.
  5. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    88
    Thanks man! This solved my problems :)