0
votes

TL;DR: Why can I only "kill" my first enemy, but the rest aren't affected by my attempt to turn their components off?

Overview

Hi Guys and Gals, I'm running into issues with my AI switching to Ragdoll when the player kills them, but more specifically it's not deactivating any other components either.

Basically, I have an AI script that runs a statemachine via IEnumerators and coroutines, I also have a RagdollDeath script just to keep code seperate.

Ideally, when the player shoots the enemy, they switch to a ragdoll state.

How I accomplish this

Besides turning off all the animator, navmesh, and other components when health reaches 0, I also turn off ALL rigid bodies using

void IsKinematic(bool newvalue)
{
    foreach (Rigidbody rb in bodyparts)
    {
        rb.isKinematic = newvalue;
    }
}

this creates a beautiful and seamless ragdoll transition from animation.

My Issue

The issue i'm running into, is that when I fire at an enemy, they do exactly as expected, but when I fire at another enemy, it doesn't run my script at all, even though I can see it running via using Print("Something") prompts. I have made sure to prefab my enemy and apply changes to said prefab.

What is even stranger, is that if I clone 2 enemies, and shoot the new one, the first one will go ragdoll across the level! It's almost as if monobehavior is not working.

Any insight into what may be causing this would be greatly appreciated.

Full Code that is causing issues
public class ZombieStateMachine : MonoBehaviour {

[SerializeField] GameObject player;
[SerializeField] GameObject los;
[SerializeField] GameObject[] waypoints;
[SerializeField] int timeBetweenWaypoints = 1;
[SerializeField] AudioSource jumpyscare;

private int health = 100;
private SuspenseAudioScript suspensescript;
private NavMeshAgent agent;
public bool canSeePlayer;
public float distanceBetween;
public string routine = "null";
private Animator animator;
public bool isAttacking = false;
private ShootScript shootscript;
private Rigidbody[] bodyparts;
private CapsuleCollider capsule;



void IsKinematic(bool newvalue)
{
    foreach (Rigidbody rb in bodyparts)
    {
        rb.isKinematic = newvalue;
    }
}

// Use this for initialization
void Start () {
    shootscript = GameObject.FindGameObjectWithTag("Player").GetComponent<ShootScript>();
    suspensescript = GetComponent<SuspenseAudioScript>();
    animator = GetComponent<Animator>();
    agent = GetComponent<NavMeshAgent>();
    StartCoroutine(Eyesite());
    StartCoroutine(Wander());
    bodyparts = GetComponentsInChildren<Rigidbody>();
    capsule = GetComponent<CapsuleCollider>();
    IsKinematic(true);

}



public void KillZombie()
{
    this.StopAllCoroutines();
    IsKinematic(false);
    animator.enabled = false;
    agent.enabled = false;
    capsule.enabled = false;
    this.enabled = false;
}



Here is the accompanying shoot script

public class ShootScript : MonoBehaviour {

[SerializeField] public int health = 100;
[SerializeField] AudioSource gunshotsound;
[SerializeField] Light gunshotflash;


public float impactforce = 2f;
private ZombieStateMachine enemyscript;
private Rigidbody rb;
private CharacterController m_CharacterController;
private Camera cam;
private CapsuleCollider enemycol;
public UnityStandardAssets.Characters.FirstPerson.FirstPersonController fpscontrol;


// Use this for initialization
void Start () {
    fpscontrol = GetComponent<UnityStandardAssets.Characters.FirstPerson.FirstPersonController>();
    enemycol = GameObject.FindGameObjectWithTag("Enemy").GetComponent<CapsuleCollider>();
    enemyscript = GameObject.FindGameObjectWithTag("Enemy").GetComponent<ZombieStateMachine>();
    cam = GetComponentInChildren<Camera>();
    rb = GetComponent<Rigidbody>();
    m_CharacterController = GetComponent<CharacterController>();

}

// Update is called once per frame
void Update () {
    Shoot();
}

public void Shoot()
{
    if (Input.GetKeyDown(KeyCode.Mouse0))
    {
        Debug.DrawRay(cam.transform.position, cam.transform.forward, Color.red, 1.0f);
        RaycastHit hit;
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, 2000f))
        {
            if(hit.transform.tag == "Enemy")
            {
                enemyscript.KillZombie();
                gunshotsound.Play();
                StartCoroutine(GunshotFlash());
            }
            else
            {
                gunshotsound.Play();
                StartCoroutine(GunshotFlash());
                print("You MIssed!");
            }
        }
    }
}

IEnumerator GunshotFlash()
{
    while (true)
    {
        gunshotflash.enabled = true;
        yield return new WaitForSeconds(0.05f);
        gunshotflash.enabled = false;
        yield return new WaitForSeconds(1);
        break;
    }
}

public void PlayerDeath()
{
        rb.AddForce(this.transform.forward * 2);
        rb.isKinematic = false;
        m_CharacterController.enabled = false;
        fpscontrol.enabled = false;
        //rb.useGravity = true;
}

}

1

1 Answers

0
votes

Not sure if you ever came across the solution to this but I believe the problem is within your start method for the Shoot script.

enemycol = GameObject.FindGameObjectWithTag("Enemy").GetComponent<CapsuleCollider>();

Doing this will return the first game object that has the "Enemy" tag, it would be be better to just do:

enemycol = GetComponent<CapsuleCollider>();

Probably the same thing needs to be done with the line right under that, the enemyscript variable:

enemyscript = GameObject.FindGameObjectWithTag("Enemy").GetComponent<ZombieStateMachine>();

change to

    enemyscript = GetComponent<ZombieStateMachine>();