Multiple objects sharing a common script problem

Please help!

I have 4 navmesh agents (pacman ghosts) that each have the same AI script attached to them.
I tried to implement the frightened mode when the player eats a power pill and have some frustrating issues!

At first, I had the ghosts going into frightened mode via the players “eating” script and it worked well until I tried to implement the eating of them.

I since removed all this from the players eating script and placed it within the AI script.

After encountering problems, I ended up disabling all modes to concentrate on why the frightened mode wasn’t working and it has left me baffled! Basically, the player eats a powerpill which sets a bool variable in the AI script to “true” and resets each ghosts “currentSeconds” timer. The AI script now knows that this mode is active and does the things to each ghost that I wanted (set destination, tag as “frightened” and turn it’s material blue). Once currentSeconds is greater than 8, the bool is set back to false, the material is supposed to go back to original, tag go back to “ghost”. I don’t set a destination at this point as I disabled the other 2 modes. What is happening instead, is only one of the ghosts goes back to it’s original state! This has had me pulling what is left of my hair out and staying up til the early hours with no luck!

using UnityEngine;
using System.Collections;

public class GhostAI : MonoBehaviour 
{
	//private GameObject[] ghosts;
	//private GameObject[] ghostLights;

	public Material[] ghostMats;

	public int ghostDots;
	public int startDots;
	public Transform ghostHome;
	public Transform chase;
	public Transform scatter;
	public Transform frighted;
	public int chaseSeconds = 30;
	public int scatterSeconds = 10;
	public int frightedSeconds = 8;
	public float currentSeconds = 0f;
	public static bool frightedGhost;

	private NavMeshAgent agent;
	
	public GameObject caps;
	public GameObject ghostLight;
	
	private float agentSpeed;
	
	void Start () 
	{
		agent = gameObject.GetComponent<NavMeshAgent>();
		agentSpeed = agent.speed;
		frightedGhost = false;
		
	}
	void Update()
	{
		currentSeconds += Time.deltaTime;
		Debug.Log (frightedGhost);
		SetMode ();
	}
	
	void SetMode()
	{
		if (frightedGhost == true) {
			Frightedmode ();
		}

		//else if (currentSeconds < scatterSeconds)
		//	Scattermode ();
		//else if (currentSeconds > scatterSeconds)
		//	Chasemode ();
	}

	void Chasemode()
	{
		agent.SetDestination (chase.position);
		//Debug.Log(gameObject + "Chase Mode");
	}
	
	void Scattermode()
	{
		agent.SetDestination (scatter.position);
		//Debug.Log(gameObject + "Scatter Mode");
	}
	
	void Frightedmode()
	{
		if (currentSeconds < frightedSeconds) {
			agent.SetDestination (frighted.position);
			GetComponentInChildren<Renderer> ().material = ghostMats [0];		
			caps.tag = "Frighted";
			ghostLight.SetActive (false);
			Debug.Log (gameObject + "Frighted");
		}
		//if (currentSeconds > frightedSeconds){
		else{
			caps.tag = "Ghost";
			ghostLight.SetActive (true);
			GetComponentInChildren<Renderer> ().material = ghostMats [1];				
			frightedGhost = false;
			Debug.Log (gameObject + "Not Frighted");
		}

	}
	IEnumerator GoingHome()
	{
		caps.GetComponent<Renderer> ().enabled = false;
		agent.speed = 10;
		agent.SetDestination (ghostHome.position);
		yield return new WaitForSeconds(10);
		agent.speed = agentSpeed;
		caps.GetComponent<Renderer> ().enabled = true;
		caps.tag = "Ghost";
	}
}

"I since figured out why only one ghost was being reset, but it poses another problem. My original problem was caused by line 82…“frightedGhost = false”…as soon as one ghost was reset, the code no longer called the frightened mode.

So, now, how do I set “frightedGhost = false” again AFTER all ghosts have reset? "

I’d suggest using an array that holds all the ghosts, then cycling through that.

public GameObject[] ghosts;

Will be declared in the class.
Next, you will replace your call to the ghost material(line 81) with:

for(int i = 0; i < ghosts.Length; i++)
{
   ghosts*.GetComponent<Renderer>().material = ghostMats[1];*

}
Definitely familiarize yourself with the for loop, as it’s used frequently for cases such as this.
Hope this solves the problem, best of luck.
PS: Make sure the array is properly sized so as to avoid index errors.
Edit: I had forgot to mention simply removing the static variable as pointed out in the comments. This type of code would be for a single script controlling the state of all 3 ghosts. Sorry if this is unclear in any way.

Since the “frightedGhost” is static, all your objects share the same value. As you noticed, when you set it to “false” for the first ghost, every other ghost sees it as “false” and they never enter the FrightedMode() method anymore.

A simple solution is to store two static int, one for the number of ghosts alive, one to trace how many ghosts are no more frightened. When these number are equal, you can set “frightedGhost” to false.

public static int ghostCount;
public static int frigthenedGhostsCount;

Start()
{
    // [...]

    ghostCount++;
}

Then, inside FrightedMode()

else
{
    // [...]

    if (frightenedGhostsCount >= ghostCount)
        frightedGhost = false
    else
        frightenedGhostsCount++;
}

Yet, as I understand your logic, all the ghosts should be frightened/unfrightened at the same time.
If that’s so, you should better check for the timer once in a “World” MonoBehaviour Update method, it would save you some CPU cycles. The “World” object could keep a list of every present ghosts in the scene in order to loop through and enable/disable the frightenedMode.
To build the list, you can use “Object.FindObjectsOfType()” or register every ghost from their “Start” method. Depend of where you will need it more often, store the list in your “World” or inside GhostAI class as a static List since you don’t want to store one List of every ghosts in each of your ghost (see line 4, wasting memory).