Problems with platformer game and collection proxies

Good morning, everyone. In the past, I programmed a few games published on the Play Store using the former Corona SDK, now Solar2D. After developing a few apps with Flutter, I felt the urge to publish a small game again.

I love retro 8-bit style 2D platformers, so I thought about using Love2D first, then Defold, while still staying within the Lua environment, so to speak. I discarded Love2D because I would like to publish the game on platforms such as Itch.io, both for desktop and HTML5, and for the latter, Defold seems better to me. However, I’m encountering some major problems during development, perhaps because I don’t yet fully understand how the Defold platform works. I initially created a main collection, inside which I put a collection proxy for the menu and several proxies, each for one of the game levels, created with the integrated tilemap editor. Yesterday, I first encountered the error of tiled maps with a maximum size of 2048x2048 tiles (solved by dividing the level into two smaller maps) and then the impossibility of having more than 8 proxies by default: when I added the 8th level, Defold gave me an error (I already have 7 proxies for each of the current levels plus the proxy for the menu).

I guess the path I’m taking is definitely wrong. How should I reorganize my game so that I can have many levels, loading what I need as I go?

1 Like

I have no experience of creating anything with multiple levels so perhaps someone else can answer that. You could also check the source code of this: https://forum.defold.com/t/cosmic-dash-is-published-madewithdefold-jam-2025/

The amount of collection proxies can be changed in the game.project file.

1 Like

All of them can be configured at Defold project settings

1 Like

Thank you both for your answers.
Yes, I am aware that I could increase these limits in the Defold settings, but I have read in several places that increasing the limits too much is not recommended because it increases memory consumption.

That’s why I asked if there was another way. I also thought about using factories instead of proxies, but I ran some tests and got confused because of the message management between the various components, since the addresses with factories are no longer the same as those I used in the case of proxies.

PS: I could double the maximum number of proxies, but I’m afraid I would need several dozen for all the levels I have in mind. I don’t think it would be very healthy to carry all these proxies around with me.

its hard to give advice with the little info i have.

i tend to use monarch that abstract away a lot of the clunkiness you are experiencing.
i tend to create a collection factory per level, and then you can create an instance of it when needed, and then unload it when you are done.

maybe have a read on how monarch works and if it suits your way of working.

otherwise i am sure it’s possible to load/unload collections without using monarch, but i never learned because monarch is too good unfortunately :smiley:

Thanks for the reply. I’m trying to figure out if I can implement my game using collection factories. I created a collection factory for each collection that contains the individual levels of my game (level_01_factory => level 1, etc.). From the main loader, I’m creating the levels as I go along. I’m using this code:

local function unload_current_level(self)
	if self.current_level then
		go.delete(self.current_level)
		collectionfactory.unload("/controller#" .. self.last_lvl)
	end
end

local function load_level(self, lvl)
	unload_current_level(self)

	local my_collection = "/controller#" .. lvl
	collectionfactory.load(my_collection, function (obj, url, result)
		if result then
			local my_level = collectionfactory.create(url, vmath.vector3(0, 0, 0))
			self.current_level = my_level
			pprint(my_level) -- debug
			self.last_lvl = lvl
			local game_logic = my_level[hash("/logic")]
			if game_logic then
				msg.post(msg.url(nil, game_logic, "game"), "init_game")
			end

			local player = my_level[hash("/player/player")]
			if player then
				msg.post(msg.url(nil, player, "player"), "init_game")
			end
		end
	end)
end

The first level is generated and loaded correctly, but when I move on to the second, I get errors.

ERROR:GAMESYS: Sound could not be created since the buffer is full (32). Increase the 'sound.max_component_count' value in [game.project](defold://open?path=/game.project)

The problem arises from the fact that collection.create returns an empty table; there are no IDs for the objects created. This is what I get at the second pprint:

{ } --[[0x7f434c291530]]

What could be causing this?

Doesn’t this happen because of the error about max sound instances?

I actually increased the value of max_component_count to 64 and now it doesn’t do it anymore, but I still don’t understand: I use a sound manager that plays all the sounds in the game, linked to each collection. In theory, when I destroy the loaded collection, it should also destroy the sound_manager, but that doesn’t seem to be the case. I just can’t understand how these collection factories work: before generating a collection, I always destroy the previous one, but even if it is not loaded dynamically, it seems that the new one is created before the components of the previous one are actually destroyed.

Reading the documentation, it says that a game object is destroyed when the current frame ends. Could it be that by destroying the game objects of a collection and then immediately loading a new one in the same frame, the first operation is actually postponed? So, all game objects actually remain active and counted, including all their components such as sounds.

How can I proceed, then? I’m sure I’m missing something.

I think I’ve solved it by postponing the creation of the new collection to the next frame using a flag that is checked in the update function.

In the first frame, I delete the game objects and unload the current collection from memory, then I set a flag that is checked by the update function in the next frame: if the flag is present, I generate the new collection.

It seems to work, now I’ll do some more testing.

Strange errors appear when trying out the game, which did not appear before when I was using proxies. At the second level change, I receive this message:

ERROR:GAMESYS: Could not get the tile since the supplied tile was out of range.

And then I find randomly generated tiles, where there is nothing, as if the engine still had something in memory that it did not completely delete.

Yes, the objects live for the entire frame and are counted towards the max counts.