Store character collections and later delete

Hello,

My character prefabs are collections. I spawn them using the collection factory. I would like to store the references to all of the spawned characters so I could later perform actions on all of them. Mainly I need it to delete all the currently spawned characters. So this would mean iterating over all of them.

I can store the returned value of collection_factory.create() in the table but when looping through the table sometime later, how can I use the stored value to reference the spawned gameobjects to then delete them? So how can I access the specific objects?

Thanks!

1 Like

There are two examples in the documentation for collectionfactory, which should help you in this case.

I’ve solved this problem in my game by the following method:

When I create a collectionfactory instance I:

table.insert(self.entity_factories, id_of_object)
self.entity_factory_offset = self.entity_factory_offset + 1

And then during level unload I do this:

for i = 1, self.entity_factory_offset do
	go.delete_all(self.entity_factories[i])
end
self.entity_factories = {}
self.entity_factory_offset = 1

This removes all the collectionfactory created instances.

Why do you need self.entity_factory_offset? You could just iterate over the whole table with ipairs, unless I’m missing something.

2 Likes

This is my code to create a character collection. I am creating many of these character collections:

This is the result of the 4 prints:
image

/body and /face are parented under /main gameobject. How can I later access the /collectionX/main game object, in the self.spawned_fish table, of every created character collection to then delete it. When I delete it recursively, the body and face would get deleted as well.

EDIT: I think I got it. By calling fish[k], I can access the required hash. Will test it out.

But what if you wanted to get a certain value with the inserted id?

I am still having some issues here. So this is how I am inserting the values into the table now:

After the fish character has been clicked, I get its path and add it to the message, which I then pass to the fish manager.

However, when I try to access the value in the table, I get a nil:
image
image

Why is it so?

URLs cannot be used as table keys. See this thread.

Assuming the fish game object has a script, you could store the key as a script property and check against that. Something like:

local fish = collectionfactory.create(...)
table.insert(self.spawned_fish, fish[hash("/main")])
msg.post(fish[hash("/main")], hash("setup_key", {key = #self.spawned_fish})

The fish script needs to have the property defined:

go.property("key", 0)

(It also needs to handle the message sent earlier, I’ll skip that)

Then to get the right fish you iterate over the table of all fish to get the right one:

local fish_key
  for key, val in ipairs(self.spawned_fish) do
    if go.get(msg.url(nil, val, "name_of_the_script"), "key") == key then
        fish_key = key
        break
    end
end

This is probably not the cleanest solution, but the first one to come to my mind.

I haven’t verified, but ipairs does check for nil entries at every step of the iteration. If you know the amount of collectionfactory entities spawned into the game and store the offset then it should be a faster process to simply walk through the list until the final offset and delete them. I’d have to benchmark it though to see for certain.

I think I’ve seen some benchmarks which show that iterating by ipairs is a bit slower, but it should be negligible in this case.

At any rate, you could use #self.entity_factories to get the number of entries in the table.

Also, in your example, the index variable seems to be reset to 1 when the table gets emptied. Shouldn’t it go to 0?

Lua tables start at index 1 not 0 like other languages.

Yeah, but an empty table has no elements, so you need to start with a 0 if you have an empty table. A table with five entries will have indices from 1 to 5.

Your code starts with an empty table and index of 1, then you add one entry (with key 1) and the index gets increased to 2. If you run the iterator then, it will run the delete function twice, once for the one element in the table and a second time with nil.

I am actually thinking that since the keys can be numbers, then in the script that creates the fish, I could just hold a local variable “self.current_id”. Use that variable as key and then the path to the fish object as the value. This current_id will be a property in a fish script. So when the fish gets deleted, for example, I will use the fish’s current id, and send a message to remove the entry from the table with that id.

self.current_id would be incremented every time a fish is spawned.