Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to mimic FindGameObjectsWithTag with FindGameObjectswithName. I know using tags is faster, but I'm trying create a way to search for objects I spawn with a child object I name on instantiation through the inspector.

My goal is create multiple enemy spawners. My current spawner has a drag and drop variable for enemyprefabs. It looks for enemies tagged "ReSpawn", then checks if that length is below (x) to start spawning more. I would like to upgrade my current single spawner to still check for enemies named respawn, but then check if those respawn have a child object named "blank" (an input string name I can specify in the editor).

This way, I can set the enemy spawners anywhere (near water, tall grass, forests, etc), and when I defeat one, the specific spawner will instantiate one of its opponent for that area.

Here is my code

var ThisSpot:String;
var Oppos : GameObject[];
var OppoCount : GameObject[];

var HowMany = 3;
var spawnSizeArea = 25;

function Start() {
    StartCoroutine ("Spawn");
}

function Update () {
    OppoCount = GameObject.FindGameObjectsWithTag("Respawn");
    // OppoCount = GameObject.FindWithName(ThisSpot);  This is what I am trying to achieve

    if(OppoCount.length < HowMany) {
        StartCoroutine ("Spawn");
    }
}

function Spawn() {
    var length = Oppos.length-1;
    var index = Mathf.Round(length*UnityEngine.Random.value);
    curSpawn = Oppos[index];

    var xz = Random.insideUnitCircle * spawnSizeArea;
    var newPosition = Vector3(xz.x,0,xz.x)+transform.position;

    yield WaitForSeconds(Random.Range(70,120));

    Instantiate(curSpawn, newPosition, transform.rotation);

    // Then I could use these 2 lines of code below to use multiple spawners      
    //var newOp : GameObject = Instantiate(curSpawn, newPosition, transform.rotation);
    //newOp.transform.Find("fighter").gameObject.name=ThisSpot;

    StopCoroutine("Spawn");
}

EDIT: the solution. Instead of looking for gameobject names/tags, just keep track of a list

    **function Update () {



    for (var i =0; i < OppoCount.length ; i ++)


    if(OppoCount.length > 0){

if (OppoCount[i].gameObject == null)

OppoCount.RemoveAt(i);
}


    if(OppoCount.length < HowMany){
    StartCoroutine ("Spawn");
    }
    }


    function Spawn(){

    var length = Oppos.length-1;
    var index = Mathf.Round(length*UnityEngine.Random.value);
    curSpawn = Oppos[index];

    //var newPosition  = Random.insideUnitCircle* spawnSizeArea;
    var xz = Random.insideUnitCircle * spawnSizeArea;
    var newPosition = Vector3(xz.x,0,xz.x)+transform.position;


    //yield WaitForSeconds(Random.Range(70,120));
    yield WaitForSeconds(Random.Range(2,4));

    //Instantiate(curSpawn, newPosition, transform.rotation);

    var newOp : GameObject = Instantiate(curSpawn, newPosition, transform.rotation);

    //newOp.transform.Find("fighter").gameObject.active = false;

    OppoCount.Push(newOp);

    StopCoroutine("Spawn");
    }**
share|improve this question
1  
Unity has their own StackExchangeish answer boards... sorry for the spam, but answers.unity3d.com will give you faster/more exact solutions. At least I think so. –  joltmode Aug 5 '11 at 17:02
1  
@Tom That's not spam, it's a useful comment :p –  Jonathan Connell Aug 6 '11 at 10:13
    
You should post your solution as an answer to the question, not an edit to the question –  Jim Apr 19 '12 at 14:03

2 Answers 2

up vote 3 down vote accepted

Unity best practices are to never use Find in any of its incarnations at run time. It's slow and unnecessarily ties the name of the object with its functionality.

Any time you call Instantiate you can save off the return value and store it somewhere (i.e. a List in some component your write). Then you can just iterate over the elements of that list to get what you want.

So for your spawner example, your spawner could have a list of game objects that it has spawned. In Update you can iterate over that list and count the number of non-null gameobjects (to check for destroyed objects). Alternatively the enemy can have a reference to its spawner and remove itself from that list in OnDestroy. Then if that number is less than a certain value spawn a new one.

share|improve this answer
    
Now why didn't I think of that?? Thanks! I will post my attempt in a few moments in my original post –  Epic447 Aug 5 '11 at 22:29
    
That was the solution I needed! Thanks to you both for your kind help! –  Epic447 Aug 5 '11 at 22:38

From Unity Reference :

// This will return the game object named Hand in the scene.
hand = GameObject.Find("Hand");

You must remember that when trying to access objects via script, any inactive GameObjects are not included in the search. And that this will only return one object.

If you want to create the same behaviour as 'FindGameObjectsWithTag', you'll have to implement the function yourself.

In one of my games, for each level I used a GameObject to parent all the other objects, this way it was easier to access the objects. You could do something like :

int count = 0;
GameObject[] children = GetComponentsInChildren<GameObject>();
foreach (GameObjectchild in children )
{
    if(children.name == "WantedName")
        ++count;
}

Edit:

If you're using the UI to add instances to the spawner, that means that the spawner, and the objects it is supposed to spawn, are already instanced at startup. I don't think this is the best way to go about it. I would personally add a script to the spawner with an Enum for each monster type. This scripts behaviour would be to check if it holds an instance to an object, if not create one of the Enum type and keep the reference.

If you haven't tried overloading UI yet, it can be quite easy and help enormously in creating a more suitable editor for your game.

share|improve this answer
    
Unless If I can somehow tally 'foreach' to get a count of how many names it finds, I can't use it. I basically need amounts to check if their lengths are below a certain amount, so the spawner can know to instantiate more. I also prefer not to parent the enemies in gameobjects because they have other scripts constantly looking for the root transform, which must be the enemy itself (amongst other reasons). Someone a while ago suggested using 'Get Types' to find String names, but I had no idea how to use it properly with Java script. Any ideas? –  Epic447 Aug 5 '11 at 11:44
    
@Epic447 I edited the answer to tally the number of objects, but I'm still not sure I understand :). –  Jonathan Connell Aug 5 '11 at 11:53
    
I appreciate your help so far, and thank you! this will work, but what about when I defeat one the spawners enemies? This code is in the update function- won't the count keep adding 1 each second after it finds someone with the right name? This is really a bigger head scratcher than I thought it would be. Anyway, the gist is to be able to place multiple spawn points in a level, drag and drop people/creatures to spawn at each one, then if the player defeats one of those characters, to spawn another. So all thats needed is a wider method for tallying each thing. I'm just trying not to use tags –  Epic447 Aug 5 '11 at 12:14
    
@Epic447 Ok now I get it :). Indeed you could use a list of string along with a UI overload to make this possible, but it's all rather messy. I'll edit my answer to try and help more. –  Jonathan Connell Aug 5 '11 at 12:39
    
Wha?? Okay, now I am lost :) I have never heard of overloading UI? So I should drop trying to find objects by name (I'm lost!)? I think I recognize 'Enum'. That means I have to type a list of every name of every enemy right? there's around 50! How would I go from there? Please, may I ask you for an example? –  Epic447 Aug 5 '11 at 13:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.