0
\$\begingroup\$

So for my game you have to hold down right mouse click to aim and then simultaneously click the left mouse click to shoot. When the gun is fired, I'd like the gunfire sound to play. Currently, I have this working, but I have a problem. When I let go of the aim button, the gunfire sound immediately stops playing (if it hasn't already played through).

I understand this is happening because of the placement of my PlayShootSound method call, but what I can't figure out is where to put it so that I don't have this problem.

Any pointers/ideas?

public class Weapon : MonoBehaviour {

 public float fireRate = 0;
 public float damage = 10;
 public LayerMask whatToHit;

 public Transform BulletTrailPrefab;
 public Transform MuzzleFlashPrefab;

 float timeToFire = 0;
 float timeToSpawnEffect = 0;
 public float effectSpawnRate = 10;
 Transform firePoint;

 public AudioClip shootSound;
 private AudioSource gunFire;

 bool isShooting = false;

 // Use this for initialization
 void Awake () {
     gunFire = GetComponent<AudioSource>();

     firePoint = transform.Find("FirePoint");
     if (firePoint == null)
     {
         Debug.LogError("No fire point...Please make an empty object named FirePoint and attach to end of gun. :)");
     }
 }
 void Update () {
     CheckIfShooting();
 }

 void CheckIfShooting()
 {
     if (Input.GetButton("Fire2")) // Holding right click
     {
         if (fireRate == 0)
         {
             print("fire rate is 0");
             if (Input.GetButtonDown("Fire1")) // Left click while holding right click
             {
                 Shoot();
                 PlayShootSound();
             }
         }
         else
         {
             if (Input.GetButton("Fire1") && Time.time > timeToFire) // For automatic guns
             {
                 timeToFire = Time.time + 1 / fireRate;
                 Shoot();
                 PlayShootSound();
             }
         }
     }
 }

 void Shoot()
 {
     Vector2 mousePosition = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
     Vector2 firePointPosition = new Vector2(firePoint.position.x, firePoint.position.y);
     RaycastHit2D hit = Physics2D.Raycast(firePointPosition, mousePosition - firePointPosition, 100f, whatToHit);


     if (Time.time >= timeToSpawnEffect)
     {
         Effect();
         timeToSpawnEffect = Time.time + 1 / effectSpawnRate;
     }
     // Debug.DrawLine(firePointPosition, (mousePosition - firePointPosition) * 100, Color.cyan);

     if (hit.collider != null)
     {
         // Debug.DrawLine(firePointPosition, hit.point, Color.red);
         Debug.Log("We hit " + hit.collider.name + " and did " + damage + " damage.");
     }
 }

 void PlayShootSound()
 {
     gunFire.PlayOneShot(shootSound, 1f);
 }

 void Effect()
 {
     Instantiate(BulletTrailPrefab, firePoint.position, firePoint.rotation); // Fire Bullet

     Transform muzzleFlashClone = Instantiate(MuzzleFlashPrefab, firePoint.position, firePoint.rotation) as Transform;
     muzzleFlashClone.parent = firePoint;
     float size = UnityEngine.Random.Range(6f, 9f); // Randomize size of muzzle flash
     muzzleFlashClone.localScale = new Vector3(size, size, size);
     Destroy(muzzleFlashClone.gameObject, 0.05f);
 }
\$\endgroup\$
1

2 Answers 2

0
\$\begingroup\$

In my own game I've put all Gun oriented logic inside of a Gun class (with derived classes representing different guns.)

I'd probably refactor this so you do a "gun.Shoot()" and then inside of gun.Shoot() you'd have something like:

public Shoot()
{
     // logic for firerate
     // logic for creating/firing a bullet

     this.PlayShootSound()
}

Depending if that's still buggy; you may go crazy and wrap it in a Task. Tasks are managed Threads from a Thread pool that are automatically assigned when needed so then you might do:

var task = new Task(() =>
    {
        this.PlayShootSound();
    }
task.Start();

Hopefully that's overkill and not necessary.

EDIT: I think you should try the above. It should be nigh guaranteed to work if you use a task;

\$\endgroup\$
8
  • \$\begingroup\$ PlayShootSound is included in the code example in the question. \$\endgroup\$
    – DMGregory
    Commented Jun 16, 2018 at 18:05
  • \$\begingroup\$ Yes indeedy, PlayShootSound() is just below Shoot() :) \$\endgroup\$ Commented Jun 16, 2018 at 18:50
  • \$\begingroup\$ @DMGregory (Can't figured out how to tag Jay) I meant PlayOneShot(). I'll edit the answer \$\endgroup\$
    – blurry
    Commented Jun 16, 2018 at 23:28
  • 1
    \$\begingroup\$ PlayOneShot is part of the Unity API. You can read up on it in the Unity documentation if you're curious. \$\endgroup\$
    – DMGregory
    Commented Jun 16, 2018 at 23:29
  • \$\begingroup\$ I'm not sure how to incorporate Task(), I tried it earlier and Unity doesn't seem recognize that method. :( \$\endgroup\$ Commented Jun 17, 2018 at 0:17
0
\$\begingroup\$

Thank you everyone for helping, but I found the answer finally!!!

I followed this tutorial on how to create an audio manager and call sounds through it...and now my problem is fixed. :)

https://www.youtube.com/watch?v=HhFKtiRd0qI

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .