Get Address of Component From Collection Factory Instance (SOLVED)

Hi all,

My setup looks like this:

world.collection 
    <player game object, camera, etc...>
    scene.collection
        map.go
            #tilemap
        <other game objects...>

How do I retrieve a URL or address to the #tilemap component? scene.collection was spawned from a collection factory. The collectionfactory.create() function give me a list of hashed addresses to each game object, but I’m struggling to go from hash(map.go) to the address of map#tilemap.

I think collectionfactory.create() should also return the path to the spawned collection. Addressing into it is difficult when all it returns are various hashes.

1 Like

From a script on a game object in the world collection:

function init(self)
	local ids = collectionfactory.create("#collectionfactory")
	pprint(ids)
	local map_id = ids[hash("/map")]
	msg.post(map_id, "disable")
end

The id lookup table looks like this:

{ --[[0x10e0fc0a0]]
  hash: [/other3] = hash: [/collection0/other3],
  hash: [/map] = hash: [/collection0/map],
  hash: [/other1] = hash: [/collection0/other1],
  hash: [/other2] = hash: [/collection0/other2]
}
DEBUG:SCRIPT: h

So to get the actual id of the generated map game object (the one with the tilemap) we do a lookup and use it:

local map_id = ids[hash("/map")]
msg.post(map_id, "disable")

This gives us the actual id which we can use in code. hash("/map") is the id assigned to the map.go in the editor. Each spawned instance of scene.collection will create a unique id for each contained game object combining a generated id of the collection ("/collection0") and the id of the individual game objects ("/map", “other1” etc).

4 Likes

Got this far, however I’m wondering how to get the address of the tilemap component of the /map game object. Using local map_id = ids[hash("/map")] will only retrieve hash: [/collection0/map]. Is there a way to use this hash to get to the #tilemap component itself?

The idea would be simply to take the returned hash(“collection0/map”) and append “#tilemap” to it. However that’s not possible since it’s a hash instead of the string itself, and we can’t revert a hash to its string representation.

You create a url from the id and add the component (fragment):

msg.url(nil, map_id, "tilemap")

URLs: https://defold.com/manuals/addressing/#urls
How they can be used with factory created objects: https://defold.com/manuals/factory/#addressing-of-factory-created-objects

1 Like

Ah, I see, that’s strange. I figured that the msg.url() wouldn’t be able to handle this, since it takes the socket and id (args 1 and 2) separately, while the hash that’s returned from .create() includes both the socket and the id together.

Not quite. A socket is only something that we use as the first part of a Defold URL and ONLY when we reference the bootstrap collection or a collection loaded by a collection proxy. You can consider the bootstrap collection and collections loaded using factories as unique worlds, each referenced by the socket:

world:/some/game/object/path#component

Game objects spawned at the root of a world will have a URL like:

world:/id

While a game object that is spawned from a collection factory will get a more path-like url:

world:/collection0/id

/collection0 in this case is not a socket, it is just part of the game object id.

2 Likes

Okay, that makes sense, thanks! Really nice of you to explain that thoroughly.

1 Like