- Home /
Raycast bullet spread C#
Can someone help me get a bullet spread going? I am currently using the script that Brackeys made for my gun and added some stuff to it: using UnityEngine; using System.Collections; using UnityEngine.UI;
public class Gun : MonoBehaviour {
public float damage = 8f;
public float range = 100f;
public float fireRate = 10f;
public float impactForce = 30f;
public int maxAmmo = 20;
public int fullAmmo = 160;
private int remainingAmmo;
private int currentAmmo;
public float reloadTime = 1.5f;
private bool isReloading = false;
private bool didFunction = false;
private bool lastClip = false;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public AudioSource gunShot;
public AudioSource noAmmo;
public AudioSource pullOutRifle;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
public Animator animator;
public GameObject ammoUI;
void Start ()
{
currentAmmo = maxAmmo;
}
void OnEnable ()
{
isReloading = false;
animator.SetBool("Reloading", false);
StartCoroutine(ChangeToWeapon());
}
void Update() {
ammoUI.GetComponent<Text>().text = currentAmmo.ToString() + "/" + fullAmmo.ToString();
remainingAmmo = 20 - currentAmmo;
if(pullOutRifle.isPlaying)
{
return;
}
if(currentAmmo == 0 && fullAmmo == 0 && Input.GetMouseButtonDown(0))
{
noAmmo.Play();
}
if (currentAmmo <= 0 && lastClip == true)
{
currentAmmo = 0;
fullAmmo = 0;
return;
}
if(fullAmmo <= 20 && didFunction == true)
{
currentAmmo = fullAmmo;
didFunction = false;
lastClip = true;
}
if(currentAmmo == fullAmmo)
{
fullAmmo = 0;
}
if (isReloading)
return;
if(currentAmmo <= 0 || Input.GetKeyDown(KeyCode.R) && currentAmmo != 20)
{
StartCoroutine(Reload());
return;
}
if(Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
IEnumerator Reload ()
{
isReloading = true;
animator.SetBool("Reloading", true);
yield return new WaitForSeconds(reloadTime - .25f);
animator.SetBool("Reloading", false);
yield return new WaitForSeconds(.25f);
currentAmmo = maxAmmo;
fullAmmo -= remainingAmmo;
isReloading = false;
didFunction = true;
}
IEnumerator ChangeToWeapon()
{
animator.SetBool("PullOutWeapon", true);
yield return new WaitForSeconds(1.041f);
animator.SetBool("PullOutWeapon", false);
}
void Shoot ()
{
muzzleFlash.Play();
gunShot.Play();
currentAmmo--;
RaycastHit hit;
if(Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Target target = hit.transform.GetComponent<Target>();
if(target != null)
{
target.TakeDamage(damage);
}
if(hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject impactGO = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactGO, 2f);
}
}
}
There are no actual bullets, can someone help me just get like a Raycast randomizer going? Thank you.
Answer by Eno-Khaon · Sep 17, 2018 at 03:22 AM
Well, there are a variety of potential options to approach this, so here's a few of 'em:
1 - Calculate an angle and a deviation
For each "bullet" fired, you're currently using
fpsCam.transform.forward to dictate the direction the bullet should be fired in the
Raycast. So, if you randomize a value up to a maximum deviation angle, then randomize the rotation around a circle, you can get a usable value out of it.
Vector3 forwardVector = Vector3.forward;
float deviation = Random.Range(0f, maxDeviation);
float angle = Random.Range(0f, 360f);
forwardVector = Quaternion.AngleAxis(deviation, Vector3.up) * forwardVector;
forwardVector = Quaternion.AngleAxis(angle, Vector3.forward) * forwardVector;
forwardVector = fpsCam.transform.rotation * forwardVector;
The value of forwardVector at that point will then be rotated and moved away randomly up to a fixed angle.
2 - Calculate deviation at a fixed distance
Using the weapon's range (other otherwise-defined value), you can decide what maximum distance of deviation you want. For example, a gun could be defined has having a 1-meter deviation at a range of 100 meters.
Vector3 deviation3D = Random.insideUnitCircle * maxDeviation;
Quaternion rot = Quaternion.LookRotation(Vector3.forward * range + deviation3D);
Vector3 forwardVector = fpsCam.transform.rotation * rot * Vector3.forward;
Mainly, what really matters is what type of implementation you're looking to use. These two options result in very different schemes for deciding a gun's accuracy.
Edit: Updated Example 2 based on my comment below
Thank you for the help. Sadly, I couldn't figure out how to do it (sorry I'm new to unity.) Do you $$anonymous$$d writing some code for me or telling me where I should put each line of code? I can't figure out where I put those lines of code you gave me. Thank you so much.
Everyone's new at some point. Don't sweat it.
Either of those would come just before this line of yours:
if(Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
Rather than using fpsCam.transform.forward then, you'd replace it with forwardVector from my examples.
Edit: Aside from that, you'd also need to define a "maxDeviation" float variable to indicate maximum degrees variation (example 1), or distance deviation (example 2)
Awesome! This worked perfectly! If you don't $$anonymous$$d, could you tell me what each line of code you posted for the first example does? Thank you so much!
Your answer