Search Unity

Question Need some help. Simple shooter doesn't shoot straight from the barrel. How to fix this?

Discussion in 'Scripting' started by timvanderweijde, Jul 3, 2022.

  1. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    Hi everyone,

    It's driving me crazy. I created simple shooter "spaceship" with a barrel. When the spaceship stands still, the bullets are going in the perfect straight path from the barrel.

    But when the spaceship is moving and especially after turning, the bullets are leaving the barrel from an angle.

    I checked the position of the barrel, but it stays in place as a child of the spaceship.

    I included an animated gif to show the behavior and I included a simplified unity package with the assets.

    I really could use your help with this one. It really doesn't make any sense anymore....

    Many thanks!
    Tim van der Weijde

    ship2.gif
     

    Attached Files:

    Last edited: Jul 3, 2022
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Please post the spawning and movement code here. No one wants to download an entire project to analyze ~4 lines of code. Thanks.
     
  3. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    Hi @GroZZleR

    I will try to give the code as simple as possible. ~4 lines is not a lot. I'm also not 100% sure it's only a script error...

    Fire code:
    Code (CSharp):
    1. var gunBarrelPosition = gunBarrel.position;
    2.  
    3. GameObject newBullet = Instantiate(this.bullet, gunBarrelPosition, gunBarrel.rotation);
    4.  
    5. Vector3 shootDir = (gunBarrelPosition - transform.position).normalized;
    6. newBullet.GetComponent<Bullet>().Setup(shootDir);
    Bullet Setup:
    Code (CSharp):
    1. transform.eulerAngles = new Vector3(0, 0,Bullet.GetAngleFromVectorFloat(shootDir));
    Bullet Update:
    Code (CSharp):
    1. transform.position += _shootDir * (moveSpeed * Time.deltaTime);
    MovePlayer code:
    Code (CSharp):
    1. _rigidbody.AddForce(transform.up * trustSpeedForward);
    RotatePlayer code:
    Code (CSharp):
    1. _rigidbody.AddTorque(_turnDirection * turnSpeed)
    Is this enough?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Time to debug!

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    You must find a way to get the information you need in order to reason about what the problem is.
     
    timvanderweijde likes this.
  5. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Code (csharp):
    1. Vector3 shootDir = (gunBarrelPosition - transform.position).normalized;
    I find this a bit "odd". I think the shootDir should be defined by the forward of the barrel gameobject. When you do it the way it is it shoots from the spaceship towards the barrel and when they are not "in line" (meaning the barrel exactly in front of the ship) it shoots somewhere to the side and potentially up/downwards. Just try wether the behavior changes when you move the barrel more to the side. This would be my guess but its hard to see your setup. Maybe show a screenshot of your ship.

    Some hints for future gifs: reduce the speed and make things larger. It's hard to see and deduce anything from your gif. But maybe it's only age making my eyes bad ;).
     
    Kurt-Dekker and timvanderweijde like this.
  6. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    Hi @exiguous

    Thanks for the feedback. The barrel is indeed in front of the ship and with this code I tried to force a direction. What would be a better way?

    This is ship by the way.
    Ship.png

    I will try to update the gif, not sure how to reduce the speed, but It will be a nice exercise. :)
    (edit: And done, slower and bigger animated gif)
     
    Last edited: Jul 3, 2022
  7. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    Thanks @Kurt-Dekker

    I already tried a lot of debuggen. I'm no stranger to that.
    The problem is still, even in de log statements, the positions and shooting directing seems correct.
     
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Why not shoot the bullets from the tip of the barrel?
     
  9. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    446
    Your code is fine I guess, the problem comes probably from your sprites origins. They are probably offsetted from the center. Since the sprites weren't included in the unity package, I just set some sprites where the origin was in the center and everything worked as expected :). With wrong origins of the sprites everything looked wrong even though it wasn't :). Hope this helps.
     
    timvanderweijde and GroZZleR like this.
  10. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    I can move the offset yes, I just did not get to that yet. But it won't change the behavior.
     
  11. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    Hi @Kreshi, are you sure it worked? There aren't any sprites, only the default sprites (hexagon and square)

    I looked at the child position and changed the local position, but it looks alright. Still the behavior exists.

    Can you share an export of a unitypackages with a working example? See what I missed maybe?
     
  12. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    It very well might. As it is, the bullets are spawning inside the ship, which is often rotating, so the ship is no longer aligned with the bullet's direction of travel by the time it reaches the end of the barrel.

    It looks like something else is going on as well, though.

    Are you sure that GetAngleFromVectorFloat is giving you correct values? But also, I'd avoid going via euler angles and doing extra math myself in the first place. eulerAngles are a wrapper around the rotation quaternion, and Unity has a method to give you a quaternion for a given direction:
    Code (csharp):
    1. transform.rotation = Quaternion.SetLookRotation(shootDir, yourUpDirection);
     
  13. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    I think changing the bullet's sprite from a dot to something like an arrow would help you in better visualizing what is likely happening here, at least for debugging. if my guess is correct if you did replace just the sprite you likely see that the sprite is pointing in the right direction you want it to travel but is moving at an angle from this correct direction.

    since you are spawning the bullet with the barrels rotation
    Code (CSharp):
    1. GameObject newBullet = Instantiate(this.bullet, gunBarrelPosition, gunBarrel.rotation);
    I would remove the code that is changing the rotation of the bullet via the eulerangles. Its actually superfluous. You don't need a shooting direction, since its already inferred by the gunBarrel.rotation. Thus, your shooting direction would most likely be bullet.transform.up (it depends on which axis the barrel sprite is pointing to at default rotation I assume its up).
    Code (CSharp):
    1. transform.position += transform.up * (moveSpeed * Time.deltaTime);
     
    mopthrow likes this.
  14. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    446
    Here is the zipped project file: https://drive.google.com/file/d/1jsu_1O_4isxt-BUqJsmVLFfJc6nC0GCu/view?usp=sharing
    I made a couple of changes to the code though - especially the bullet. You can swap between FixedUpdate, Update and LateUpdate now (positions can be set in FixedUpdate and interpolated in Update/LateUpdate).

    While evaluating your previous results and the results of the above project, please take into consideration that if you move with some kind of sideways acceleration and torque, it will always feel like the bullets are somehow off because they were instantiated on a previous position with a previous direction in comparison to the ships current position and direction. Therefore while moving the ship and continously shooting bullets, some kind of offset from ship to instantiated bullets is the expected behaviour.

    I also implemented a version where you can force the direction to "hold" onto the ships direction for a given time duration but this doesn't really improve it visually so I didn't include in the above project (this only leads to basically the same effect but delayed).

    Remember: the moment the ship lets go of a bullet, the bullet is going to move in a different direction from the ship because the ship moves sideways while the bullet moves in the direction of the ships up axis.
     
    Last edited: Jul 4, 2022
    exiguous likes this.
  15. Kreshi

    Kreshi

    Joined:
    Jan 12, 2015
    Posts:
    446
    I also added angularDrag and drag in the above example. If you increase angularDrag from 1.0 to something like 2.5, it is going to counteract the off-looking-like behaviour as well.
    You can counteract the effect additionally by adding this to the end of your FixedUpdate:

    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         _rigidbody.drag = drag;
    4.         _rigidbody.angularDrag = angularDrag;
    5.         MovePlayer();
    6.         RotatePlayer();
    7.         _rigidbody.velocity = Vector2.Lerp(_rigidbody.velocity, transform.up * _rigidbody.velocity.magnitude, Time.deltaTime * forceVelocityToForwardDirectionSpeed);
    8.     }
    forceVelocityToForwardDirectionSpeed is a SerializeField. I got good result with a value of 5.0.
    All changes have a side-effects to the ships physics so keep that in mind please.
     
  16. timvanderweijde

    timvanderweijde

    Joined:
    Jun 21, 2014
    Posts:
    8
    @Kreshi So many thanks for helping me out!

    I guess there is always a visual effect because of all those movements. Even when I set the forceVelocityToForwardDirectionSpeed to 5.0, it still looks funny.
    Especially when the ship speed is fast and doing a turn/torque.

    I will try thinks out trying to get it working. I didn't expect something like this would be that hard. It was a simple idea...

    Many thanks again!
     
    Kreshi likes this.