TUK
TUK

Reputation: 51

How to change a value in all the gameobjects that are spawning in unity?

I have an enemy spawner that spawns up to 10 enemies at a time. I want that when a player collects an item the value in a script that is on all the spawning enemies will change. Let's say that their speed is equal to 5, I want to do that after the player picks up a potion the speed will change to 3. I thought about creating an array of the scripts and then changing the value in each one using a loop, like that:

public class PlayerController : MonoBehaviour
{
    public EnemyController[] enemCon;

    void Start()
    {
        enemCon = FindObjectsOfType<EnemyController>();
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag=="Potion")
        {
            for (int i=0; i<enemCon.Length;i++)
            {
                enemCon[i].speed = 3;
            }
        }
    }
}
public class EnemyController : MonoBehaviour
{
    public int speed=5;
}

But to do so I need to put the scripts in the inspector. The problem is that the enemies are being created during the game and so I cant use them in the inspector beforehand.

Is there a way to do such a thing?

Upvotes: 2

Views: 191

Answers (4)

not_actually_finn
not_actually_finn

Reputation: 1

I think there are two main ideas how you can do that.

  1. Your script has a List/ Array that stores all the gameObjects (the gameObject that holds the scripts of the enemy). Your InputActionMap has a action "click q" notices when you clicked for example "q" and then runs a script. This script would have a look if you picked up a portion (If(pickedUp = "potion")) and would have a reference to your enemy-spawner and loop over the list and set the speed of each enemy (GameObject.GetComponent<EnemyController>().getSpeed() = 3).
  2. All enemies are childs of one GameObject so that you can find them by having the parent and using foreach (foreach(GameObject enemy in parent){//do stuff}) after a pick up was recognized for example with the second part of the first solution or your solution
void OnTriggerEnter2D(Collider2D other)
{
   if (other.tag=="Potion"){
      //the loop
   }
}

I hope that helps and summarizes the two other posts.

Upvotes: 0

hijinxbassist
hijinxbassist

Reputation: 4711

Use a static variable for the speed.

A static variable will exist once across the entire application, and can be accessed through the Type in which it is declared. This approach is valid when you need a single variable accessible from everywhere.

Simply change you speed variable to static.

public class EnemyController : MonoBehaviour
{
    public static int speed=5;
}

Now all enemies will have the same exact speed, and the speed can be changed easily.

EnemyController.speed = 3;

Upvotes: 1

Xander
Xander

Reputation: 447

Architecturally correct solution: you need a Player, a Spawner, an Event and a Rule entities. Player and Spawner are emitting events: OnPickUp(item) and OnSpawn(entity). A Rule is a thing that describes on a high level how your game should behave in regards of particular mechanic. Following your example, you need a rule that modifies existing enemies (increase speed) and every next one that will be spawned after the Player picks up certain object (or a certain number of objects). So, the Rule in this case must:

  • subscribe to Player's OnPickUp event and count particular objects,
  • subscribe to Spawner's OnSpawn event and store references to spawned enemies,
  • store the data that represents how many pickups is needed to strengthen the enemies and how strong they should be now.

From this point the logic is pretty obvious: now you'll have different objects with their own responsibilities and no one of them is not trying to do what it is not supposed to (like the Player counting pickups and changing monster's power).

With that structure (or similar) you'll easily expand the logic of your game, adding new rules. In Unity it's easier to store such persistent things as Rules as ScriptableObjects to be able to copy, modify and reference them on scene or in prefabs.

Upvotes: 0

cat24a
cat24a

Reputation: 1

Maybe try finding enemies every time the player picks up a potion. FindObjectsByType allows to not sort them so it's faster, but FindObjectsOfType would work too.

public class PlayerController : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.tag=="Potion")
        {
            EnemyController[] enemCon = FindObjectsByType<EnemyController>(FindObjectsSortMode.None);
            for (int i=0; i<enemCon.Length; i++)
            {
                enemCon[i].speed = 3;
            }
        }
    }
}

Upvotes: 0

Related Questions