Problem - Shotgun raycast instantiates multiple destroyed gameobjects instead of one
Hello again!
I was following PushyPixels' tutorial on making a shotgun using multiple raycasts. Everything works except for one problem. I have a wooden box that has health script on it, so when box' health drops to 0, the game object is deleted and destroyed version of a box is instantiated as well as some particle effects. Now the problem:
If I shoot just one raycast that does enough damage to destroy the box - no problem. If I shoot two raycasts and both of them hit the box then the number of instantiated destroyed objects will be doubled. If I use three then it will be tripled and so on....
This is script that shoots raycasts:
public class ShotgunWeapon : BaseWeapon { public int shotFragments = 8; public float spreadAngle = 10.0f; public float BulletForce = 10.0f;
protected override void PrimaryFire()
{
for (int i = 0; i < shotFragments; i++) {
RaycastHit hit;
Quaternion fireRotation = Quaternion.LookRotation(transform.forward);
Quaternion randomRotation = Random.rotation;
fireRotation = Quaternion.RotateTowards(fireRotation, randomRotation, Random.Range(0.0f, spreadAngle));
if (Physics.Raycast(transform.position, fireRotation * Vector3.forward, out hit, Mathf.Infinity, layerMask))
{
GunHit gunHit = new GunHit();
gunHit.damage = damage;
gunHit.raycastHit = hit;
//Check if hit object has health
HasHealth h = hit.collider.gameObject.GetComponent<HasHealth>();
if (h != null)
{
h.ReceiveDamage(damage);
}
if (gunHit.raycastHit.rigidbody)
{
gunHit.raycastHit.rigidbody.AddForceAtPosition(transform.forward * BulletForce * 10, gunHit.raycastHit.point);
}
}
}
}
}
It's inherented class, so this is the base weapon script:
public abstract class BaseWeapon : MonoBehaviour {
public float fireDelay = 0.1f;
public int maxAmmo = 0;
public float damage = 1.0f;
public string primaryFire = "Fire1";
public LayerMask layerMask = -1;
public bool automaticFire = false;
private bool readyToFire = true;
private int currentAmmo;
protected abstract void PrimaryFire();
void start()
{
currentAmmo = maxAmmo;
}
// Update is called once per frame
void Update()
{
CheckInput();
}
protected virtual void CheckInput()
{
bool primaryFirePressed;
if (automaticFire)
{
primaryFirePressed = Input.GetButton(primaryFire);
}
else
{
primaryFirePressed = Input.GetButtonDown(primaryFire);
}
if (primaryFirePressed)
{
if (readyToFire && (currentAmmo > 0 || maxAmmo == 0))
{
PrimaryFire();
readyToFire = false;
currentAmmo--;
Invoke("SetReadyToFire", fireDelay);
}
}
}
void SetReadyToFire()
{
readyToFire = true;
}
}
And finally this is the script for health:
public class HasHealth : MonoBehaviour {
public float HitPoints = 10f;
public GameObject DestroyedParticle;
public GameObject DestroyedObject;
public void ReceiveDamage (float amount)
{
HitPoints -= amount;
if (HitPoints <= 0)
{
Die();
}
}
void Die()
{
Destroy(gameObject);
Instantiate(DestroyedObject, transform.position, transform.rotation);
Instantiate(DestroyedParticle, transform.position, transform.rotation);
}
}
I'm pretty sure the problem is in rays that hit the box in the same time and they all trigger the event that instantiantes the destroyed box object. But how to solve it?
Sorry for the wall of text, but that's been bugging me for quite a while.
Thanks in advance!
Answer by MadAce · Oct 21, 2015 at 07:08 AM
Managed to fix the problem thanks to a collegue at work!
Problem was in HasHealth script. Fixed script:
public void ReceiveDamage (float amount)
{
if (HitPoints > 0)
{
HitPoints -= amount;
Debug.Log(HitPoints);
if (HitPoints <= 0)
{
Die();
}
}
}
void Die()
{
Destroy(gameObject);
Instantiate(DestroyedObject, transform.position, transform.rotation);
Instantiate(DestroyedParticle, transform.position, transform.rotation);
}
}
I had the exact same issue. Thanks to you it's sorted :D I was just missing the "if (HitPoints > 0)".