using UnityEngine; namespace BigRookGames.Weapons { public class GunfireController : MonoBehaviour { // --- Audio --- public AudioClip GunShotClip; public AudioSource source; public Vector2 audioPitch = new Vector2(.9f, 1.1f); // --- Muzzle --- public GameObject muzzlePrefab; public GameObject muzzlePosition; // --- Config --- public bool autoFire; public float shotDelay = .5f; public bool rotate = true; public float rotationSpeed = .25f; // --- Options --- public GameObject scope; public bool scopeActive = true; private bool lastScopeState; // --- Projectile --- [Tooltip("The projectile gameobject to instantiate each time the weapon is fired.")] public GameObject projectilePrefab; [Tooltip("Sometimes a mesh will want to be disabled on fire. For example: when a rocket is fired, we instantiate a new rocket, and disable" + " the visible rocket attached to the rocket launcher")] public GameObject projectileToDisableOnFire; // --- Timing --- [SerializeField] private float timeLastFired; private void Start() { if(source != null) source.clip = GunShotClip; timeLastFired = 0; lastScopeState = scopeActive; } private void Update() { // --- If rotate is set to true, rotate the weapon in scene --- if (rotate) { transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y + rotationSpeed, transform.localEulerAngles.z); } // --- Fires the weapon if the delay time period has passed since the last shot --- if (autoFire && ((timeLastFired + shotDelay) <= Time.time)) { FireWeapon(); } // --- Toggle scope based on public variable value --- if(scope && lastScopeState != scopeActive) { lastScopeState = scopeActive; scope.SetActive(scopeActive); } } /// /// Creates an instance of the muzzle flash. /// Also creates an instance of the audioSource so that multiple shots are not overlapped on the same audio source. /// Insert projectile code in this function. /// public void FireWeapon() { // --- Keep track of when the weapon is being fired --- timeLastFired = Time.time; // --- Spawn muzzle flash --- var flash = Instantiate(muzzlePrefab, muzzlePosition.transform); // --- Shoot Projectile Object --- if (projectilePrefab != null) { GameObject newProjectile = Instantiate(projectilePrefab, muzzlePosition.transform.position, muzzlePosition.transform.rotation, transform); } // --- Disable any gameobjects, if needed --- if (projectileToDisableOnFire != null) { projectileToDisableOnFire.SetActive(false); Invoke("ReEnableDisabledProjectile", 3); } // --- Handle Audio --- if (source != null) { // --- Sometimes the source is not attached to the weapon for easy instantiation on quick firing weapons like machineguns, // so that each shot gets its own audio source, but sometimes it's fine to use just 1 source. We don't want to instantiate // the parent gameobject or the program will get stuck in a loop, so we check to see if the source is a child object --- if(source.transform.IsChildOf(transform)) { source.Play(); } else { // --- Instantiate prefab for audio, delete after a few seconds --- AudioSource newAS = Instantiate(source); if ((newAS = Instantiate(source)) != null && newAS.outputAudioMixerGroup != null && newAS.outputAudioMixerGroup.audioMixer != null) { // --- Change pitch to give variation to repeated shots --- newAS.outputAudioMixerGroup.audioMixer.SetFloat("Pitch", Random.Range(audioPitch.x, audioPitch.y)); newAS.pitch = Random.Range(audioPitch.x, audioPitch.y); // --- Play the gunshot sound --- newAS.PlayOneShot(GunShotClip); // --- Remove after a few seconds. Test script only. When using in project I recommend using an object pool --- Destroy(newAS.gameObject, 4); } } } // --- Insert custom code here to shoot projectile or hitscan from weapon --- } private void ReEnableDisabledProjectile() { projectileToDisableOnFire.SetActive(true); } } }