Shotgun problem (isometric, raycast, looped)

I am working on an top-downish shooter based on the unity survival shooter tutorial. I have added some different weapons, and now I’m trying to implement a shotgun. It works partially, but not as I intended.
The problem is it displays only one ray instead of one ray for each pellet as I intended (or more likely, raycasts all the pellets in the same random direction). Mechanics wise, it does raycast multiple pellets, judging by the damage it does to enemies. I am not very familiar with looping, which you might notice in a minute… :stuck_out_tongue: Any help would be greatly appreciated.

Here’s the code, minus some parts which I feel are not relevant (reloading and ammo counter etc)

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class ShotgunWeapon : MonoBehaviour
{
    public int shotPellets = 8;
    public float scattering = 10.0f;
    public int damagePerShot = 15;                 
    public float timeBetweenBullets = 1f;       
    public float range = 20f;                     
    public float reloadTime = 3f;
    public int maxAmmo = 6;
    public Slider ammoSlider;
    public Text curAmmoCount;

    private int currentAmmo;
    private bool isReloading = false;

    float timer;                                   
    Ray shootRay;                                  
    RaycastHit shootHit;                          
    int shootableMask;                             
    ParticleSystem gunParticles;                  
    LineRenderer gunLine;                          
    AudioSource gunAudio;                         
    Light gunLight;                                
    float effectsDisplayTime = 0.05f;

    

    void Awake ()
    {
        shootableMask = LayerMask.GetMask ("Shootable");


        gunParticles = GetComponent<ParticleSystem> ();
        gunLine = GetComponent <LineRenderer> ();
        gunAudio = GetComponent<AudioSource> ();
        gunLight = GetComponent<Light> ();
    }

    void Update ()
    
        if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets)
        {
            Shoot ();
        }
           
        if(timer >= timeBetweenBullets * effectsDisplayTime)
        {
            DisableEffects ();
        }
    }
    public void DisableEffects ()
    {
        gunLine.enabled = false;
        gunLight.enabled = false;
    }

    void Shoot ()
    {
        currentAmmo--;
        ammoSlider.value = currentAmmo;
        curAmmoCount.text = ammoSlider.value.ToString("0");
        timer = 0f;

        gunAudio.Play ();

        gunLight.enabled = true;

        gunParticles.Stop ();
        gunParticles.Play ();

        gunLine.enabled = true;
        gunLine.SetPosition (0, transform.position);

        for (int i = 0; i < shotPellets; i++)
        {

            shootRay.origin = transform.position;
            Vector3 randomDirection = transform.forward * Random.Range(-scattering, scattering);
            randomDirection.x = 0;
            shootRay.direction = transform.forward + randomDirection;

            if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
            {
                EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();

                if (enemyHealth != null) {
                    enemyHealth.TakeDamage (damagePerShot, shootHit.point);
                }
                gunLine.SetPosition (1, shootHit.point);
            }
            else {
                gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
            }
        }
    }
}

Your rays are all pointing in the forward direction. The forward direction multiplied by a random factor is still the forward direction.

What you want is to add a random multiple of the right vector to the forward vector, and then normalize. If you do:

randomDir = transform.forward;
randomDir += Random.Range(-scattering, scattering) * transform.right;

You’ll get what you’re looking for.

Note that the length of transform.forward is 1, so a scattering where you multiply right by ±10 would cause the scattering to be completely bonkers. A scattering of 1 would give a 45 degree scatter maximum.

1 Like

Thanks. I already set the scattering to 1 when testing as I noticed things got pretty wild with 10 scatter.
I’m still having difficulties adapting your suggestion to my code. I’m not sure which parts of the old code I should remove and where to add the suggested lines. Could you please be more specific?

randomDir = transform.forward;
randomDir += Random.Range(-scattering, scattering) * transform.right;
shootRay.direction = randomDir;
1 Like

Thank you very much, that did it. Actually it is not drawing each of the pellets as separate line renderers, only one of them, but that doesn’t matter - I wouldn’t use them in the final form anyway. Mechanics wise it spreads nicely now.