Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Dylan Taylor - Project SciGun
- //This script is attached to all gun objects, and gives them their behavior. This script is what tells them how to fire and behave.
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Networking;
- public class GunScript : NetworkBehaviour
- {
- //It should be noted that all of these assigned values are simply placeholders or default values, and are generally overwritten in Unity itself.
- public Animator animator; //The animation controller of the gun.
- public GameObject bulletPrefab; //The bullet for the gun to fire
- public GameObject bulletSpawn; //The location for the gun to spawn the bullet
- public GameObject owner; //The player who's in control of this gun.
- private int oldFOV; //The camera's Field of View before zooming in/out
- public int primaryFiringMode = 0; //Which firing mode the gun should use
- public int secondaryFiringMode = 3;
- public int numBulletsToBurst = 3; //How many bullets for the gun to bust, if it uses the burst firing mode.
- [SyncVar] //Sync the value of the next variable over the network, with all instances of this object.
- public int totalAmmo = 30; //The amount of ammo that the gun has in total.
- public int MAX_LOADED_AMMO = 12;
- [SyncVar]
- public int loadedAmmo = 0; //How much ammo the gun has loaded
- public int firingPower = 100; //How much physics force to give the bullet as it leaves the gun.
- public float zoom = 2f; //The magnification level for weapons that use the zoom feature.
- public float fireDelay = .5f; //How long (in seconds) to wait before allowing the gun to fire again.
- public float accuracy = 2.5f; //An accuracy of 0 means that the gun has no spread.
- public Texture gunIcon; //The gun's icon, to show up in the bottom-right corner of the game when the weapon is picked up.
- public string gunName = "Weapon"; //Give the weapon a default name, in case it isn't assigned in the inspector.
- [SerializeField] //Make the private variable modifiable in the Unity editor itself, while keeping it private
- private AudioSource audioSource; //The gun's audio source, to be used to play gunshot and relaod sounds
- [SerializeField]
- private AudioClip primary; //The AudioClip sound for the primary fire. This will be played every time a bullet is fired.
- [SerializeField]
- private AudioClip secondary; //The AudioClip sound for the secondary fire. This will be played every time a bullet is fired.
- [SerializeField]
- private AudioClip reload; //The AudioClip sound for reloading. This will be played when the player reloads.
- private bool stillFiring = false; //If this is true, the gun cannot fire as it is in cooldown mode.
- private bool holdingPrimary = false; //The boolean variable to determine if the player is still holding down the primary firing button.
- private bool holdingSecondary = false; //The boolean variable to determine if the player is still holding down the secondary firing button.
- private Camera cam; //The local player's camera object
- // Use this for initialization
- void Start()
- {
- if (loadedAmmo == 0)
- {
- loadedAmmo = Random.Range(0, MAX_LOADED_AMMO); //Put a random amount of ammo in the magazine to begin with, and remove that number of bullets from totalAmmo. Only do this if loadedAmmo wasn't already assigned.
- totalAmmo -= loadedAmmo;
- }
- }
- // Update is called once per frame
- void Update()
- {
- if(cam == null)
- {
- foreach(GameObject c in GameObject.FindGameObjectsWithTag("MainCamera"))
- {
- if(c.name == "Local Camera")
- {
- cam = c.GetComponent<Camera>();
- oldFOV = (int)cam.fieldOfView;
- }
- }
- }
- }
- public void FirePrimary() //This function gets called when the user clicks the left mouse button.
- {
- if (stillFiring == false)
- {
- if (primaryFiringMode == 0) //Fires a single bullet
- {
- if (loadedAmmo > 0)
- {
- animator.SetBool("Fire0", true); //Tell the animator that we're firing, and tell it if it's primary or secondary
- CmdFire(0);
- animator.SetBool("Fire0", false); //Tell the animator that we're done firing, and tell it if it's primary or secondary
- }
- }
- else if (primaryFiringMode == 1) //Fires numBulletsToBurst bullets in a shotgun-like pattern, with high spread
- {
- if (loadedAmmo >= numBulletsToBurst)
- {
- animator.SetBool("Fire0", true); //Tell the animator that we're firing, and tell it if it's primary or secondary
- for (int i = 0; i < numBulletsToBurst; i++)
- {
- if (loadedAmmo > 0)
- {
- CmdFire(0);
- }
- }
- animator.SetBool("Fire0", false);
- }
- }
- else if (primaryFiringMode == 2) //Burst fire mode
- {
- if (Input.GetButton("Fire2") && stillFiring == false) //Burst fire
- {
- CmdBurst(numBulletsToBurst, 0);
- }
- }
- else if (primaryFiringMode == 3) //Aim-Down-Sights mode
- {
- StartCoroutine(ZoomIn());
- }
- else if (primaryFiringMode == 4) //Full-Auto mode
- {
- holdingPrimary = true;
- StartCoroutine(FullAuto(0));
- }
- else
- {
- Debug.LogError("Primary firing mode " + primaryFiringMode + " has not been defined in GunScript.cs");
- }
- }
- }
- public void FireSecondary() //This function gets called when the player clicks the right mouse button.
- {
- if (secondaryFiringMode == 0) //Fires a single bullet
- {
- if (loadedAmmo > 0)
- {
- animator.SetBool("Fire1", true); //Tell the animator that we're firing, and tell it if it's primary or secondary
- CmdFire(1);
- animator.SetBool("Fire1", false);
- }
- }
- else if (secondaryFiringMode == 1) //Fires numBulletsToBurst bullets in a shotgun-like pattern, with high spread
- {
- if (loadedAmmo >= numBulletsToBurst)
- {
- animator.SetBool("Fire1", true);
- for (int i = 0; i < numBulletsToBurst; i++)
- {
- if (loadedAmmo > 0)
- {
- CmdFire(1);
- }
- }
- animator.SetBool("Fire1", false);
- }
- }
- else if (secondaryFiringMode == 2) //Burst fire mode
- {
- if (Input.GetButton("Fire2") && stillFiring == false) //Burst fire
- {
- CmdBurst(numBulletsToBurst, 1);
- }
- }
- else if (secondaryFiringMode == 3) //Aim-Down-Sights mode
- {
- StartCoroutine(ZoomIn());
- }
- else if (secondaryFiringMode == 4) //Full-Auto mode
- {
- holdingSecondary = true;
- StartCoroutine(FullAuto(1));
- }
- else
- {
- Debug.LogError("Secondary firing mode " + secondaryFiringMode + " has not been defined in GunScript.cs");
- }
- }
- public void Reload() //Tells the animator that the gun should reload. This triggers the reload animation, and this animation will call the RealReload function after it has finished to actually adjust the ammo count.
- {
- stillFiring = true;
- UpPrimary();
- UpSecondary();
- if (loadedAmmo < MAX_LOADED_AMMO && totalAmmo > 0)
- {
- animator.SetTrigger("Reload");
- }
- }
- public void RealReload() //This function will transfer as much ammo as it can from totalAmmo to loadedAmmo, without exceding MAX_LOADED_AMMO, and without allowing totalAmmo to become negative.
- {
- if (loadedAmmo < MAX_LOADED_AMMO) //When reloading, check to see if there is enough ammo to fully fill the mag.
- {
- if (totalAmmo > (MAX_LOADED_AMMO - loadedAmmo))
- {
- totalAmmo -= (MAX_LOADED_AMMO - loadedAmmo); //Subtract the difference between the loaded ammo amount and the max loaded ammo amount
- loadedAmmo = MAX_LOADED_AMMO; //Fill the mag
- }
- else if (totalAmmo + loadedAmmo <= MAX_LOADED_AMMO)
- {
- loadedAmmo += totalAmmo; //If there isn't enough in totalAmmo to fill the mag, put all remaining bullets in the mag, and set the totalAmmo to 0.
- totalAmmo = 0;
- }
- else if (totalAmmo == MAX_LOADED_AMMO) //Otherwise, if there's no loadedAmmo and there's enough to fill the mag, then fill the mag and set totalAmmo to 0.
- {
- loadedAmmo = MAX_LOADED_AMMO;
- totalAmmo = 0;
- }
- animator.ResetTrigger("Reload"); //Tell the animator that we're done reloading.
- stillFiring = false;
- UpPrimary();
- UpSecondary();
- Debug.Log("loadedAmmo: " + loadedAmmo);
- }
- }
- [Command]
- public void CmdBurst(int numBursts, int c) //Accepts a number of bullets to burst fire, and an int c to tell the gun which sound clip to play (0 = primary fire sound, 1 = secondary fire mode, 2 = reload sound)
- {
- if(!stillFiring) //If the gun isn't currently firing or in its wait period for firing, we're clear to move on
- StartCoroutine(Burst(numBursts, c)); //Start the firing coroutine. This has to be in a coroutine so that the firing method can wait to fire until the wait period for firing again is over.
- }
- [Command]
- public void CmdFire(int c) //This is the function that ultimately tells the server to actually fire the gun. Accepts an int parameter to tell it which sound clip to play.
- {
- StartCoroutine(Fire(c));
- }
- public IEnumerator Burst(int numBursts, int c) //This will repeatedly call CmdFire(c) numBursts times
- {
- stillFiring = true;
- animator.SetFloat("BurstSpeed", 3); //Tell the animator to play the firing animation at triple-speed
- for (int i = 0; i < numBursts; i++)
- {
- if (loadedAmmo > 0) //Make sure we don't fire more times than our ammo allows for.
- {
- CmdFire(c);
- yield return new WaitForSeconds(fireDelay / 3f); //Wait for one-third of the gun's normal fireDelay, then fire another round. This allows the gun to burst fire much more quickly than simply firing normally
- }
- else
- {
- stillFiring = false;
- break;
- }
- animator.SetBool("Fire" + c, false);
- }
- yield return new WaitForSeconds(fireDelay / 3);
- animator.SetFloat("BurstSpeed", 1); //Tell the animator to play the firing animation at normal speed
- yield return new WaitForSeconds(fireDelay * (2 / 3));
- animator.SetBool("Fire" + c, false);
- stillFiring = false;
- }
- public IEnumerator Fire(int c) //This is the function that occurs locally on the serverside. Accepts an int c to determine which sound clip to play.
- {
- stillFiring = true;
- if (loadedAmmo > 0)
- {
- CmdPlaySound(c);
- loadedAmmo--;
- GameObject bullet = (GameObject)Instantiate(
- bulletPrefab,
- bulletSpawn.transform.position,
- new Quaternion(90, bulletSpawn.transform.rotation.y, bulletSpawn.transform.rotation.z, 0));
- bullet.GetComponent<Rigidbody>().velocity = (bulletSpawn.transform.forward * firingPower) + (bulletSpawn.transform.up * Random.Range(-1 * accuracy, accuracy)) + (bulletSpawn.transform.right * Random.Range(-1 * accuracy, accuracy)); // Add velocity to the bullet, and add a random bit of spread based on the gun's accuracy
- NetworkServer.Spawn(bullet);//Spawn the bullet for all connected players
- bullet.GetComponent<Bullet>().owner = PlayerPrefs.GetString("Player Name");
- bullet.GetComponent<Bullet>().firingPlayer = owner;
- yield return new WaitForSeconds(fireDelay);
- stillFiring = false; //Tell the scripts that we're cleared to fire again
- yield return new WaitForSeconds(2f - fireDelay);
- NetworkServer.Destroy(bullet); //This destroys the bullet after 2 seconds on all connected games, so that someone doesn't fire into the sky and never have the bullet break. If we did this, the game would eventually slow down drastically
- }
- }
- [Command]
- public void CmdPlaySound(int c)
- {
- RpcPlaySound(c); //Call the "Play Sound" function on all connected clients.
- }
- [ClientRpc] //The server will always call a ClientRPC function. The [ClientRPC] Attribute, along with RpcXXX(), means that this object will have this function called on it in every instance of the connected games.
- public void RpcPlaySound(int c) //Plays "AudioClip c" through the gun's AudioSource component.
- {
- if (c == 0)
- audioSource.PlayOneShot(primary);
- else if (c == 1)
- audioSource.PlayOneShot(secondary);
- else
- audioSource.PlayOneShot(reload);
- }
- [Command]
- public void CmdAddAmmo(int a) //Used for picking up ammo. This function will be called from the gunControllerScript.
- {
- totalAmmo += a;
- }
- public Texture GetGunIcon() //Return the weapon's icon, so that it shows up in the UI for the player.
- {
- return gunIcon;
- }
- public string GetName() //Return the assigned name of this object to the gunControllerScript, so that it shows up in the UI for the player.
- {
- return gunName;
- }
- public string[] GetAmmo() //returns a string array, with the first element being the loaded ammo and the second element being total remaining ammo. This is done to allow for only one function call from the gunHandler script.
- {
- return new string[2] { loadedAmmo.ToString(), totalAmmo.ToString() };
- }
- public IEnumerator ZoomIn() //Zooms the player's camera in, for firing modes that use zoom.
- {
- while(cam.fieldOfView > (int)(oldFOV / zoom))
- {
- cam.fieldOfView = Mathf.Lerp(cam.fieldOfView, (int)(oldFOV / zoom), 2);
- yield return new WaitForEndOfFrame(); //We don't actually need a wait function, this is just to satisfy the requirement for a yield return value. I don't want to change this to a void function in case I want to animate via scripting
- }
- }
- public IEnumerator ZoomOut() //Zooms the player's camera back to its original Field of View.
- {
- cam.fieldOfView = oldFOV;
- yield return new WaitForEndOfFrame(); //We don't actually need a wait function, this is just to satisfy the requirement for a yield return value. I don't want to change this to a void function in case I want to animate via scripting
- }
- public void UpPrimary() //This is called when the player lets go of the primary firing button (left mouse button).
- {
- holdingPrimary = false;
- if(primaryFiringMode == 3)
- {
- StartCoroutine(ZoomOut());
- }
- }
- public void UpSecondary() //This is called when the player lets go of the secondary firing button (right mouse button).
- {
- holdingSecondary = false;
- if(secondaryFiringMode == 3)
- {
- StartCoroutine(ZoomOut());
- }
- }
- public IEnumerator FullAuto(int c) //The coroutine to handle full-auto firing. Accepts an int c to determine which sound clip to play.
- {
- stillFiring = true;
- animator.SetBool("Fire" + c, true);
- while ((holdingPrimary || holdingSecondary) && loadedAmmo > 0)
- {
- CmdFire(c);
- yield return new WaitForSeconds(fireDelay);
- }
- stillFiring = false;
- holdingPrimary = false;
- holdingSecondary = false;
- animator.SetBool("Fire" + c, false);
- }
- }
Add Comment
Please, Sign In to add comment