How should I work around this bug? (SOLVED)

I’m working on my weapons for my Doom clone and it’s been going pretty we…

Well, it’s been going.

Up to this point I’ve been starting the shots in the player’s collider and only applying damage on collision enter.

It works pretty well too, since I can manage to shoot myseld (or others), but it won’t count until it exits the player’s collider.

But now I’m hung up on my Flak cannon primary fire.

You see, I’ve got a parent called “Flak Shot” and it houses 10 “Flak Shrapnel” projectiles.

When the shrapnel respawns on the next shot I have to move them in place on enable. Boom! That’s an collision enter.

I tried to turn off the collider at the start for one frame, but that led to shooting through walls.

Any suggestions?

Here’s my current code for the parent:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Flak_Shot : MonoBehaviour {
    public float lifeSpan;
    public float lifeClock;
    // Use this for initialization

    private void Awake()
    {
        lifeClock = lifeSpan;
    }

    void OnEnable ()
    {
        lifeClock = lifeSpan;
    }

    // Update is called once per frame
    void Update()
    {
        lifeClock -= Time.deltaTime;
        if (lifeClock < 0)
        {
            gameObject.SetActive(false);
        }
    }
}

And the shrapnel:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Flak_Shrapnel : MonoBehaviour {
    public float speed;
    public float dropOffSpeed;
    public float maxDamage;
    public float lifeSpan;
    float lifeClock;
    Vector3 startPosition;
    Quaternion startRotation;
    Rigidbody myRigidbody;
    Light myGlow;
    float myGlowIntensity;
    // Use this for initialization
    void Awake () {
        lifeClock = lifeSpan;
        myRigidbody = GetComponent<Rigidbody>();
        myGlow = GetComponent<Light>();
        myGlowIntensity = myGlow.intensity;
        startPosition = transform.localPosition;
        startRotation = transform.localRotation;
    }
    private void OnEnable()
    {
        lifeClock = lifeSpan;
        myGlow.intensity = myGlowIntensity;
        //transform.localPosition = startPosition;
        //transform.localRotation = startRotation;
        myRigidbody.velocity = Vector3.zero;
        myRigidbody.angularVelocity = Vector3.zero;
        myRigidbody.velocity = transform.forward * speed;
        myRigidbody.useGravity = false;
    }
    // Update is called once per frame
    void Update () {
        lifeClock -= Time.deltaTime;
        if (lifeClock < 0){
            transform.localPosition = startPosition;
            transform.localRotation = startRotation;
            myRigidbody.velocity = Vector3.zero;
            myRigidbody.angularVelocity = Vector3.zero;
            gameObject.SetActive(false);
        }
        if (myRigidbody.velocity.magnitude < dropOffSpeed)
        {
            myRigidbody.useGravity = true;
            myGlow.intensity -= Time.deltaTime;
        }
    }
    private void OnCollisionEnter(Collision collision)
    {
        int damage;
        damage = Mathf.RoundToInt (myRigidbody.velocity.magnitude / speed * maxDamage);
        if (collision.transform.tag == "Player"){
            //Debug.Log("Ouch! You just took " + damage + " damage!");
            collision.transform.GetComponent<Status>().ChangeCurrentHealth(damage);
        }
    }
}

I don’t see any collision related code here…

Does changing layer cause a collision check? If not, then the shrapnel could be moved to an ‘inert’ layer, moved inside the collider and then changed back to the correct ‘active’ layer.

If that doesn’t work, have you tried explicitly ignoring between the shot and the shrapnel?

2 Likes

Oh, shoot!

Posted the same code twice.

Edited in the correct code in the OP.

You should script the projectiles to ignore the gun and unimportant colliders, or use collision layers.

The gun doesn’t have a collider. The player does, but I need the projectiles to be able to damage them if they catch a ricochet or something.

You can tell it to ignore a specific collider. Did you look at the manual? Unity - Scripting API: Physics.IgnoreCollision

(ignore the parameters because Unity got that wrong).

1 Like

Maybe something like this?

    private void OnCollisionEnter(Collision collision)
    {
        if (lifeClock < lifeSpan)
        {
            int damage;
            damage = Mathf.RoundToInt (myRigidbody.velocity.magnitude / speed * maxDamage);
            if (collision.transform.tag == "Player") {
                //Debug.Log("Ouch! You just took " + damage + " damage!");
                collision.transform.GetComponent<Status>().ChangeCurrentHealth(damage);
            }
        }
    }

Unless your issue is the projectiles are also changed in trajectory or velocity by the player collider as well.

I think @hippocoder has got the perfect solution for me.

Thanks again, man!

You’re a life-saver!

You too, @Doug_B !

1 Like