Reset a script mid game

Anyone know how to reset a script in the middle of a game? It would be best if it called the Start method and everything. I know I could remove the component and re add it but it would be a script on active enemy’s and I would rather not have 10 - 20 remove and add components going at the same time.

this.Start() ?

(of course it’ll only work well if you initialize everything in it…)

Well the problem I am having is I have an enemy that shoots arrows. That script has a listener that listens for the game to start. Once the game starts he shoots arrows and if the player dies he stops. The player has 3 lives so the enemy waits for the player to start the game again. All this works perfectly up until you start the game again. And then the cool down period that the enemy is suppose to wait between shots seems like it gets messed up. Sometimes even shooting arrows back to back. Here is my code:

using UnityEngine;
using System.Collections;

public class EnemyProjectile : MonoBehaviour
{
    public GameObject projectile;
    public float fireSpeedMin = 0.0f;// Min ammount of seconds between fire
    public float fireSpeedMax =0.0f;// Max ammount of seconds between fire
    public float speed = 20f; // The speed the object moves on the Y axis
    public float damage = 10f; // Damage the projectile does to the paddle
    public LevelScaleP levelScale;
   
    [HideInInspector]
    public int level = 0;
   
    //Private
    private GameObject firedObject;
    private bool timeToShoot = false;
    //Events
    //private EventManager EM;
    private bool gameStopped = false;
    void OnEnable()
    {
        EventManager.gameBegins += gameBegins;
        //EM = GameObject.Find("Main Camera").GetComponent<EventManager>();
    }

    void Start ()
    {
        CheckLevelStats();
    }
    void Update ()
    {
        if(timeToShoot == true && gameStopped == false)
        {
            firedObject = Recycling.Do().CreateObject(projectile, gameObject.transform.position, Quaternion.identity);// Create or grab obj
            firedObject = ResetObj(firedObject);// resets obj to prefab state
            firedObject.rigidbody2D.AddForce((Vector2.up * -1) * speed); // adds force to shoot downwards
            timeToShoot = false; // Tell script that it needs to go on cooldown
            firedObject.GetComponent<ProjectileAI>().damage = damage; // sets damage for the arrow
            StartCoroutine(WaitingForCD()); // Starts cooldown timer.
        }
    }
    private GameObject ResetObj(GameObject obj)
    {
        //Resets obj to prefab state
        obj.layer = projectile.layer;
        obj.transform.rotation = projectile.gameObject.transform.rotation;
        return obj;
    }
    void CheckLevelStats()
    {
        speed  += levelScale.speedPerLevel * level;
        damage += levelScale.damPerLevel   * level;
    }
   
    IEnumerator WaitingForCD()
    {
        if(timeToShoot == false)
        {
            yield return new WaitForSeconds(Random.Range(fireSpeedMin, fireSpeedMax));
            timeToShoot = true; // Says the enemy can shoot again
        }
       
    }
    void gameBegins(bool gameStart)
    {
        if(gameStart == true)
        {
            StartCoroutine(WaitingForCD());
            gameStopped = false;
        }
        if(gameStart == false)
        {
            gameStopped = true;
            timeToShoot = false;// So the enemy does start off shooting
            Recycling.Do().CleanUp();
        }
    }
}
[System.Serializable]
public class LevelScaleP
{
    public float damPerLevel     = 0.0f;
    public float speedPerLevel  = 0.0f;
}

Do you disable this script at some point ? You’re not cleaning up anything so for example the speed will keep going up as you re-enable the script and every time you enable the script you’re adding a listener, so what this does is that every additionnal life it starts an additionnal coroutine, so in some circumstances you probably have the first CD firing an arrow, setting timeToShoot to false and then right away the 2nd coroutine sets it back to true so it fires again.

You need to handle removing the event listener. Also you may have some sort of memory leak.

Instead of a coroutine, I would use a timer :

float nextShootTime = 0;

void Update()
{
      if (!gameStopped && nextShootTime < Time.realtimeSinceStartup)
      {
             nextShootTime = Time.realtimeSinceStartup + Random.Range(fireSpeedMin, fireSpeedMax);
             //Throw your arrow
      }
}

Coroutine are great to split tasks accros frames but I believe they shouldn’t be used for timing purposes, this is the kind of mess you get into when you do :wink:

Ok ill keep that in mind. And no I never disabled the script thus why i never worried about removing the listener. Thanks for the info and sugestions.