List/Array confusion

Hi all,

I need a method whereby I can access all my baddies (and potentially other things).
Rather than find"name" or find tag as I assume this would be slow I decided to read up on the multitude of list/arraylist etc. etc. methods.
My plan was that a ‘baddie controller’ object is responsible for all spawns and destroys of baddies and therefore will have a reference to them all.
After reading though I’m not sure if this is more efficient because it will have to manage some list which dynamically alters as baddies are killed/generated.
Should I just findwithtag when I need to? - just thinking a ‘global’ container of these things would make things easier and quicker…

Please note below is the type of thing I was thinking - not exact code!! (not sure how to get the index to remove) or even if this is the best method…

List<GameObject> go_list;
	
	// Use this for initialization
	void Start () 
	{
		go_list = new List<GameObject>();
	}
	
	public void spawn_baddie(GameObject thing,Transform trans)
	{
		GameObject spawn = GameObject.Instantiate(thing,trans.position,trans.rotation) as GameObject;	
		
		go_list.Add(spawn);
	}
	
	public void kill_baddie(GameObject thing)
	{
		foreach (GameObject go in go_list)
		{
			if (go.GetInstanceID == thing.GetInstanceID)
			{
				go_list.RemoveAt(go);
				Destroy (go);
				return;
			}
		}
	}

Any suggestions appreciated

Cheers

I think you’ve got the right idea - just one thing right off the bat. Don’t modify collections as you’re iterating over them.

A better method might be to use a Dictionary with the IDs as a key and the object as the value. This should make your lookups faster (although probably not noticeably unless you’re dealing with a lot of objects) and ends up being a bit less code to deal with.

Your next step should be to cache inactive GameObjects for re-use later on instead of Instantiate() and Destroy() every time. Then you’ve got a for realsies Object Pool at your disposal.

Hey KelsoMRK,

Appreciate the comments.
Don’t suppose you could splat some dictionary code up there for me? :slight_smile: (I did read about them but assumed lists were the way to go.
Also you say “don’t modify collections as you iterate” ; what exactly do you mean and where??? <sorry, noob to this as you can tell!>
How do I cache the inactive game objects? (I assume you mean don’t destroy them but leave in the list as ‘null’ or whatever).
I’m probably thinking of too many things so some guidance on what you are saying would be much appreciated!

Cheers

Actually, it is fairly simple, thought your on the right mindset.

When you want to destroy a baddie, you would do something like this:

	public void kill_baddie(GameObject thing){
		if(!go_list.Contains(thing)) return;
		go_list.Remove(thing);
		Destroy(thing);
	}

Now… On the flip side, if you have a “Baddie Controller” then you will also need a way to get those onto the list. Lets look at a generic Baddie…

	GameObject GenericBaddie;
	
	public void Add_baddie(Vector3 position, Quaternion rotation){
		GameObject thing = Instantiate(GenericBaddie, position, rotation);
		go_list.Add(thing);
	}

Now of course, you may want more than one type of Baddie, so you could use something like this:

	GameObject[] BaddieTemplates;
	
	public void Add_baddie(int BaddieType, Vector3 position, Quaternion rotation){
		GameObject thing = Instantiate(BaddieTemplates[BaddieType], position, rotation);
		go_list.Add(thing);
	}

Hey BigMisterB,

Thanks for the input will look into it!

Cheers

A very very basic object cache that I use as a starting point. The cache is backed by a dictionary and prevents multiple objects with the same identifier.

public sealed class ObjectCache
{
    private static ObjectCache instance;
    private Dictionary<id, SomeObject> cacheObjects;
    public static ObjectCache Instance
    {
        get
        {
            if (instance == null)
                instance = new ObjectCache();

            return instance;
        }
    }

    private ObjectCache()
    {
        cacheObjects = new Dictionary<int, SomeObject>();
    }

    public void AddObject(int key, SomeObject obj)
    {
        if (!cacheObjects.ContainsKey(key))
        {
            cacheObjects.Add(key, obj);
        }
        else
        {
            throw new CacheException("Object with key " + key + " already exists.");
        }
    }

    public SomeObject GetObject(int key)
    {
        if (cacheObjects.ContainsKey(key))
        {
            return cacheObjects[key];
        }
        return null;
    }
}

Basically if you add or remove items from a list it will mess up your indexes and you can either skip items or end up with an IndexOutOfBounds exception.

Instead of using Destroy() simply set the object to inactive and put it in a collection somewhere. Then, when you need another object of that type first check the collection to see if there are any unused ones available. If there are - remove it from the collection, activate it, run some method to restore some default values (like health or whatever) and then reposition it in the game world where you need it.

Appreciated!

Cheers