Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Firing a bullet from a gun

Discussion in 'Scripting' started by DustyShinigami, Jun 26, 2019.

  1. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I know this has been asked countless times already, but I'm having difficulty managing this. I've tried following various suggestions/threads on the subject and even this tutorial...



    ...but I can't get it working properly. With that tutorial, the bullet/projectile doesn't even appear. If I use my Raycast to detect whether something has been hit, it ends up detecting/hitting the player instead. I've commented all of that out though and just used an OnTriggerEnter like from the tutorial, but it still doesn't show. I've been trying for hours with various ways and gotten no where. :-\

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class RayGun : MonoBehaviour
    6. {
    7.     public GameObject projectilePrefab;
    8.     public Transform projectileSpawn;
    9.     public float projectileSpeed = 30f;
    10.     public float lifeTime = 3f;
    11.  
    12.     void Start()
    13.     {
    14.        
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         if (Input.GetKeyDown(KeyCode.Space))
    20.         {
    21.             Fire();
    22.         }
    23.     }
    24.  
    25.     private void Fire()
    26.     {
    27.         GameObject projectile = Instantiate(projectilePrefab);
    28.         Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawn.parent.GetComponent<Collider>());
    29.         projectile.transform.position = projectileSpawn.position;
    30.         Vector3 rotation = projectile.transform.rotation.eulerAngles;
    31.         projectile.transform.rotation = Quaternion.Euler(rotation.x, transform.eulerAngles.y, rotation.z);
    32.         projectile.GetComponent<Rigidbody>().AddForce(projectileSpawn.forward * projectileSpeed, ForceMode.Impulse);
    33.         StartCoroutine("DestroyProjectile");
    34.     }
    35.  
    36.     private IEnumerator DestroyProjectile (GameObject projectile, float delay)
    37.     {
    38.         yield return new WaitForSeconds(delay);
    39.         Destroy(projectile);
    40.     }
    41. }
    42.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class HurtEnemy : MonoBehaviour
    6. {
    7.     public int damnageToGive = 10;
    8.     public float range;
    9.     public ParticleSystem projectileEffect;
    10.  
    11.     private void OnTriggerEnter(Collider other)
    12.     {
    13.         print("hit " + other.name + "!");
    14.         Destroy(gameObject);
    15.     }
    16.  
    17.     //Physics such as Raycasts are better within the FixedUpdate function as it runs in tandem with the physics
    18.     /*public void FixedUpdate()
    19.     {
    20.         projectileEffect.Play();
    21.         RaycastHit hit;
    22.         if(Physics.Raycast(transform.position, transform.forward, out hit, range))
    23.         {
    24.             Debug.Log(hit.transform.name);
    25.             EnemyController target = hit.transform.GetComponent<EnemyController>();
    26.             if(target != null)
    27.             {
    28.                 target.Damage(damnageToGive);
    29.             }
    30.         }
    31.     }*/
    32. }
    33.  
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,616
    Can you see the projectile in the Hierarchy panel, at least?
     
  3. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Yeah. But it isn't even hitting an enemy either.
     
  4. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    It looks like the projectile object is in the scene, and if I fire, though I can't see any bullets fire, something is still hitting the projectile that's there and destroying it.
     
  5. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I've even tried following this one. Same problem - no projectile. :(

     
  6. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    seems like you hit your own collider
    + you are making 3d right? not 2d...?
    p.s. i think your bullet is not parented to player so you don't ignore physics by saying .tranform.parent...
     
  7. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Yeah. Which is strange as this bit of code was supposed to prevent that from happening:

    Code (CSharp):
    1. Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawn.parent.GetComponent<Collider>());
    Then again, the parent is probably my gun and not the character. The gun is a child of one of my character's hands.
     
  8. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    i think your bullet is not parented to player so you don't ignore physics by saying projectileSpawn.parent.GetComponent<Collider>()
    I think insantiate just puts it into scene.. so it doesn't have parent
     
  9. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Though I need to avoid parenting my bullet to the player/gun. I did that before. I need it to fire independently as it doesn't work correctly when I try to use two animation layers and an avatar mask so I can shoot and walk at the same time.
     
  10. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    well yeah i think you should avoid that,
    but what you could try is, in bullet at:
    Code (CSharp):
    1. private void OnTriggerEnter(Collider other)
    2.     {
    3.         print("hit " + other.name + "!");
    4.         Destroy(gameObject);
    5.     }
    change to this
    Code (CSharp):
    1. private void OnTriggerEnter(Collider other)
    2.     {
    3.         if (other.gameObject.tag == "Player") {
    4.             return;
    5.         }
    6.         print("hit " + other.name + "!");
    7.         Destroy(gameObject);
    8.     }
    just for testing, and make player tagged Player
     
  11. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I've changed a lot of code around now that it's no longer hitting the player, but comes up with 'Object reference not set to an instance of an object' on the
    Code (CSharp):
    1. Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawn.parent.GetComponent<Collider>());
    line.
     
  12. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    is your projectileSpawn set up in inspector?
    you can see the setup in hiearchy right? so you can count the number of parent to get to player, because you said gun is child of hands which i presume are child of player so you should try
    Code (CSharp):
    1. Physics.IgnoreCollision(projectile.GetComponent<Collider>(), projectileSpawn.parent.parent.GetComponent<Collider>());
     
  13. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, so now, after trying that, the projectile is instantiating in the scene, but it's appearing outside. If I move it in the player's path, it gets destroyed and says 'hit Player'. Nor are they being destroyed via the Coroutine.
     
    Last edited: Jun 27, 2019
  14. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    outside of what? + i think the coroutine never worked, you could just write
    Destroy (projectile, 2f); instead of startcoroutine in fire method. this will destroy it after 2 seconds.
     
  15. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Outside of the scene/the camera's view. I've sorted it though - it was my original prefab's position. I've set up a new one. Okay, I'll give that a go. Usually I've had no problems with Coroutines, so it's strange how it wasn't being called.

    To be honest, I'm starting to think with the way my character, gun and animations are set up, I don't think any traditional method of firing a bullet is going to work. When Space is down, there's a slight delay before the fire animation plays. The gun object is set to inactive for the other animations, but is active in my Attack animation and it plays. But then it quickly deactivates after it's finished. With the delay and how it becomes active and inactive, it makes the projectiles appear in different places each time. The Raycast line I got showing when I had that set up made the line flicker in different places every frame.
     
  16. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    there is also this tut

    in which you dont spawn no bullets but just a little particle effect at hit point and it's instant over range, but of course you could add a setup that could depend on distance and give a slight delay and offset as wind or something and perhaps add some tracers at the barrel so it looks like its actually shooting projectiles...
     
  17. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Yeah, Brackey's tutorial was the first one I used. :) His tutorials have been very useful. I guess that's what I'll have to do in this case. Shame, as I would have liked to have figured out a good way of firing actual bullets/projectiles. How do other Unity devs manage when different animation states are played, such as attack? Are their weapons usually part of the firing animation? Or do they attach the weapon as a child to the character's hand and toggle it on/off?
     
  18. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    i never did something with shooting projectiles from firearms and animations so i don't know.
    but i think they stop the animation that is not "shoot" and just play "shoot" if thats what you mean
     
  19. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Well, thanks for your help anyway. :)
     
  20. Reedex

    Reedex

    Joined:
    Sep 20, 2016
    Posts:
    389
    is your game 3d first person?
     
  21. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,616
    Either way would work fine.

    If you want the bullet to fire off at a specific time in the animation, you can use an animation event
    https://docs.unity3d.com/Manual/animeditor-AnimationEvents.html

    Another super-simple way to accomplish this is to first simply figure out about how much time it takes to get to that point in the animation. When the player presses the shoot button and the shooting animation starts, use Invoke to delay the bullet fire by that much time. This could potentially look silly if the player were able to change animation states before the bullet fires, though
     
  22. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    It's a 2.5D platformer
     
  23. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    Okay, I'll bare that in mind. Someone did suggest Animation Events in another thread, though I've yet to figure those out properly. In the end, I haven't been able to successfully get the bullet to move to be able to use them though. I'll just have to settle with the illusion that something has been fired.
     
  24. DustyShinigami

    DustyShinigami

    Joined:
    Jan 5, 2018
    Posts:
    529
    I seem to be just going round and round in circles with this. So I've settled on just firing a raycast, but every time I try to re-position the weapon and the spawn point so the ray actually hits the enemies accurately, the repositioned weapon doesn't set when keyframed in the Animator. After much faffing about trying to get to the bottom of it, it turned out to be because of one of my Avatar Masks. Getting rid of that works, but then I'm no longer able to fire and walk at the same time. If I try to just have one Avatar Mask and set it either to the Base Layer (walking), or the Attack Layer (shooting), I either get no walking animation, no walking and shooting, or the weapon/raycast not positioned correctly.