After a few weeks of hacking around, I’m still quite new to Defold so I definitely don’t have a complete perspective on all its systems. But I’ve noticed a pattern in my usage where I’ve started defaulting to using Collections instead of Game Objects, even if at the present moment I only need a GO, so I wanted to ask about it:
There have been several times where I defined a game object, then later needed a second game object (for instance, adding a pivot to offset a camera), so then I had to migrate both the implementation and all the usage sites to a collection instead. Now, I generally just start with a collection with a single child GO by default. That way future expansion is easy and there doesn’t seem to be a downside (perhaps there is, and I just haven’t run into it yet?)
It does feel a bit weird, but you’re not wrong to default to collections. In my opinion, this is Defold’s most blatant example of poor engine design.
Game objects and collections are virtually the same, the only practical difference being that if you want to spawn a hierarchy of game objects, you use a collection. Collections act as a sort of root game object in a hierarchy, but they don’t actually exist… Which is so so strange, because game objects alone can already act as roots of other game objects, but only within a collection or via go.set_parent(). It’s a totally arbitrary abstraction of the concept of a root game object, a restriction that shouldn’t exist. They’re just an unnecessary addition to the web of complexity that comes with its own API, way of working, requirement for newcomers to wrap their minds around, source of confusion and bugs, etc.
Collections should be entirely axed from the engine, at least from the user’s perspective. Game objects should be able to nest other game objects in their component files, not just in collection component files or programmatically. They also fly directly in the face of Defold’s core bare-bones philosophy. I’m surprised they’ve lasted this long. They were probably included since the initial design of the engine, which might make them difficult to remove.
I ran into the same patterns that you mentioned, where eventually I found myself needing to spawn a hierarchy of game objects rather than just one. Like you said, this required me to refactor all of my code and files that touched anything related to the issue, which was… a lot of code and files.
I agree. The two concepts should be merged somehow. This has been the topic of many internal discussions and it may happen at some point but it is also a huge breaking change.
To follow up on this, I have also encountered the opposite problem: starting something as a collection, then needing to refactor it into a game object due to the limitations of collections.
For example, I made a “floating_platform” as a collection with a single game object. Later, I wanted to make a “pinwheel” that had 4 floating platforms within it, all rotating around a central pivot. The most convenient arrangement here is for the pivot point to be a game object, so that platforms can be parented to it and rotate around it, having a single GO to place in the world.
However, since collections can’t be placed inside of game objects and collections themselves do not create local coordinate spaces, I had to either refactor the floating_platform collection into a game object, or make the platforms themselves a little more complicated by having knowledge of a “pivot” they should move relative to.
I think unification of these concepts would go a long way towards making defold even more elegant and approachable. I’m still a little fuzzy about the details of what various combinations of game objects and collections would do, especially since collections seem like they might create local coordinate systems under some circumstances.
Since this would be a big breaking change and we don’t know when it will be implemented, would make sense to just add the ability for gameobjects to nest other gameobjects without removing Collections.
Even though it will add another way of doing things but at the same time this will greatly simplify crafting and architecting the project tree.
Visual editing works really well and I find it very helpful. This methodicalness is not always practicable. By the look of it the answer that is occurring, and all round panacea, is editor-scripts. As I understand it you can use Lua to create objects (GO/collections/components) and relationships; then use an editor script to automatically create the protobuf-structure to feed to the engine. This is mega and will make a GO<->collection swap trivial (once the infrastructure is in place…). Seems that this tiger is quietly being released into the wild and the devs are watching to see what it will do/eat. Editor scripting improvements in the upcoming 1.10.4 version.
Sure, my comment was predicated on gameobject nesting already being possible when the gameobject is placed inside a Collection. So this feature can be extended to gameobjects outside of a Collection, of course with the necessary care and testing.
I wonder if there are any plans to resolve this dilemma? For instance, by allowing GOs to be nested within one another?
As a newcomer, I find these rather odd conventions confusing—especially coming from Godot’s dead-simple “everything is a scene/everything is a node” principle.
IMO unifying or axing it from the engine might not be the best solution. For me collections true purpose is when using collection proxies, it is an effective separation between “worlds” not only creating a different namespace but also separating the physics which I think is an important feature to keep in the engine. That said, I think that this should be its only role!
I agree that having to have to use it for nesting game objects is bad design and root cause of too many hours of refactoring or planning the architecture far ahead. I would be very happy to be able to nest game objects without collections and also be able to use collection proxies for deferring the loading of my worlds without physics or namespace clashing.
As a kind of workaround to refactor complexe gameobjects, I have find out that instead of transforming a gameobject into a collection, you add gameobject factories to your gameobject, and you spawn your subobjects with factories at init.
Then you can parent them etc. via code. And you have still one master GO that will move the subobjects.
It can be sometime a bit hard to compute good placements for subobjects since you dont see them in the editor, but you can prototype that in a collection then use just the positions to spawn via factories.
For example for the multiplateform with a pivot:
Your master GO is then the pivot, and it spawn a number of existing plateform objects that will revolve arround. Then the script move the subplateforms and comput all interactions.
This pattern works quite well without collections, even if it is a bit more of code.
But this also make things dynamic: for example here you can set a property as the number of plateforms to spawn!
This make these systems more reusable in fact.
As mentioned before, it’s something we wish to simplify/unify.
We don’t have it in our plans for the near future.
But we should start designing it though.