Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Instantiated Bullets Teleport When Shot

Discussion in '2D' started by xXREACHXx, Sep 16, 2022.

  1. xXREACHXx

    xXREACHXx

    Joined:
    Apr 15, 2020
    Posts:
    6
    I am stumped in trying to figure out what is causing this issue. After recording what it looks like and slowing the footage down, the bullet will seemingly teleport to a different position towards the mouse during the few frames right after it is instantiated. Both the ship and the bullet are dynamic rigidbodies that are propelled by the AddForce method (using impulse). Propelling the bullets using rigidbody2d.velocity didn't change this behavior. Making the bullets go slower also did not help in any way.

    In the editor and in the game this issue makes it look like two or three bullets are being shot during the single frame they are instantiated, but has no other issues in the remaining frames, however it doesn't really happen in the screen recording. Upon trying extrapolation on the bullets, they still teleported, just in a different direction. Without either interpolation or extrapolation it just looks like two or three bullets are being shot in parallel at the same time even though it is still only one bullet being instantiated and shot.

    Code for propelling the bullet:
    Code (CSharp):
    1.     public void setup(Vector3 shootDirection, Vector3 shipVelocity)
    2.     {
    3.         // convert shootDirection to an angle
    4.         shootDirection = shootDirection.normalized;
    5.         float angle = Mathf.Atan2(shootDirection.y, shootDirection.x) * Mathf.Rad2Deg;
    6.  
    7.         if (angle < 0) angle += 360;
    8.         transform.eulerAngles = new Vector3(0, 0, angle);
    9.         Rigidbody2D rb = GetComponent<Rigidbody2D>();
    10.         rb.AddForce(shootDirection * speed + shipVelocity, ForceMode2D.Impulse);
    11.         //rb.velocity = shootDirection * speed + shipVelocity;
    12.  
    13.         Destroy(gameObject, 5f);
    14.     }
    Code used to instantiate the bullet:
    Code (CSharp):
    1. private void shootLaser(Vector3 mousePosition, Vector3 shipVelocity)
    2.     {
    3.         // Only start shooting when mouse is within certain angle relative to sprite's rotation
    4.         shootDirection = (mousePosition - transform.position).normalized;
    5.         angle = Vector3.Angle(transform.up, shootDirection);
    6.  
    7.         if (angle <= fieldOfFire)
    8.         {// Alternating fire between left and right side
    9.             if (nextFire < Time.time && !leftFired)
    10.             {
    11.                 nextFire = Time.time + (coolDown * 2);
    12.                 shootDirection = (mousePosition - leftLaserSpawn.position).normalized;
    13.                
    14.                 bulletTransform = Instantiate(pfBlueLaser, leftLaserSpawn.position, Quaternion.identity);
    15.                 bulletTransform.GetComponent<Laser>().setup(shootDirection, shipVelocity);
    16.                 leftFired = true;
    17.             }
    18.  
    19.             else if (nextFire < Time.time && leftFired)
    20.             {
    21.                 nextFire = Time.time + (coolDown * 2);
    22.                 shootDirection = (mousePosition - rightLaserSpawn.position).normalized;
    23.  
    24.                 bulletTransform = Instantiate(pfBlueLaser, rightLaserSpawn.position, Quaternion.identity);
    25.                 bulletTransform.GetComponent<Laser>().setup(shootDirection, shipVelocity);
    26.                 leftFired = false;
    27.             }
    28.         }



    Any ideas would be appreciated.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,710
    Top video looks like your bullets are colliding with whatever is firing them.

    Use layers and the physics collision matrix to prevent this.

    You probably do not even want bullets colliding with each other either. Same solution.
     
  3. xXREACHXx

    xXREACHXx

    Joined:
    Apr 15, 2020
    Posts:
    6
    So I made a separate layer for the bullets and in the physics collision matrix set it not to collide with itself, then tried not colliding with anything, but it doesn't seem to have any effect. I tested spawning them far away from the ship in case they spawned inside of it or clipped it while spawning, but still no change. I also tried shooting the bullets without adding the ship's velocity without any luck. Switching them to kinematic and using rigidbody2d.velocity also didn't work.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,710
    Another issue is you are aligning them by shootDirection but then imparting force by shootDirection * speed + shipVelocity

    Is that the problem?

    You don't need to really impart force either: you can just set the
    .velocity
    directly... I prefer that since when I hear AddForce I think "I am shoving this" when really what you are doing is setting the velocity.

    Also you can remove the duplicate code for left / right fire pretty easily. :)

    It would go something like:

    Code (csharp):
    1. if (angle okay to fire)
    2. {
    3.    if (cooldown timer expired)
    4.    {
    5.       // toggle sides
    6.       leftSide = !leftSide;
    7.  
    8.       // presume right side
    9.       Vector3 launchPoint = rightLaserSpawn.position;
    10.       // except when left!
    11.       if (leftSide) launchPoint = leftLaserSpawn.position;
    12.  
    13.       // now all the standard launch code, but use launchPoint as a proxy for left / right above
    14.    }
    15. }
    Just say "no" to duplicate code.

    I also recommend NOT using Time.time for cooldowns. Just set it to nonzero when the gun is cooling and then count down Time.deltaTime until it gets at or below zero. It makes the numbers always 0 to X instead of ever-advancing.

    Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

    https://forum.unity.com/threads/fire-rate-issues.1026154/#post-6646297

    GunHeat (gunheat) spawning shooting rate of fire:

    https://forum.unity.com/threads/spawning-after-amount-of-time-without-spamming.1039618/#post-6729841
     
    DragonCoder likes this.
  5. xXREACHXx

    xXREACHXx

    Joined:
    Apr 15, 2020
    Posts:
    6
    Yea I kinda left the copy pasta because of this projectile issue, but I will definitely implement your code once I sort this issue out. What you said about using velocity makes sense, so I have switched to that.

    You made a good point about using shootDirection in the velocity calculation, so I replaced it with transform.right, but the behavior remained the same. I also tried moving the bullet propelling logic into an update function rather than setting the velocity once in response to an input event, but still nothing has changed. Just in case my duplicate code was doing bad things, I commented out one side from firing, but it still had the same effect.

    I printed out the rb.velocity of the bullet along with its magnitude, both of which seem normal.

    Maybe I have accidentally changed some physics setting somewhere down the line? I might try to replicate behavior this in a fresh project file.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    I would certainly change your 2D only methods to use Vector2 and not Vector3. Subtle issues can creep in when using Vector3 such as when nomalising. If you have anything in the Z component then it'll change the 2D vector you're interested in.

    Don't lazily just use Vector3 everywhere. Every single thing in 2D physics uses Vector2 but Unity itself will automagically convert to Vector2 which, whilst convenient, lets you shoot yourself in the foot.

    Also, for Physics, never write or read from the Transform when you've got a Rigidbody2D. It is the authority on the position and rotation. The Transform might be somewhere else, especially true when using interpolation or extrapolation. Don't fixate on Transform, fixate on Rigidbody2D.position and Rigidbody2D.rotation. Those are the bosses here. :)

    There's no physics setting that says, sort of work but change the angle. Don't worry about that.
     
    Kurt-Dekker likes this.
  7. xXREACHXx

    xXREACHXx

    Joined:
    Apr 15, 2020
    Posts:
    6
    Ok, so I switched all the vector3s to vector2s, and replaced everything using transforms with rigidbodies, (except for the transforms used to instantiate the bullet). Unfortunately it does not seem to have fixed the issue.

    Is it possible that when the bullets are instantiated, because they don't inherit the velocity of the ship, they fall behind in relation to the ship until their velocity is modified? Or is their velocity set almost instantaneously? When moving the ship at higher speeds it appeared to create a sort of delay before the bullets moved. I got a GIF of it here:
    https://imgur.com/a/AEUN0BD
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,507
    Only you can debug that. If you're asking does physics have some kind of arbitrary "delay" then the answer is no. Maybe you're not aware that physics runs in the FixedUpdate by default but are doing stuff per-frame and expecting that in the next frame that physics has run; it might not have because ... FixedUpdate.

    If you set a velocity on the body, then the next time the simulation runs, it'll be used. Same with any change.

    I will say that you should read what I said above about Transforms. They are not the authority on position. Don't set them, don't read them when you're dealing with physics. Do what I said above.
     
  9. xXREACHXx

    xXREACHXx

    Joined:
    Apr 15, 2020
    Posts:
    6
    Alright everyone, I figured out the issue. It was an easy fix that completely eluded my mind. The ship itself had interpolation enabled. Having no interpolation on both the ship and the bullets removes all the weirdness happening before. Thanks for all the advice, as I now have much cleaner code.
     
    Kurt-Dekker likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,710
    Nice work keeping after it... Hope you keep having fun and success in coding!
     
    xXREACHXx likes this.