Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using UnityEngine;
- using TMPro;
- /// Thanks for downloading my projectile gun script! :D
- /// Feel free to use it in any project you like!
- ///
- /// The code is fully commented but if you still have any questions
- /// don't hesitate to write a yt comment
- /// or use the #coding-problems channel of my discord server
- ///
- /// Dave
- public class ProjectileGunTutorial : MonoBehaviour
- {
- //bullet
- public GameObject Ammo;
- public GameObject bullet;
- public Animator animator;
- public float damage = 15f;
- public Behaviour WS;
- //bullet force
- public float shootForce, upwardForce;
- //Gun stats
- public float timeBetweenShooting, spread, reloadTime, timeBetweenShots;
- public int magazineSize, bulletsPerTap;
- public bool allowButtonHold;
- int bulletsLeft, bulletsShot;
- //Recoil
- public Rigidbody playerRb;
- public float recoilForce;
- //bools
- bool shooting, readyToShoot, reloading;
- //Reference
- public Camera fpsCam;
- public Transform attackPoint;
- //Graphics
- public GameObject muzzleFlash;
- public TextMeshProUGUI ammunitionDisplay;
- //bug fixing :D
- public bool allowInvoke = true;
- private void Awake()
- {
- //make sure magazine is full
- bulletsLeft = magazineSize;
- readyToShoot = true;
- }
- private void Update()
- {
- Ammo.SetActive(true);
- MyInput();
- //Set ammo display, if it exists :D
- if (ammunitionDisplay != null)
- ammunitionDisplay.SetText(bulletsLeft / bulletsPerTap + " / " + magazineSize / bulletsPerTap);
- }
- private void MyInput()
- {
- //Check if allowed to hold down button and take corresponding input
- if (allowButtonHold)
- shooting = Input.GetKey(KeyCode.Mouse0);
- else
- shooting = Input.GetKeyDown(KeyCode.Mouse0);
- //Reloading
- if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazineSize && !reloading)
- Reload();
- //Reload automatically when trying to shoot without ammo
- //Shooting
- if (readyToShoot && shooting && !reloading && bulletsLeft > 0 && Input.GetKey(KeyCode.Mouse0))
- {
- //Set bullets shot to 0
- bulletsShot = 0;
- animator.Play("AttackS");
- animator.SetTrigger("Attack");
- Shoot();
- }
- else if (!shooting)
- {
- animator.Play("IdleS");
- }
- }
- private void Shoot()
- {
- bulletsShot = 0;
- readyToShoot = false;
- //Find the exact hit position using a raycast
- Ray ray = fpsCam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); //Just a ray through the middle of your current view
- RaycastHit hit;
- //check if ray hits something
- Vector3 targetPoint;
- if (Physics.Raycast(ray, out hit))
- targetPoint = hit.point;
- else
- targetPoint = ray.GetPoint(75); //Just a point far away from the player
- //Calculate direction from attackPoint to targetPoint
- Vector3 directionWithoutSpread = targetPoint - attackPoint.position;
- //Calculate spread
- float x = Random.Range(-spread, spread);
- float y = Random.Range(-spread, spread);
- //Calculate new direction with spread
- Vector3 directionWithSpread = directionWithoutSpread + new Vector3(x, y, 0); //Just add spread to last direction
- //Instantiate bullet/projectile
- GameObject currentBullet = Instantiate(bullet, attackPoint.position, Quaternion.identity);
- // Attach a script to the bullet to handle destruction
- Bullet bulletScript = currentBullet.AddComponent<Bullet>();
- bulletScript.lifetime = 5f; // Set the lifetime as desired
- //Rotate bullet to shoot direction
- currentBullet.transform.forward = directionWithSpread.normalized;
- currentBullet.transform.Rotate(90.0f, 0.0f, 0.0f, Space.Self);
- //Add forces to bullet
- currentBullet.GetComponent<Rigidbody>().AddForce(directionWithSpread.normalized * shootForce, ForceMode.Impulse);
- currentBullet.GetComponent<Rigidbody>().AddForce(fpsCam.transform.up * upwardForce, ForceMode.Impulse);
- //Instantiate muzzle flash, if you have one
- if (muzzleFlash != null)
- Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
- bulletsLeft--;
- bulletsShot++;
- //Invoke resetShot function (if not already invoked), with your timeBetweenShooting
- if (allowInvoke)
- {
- Invoke("ResetShot", timeBetweenShooting);
- allowInvoke = false;
- //Add recoil to player (should only be called once)
- playerRb.AddForce(-directionWithSpread.normalized * recoilForce, ForceMode.Impulse);
- }
- //if more than one bulletsPerTap make sure to repeat shoot function
- if (bulletsShot < bulletsPerTap && bulletsLeft > 0)
- {
- Invoke("Shoot", timeBetweenShots);
- }
- Target target = hit.transform.GetComponent<Target>();
- if (target != null)
- {
- target.TakeDamage(damage);
- }
- }
- private void ResetShot()
- {
- //Allow shooting and invoking again
- readyToShoot = true;
- allowInvoke = true;
- }
- private void Reload()
- {
- reloading = true;
- Invoke("ReloadFinished", reloadTime); //Invoke ReloadFinished function with your reloadTime as delay
- }
- private void ReloadFinished()
- {
- //Fill magazine
- bulletsLeft = magazineSize;
- reloading = false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment