Big List of Defold Pro Tips!

Texture compression can take a long time. Be aware that if you have compression_level=BEST making bundles can take a long time. It may look like it has hanged, but if you have this setting on with a large project it’s most likely still busy so give it some more time.

2 Likes

On loading screens, which improve user experience, and load your main collection. As your project grows, and especially as your main collection grows, you will find it takes longer to boot up your game into its ready state. This can be a problem for mobile devices, and for best experience you’ll need to give an indication that your game is still happily getting the game ready for them.

It’s not easy to know how long it will take to load your main collection. You want a visual indicator, you want a progress bar that is constantly moving. It’s not a bad idea to “fake” your progress bars so that they are constantly moving, but have diminishing speed the closer they get to 100%, and then have them instantly jump to 100% before screen transitions. But you’ll still want to make what’s right for your game. Some games “fake” the first 50% and then the rest is real progress based on chunk milestones, but again with loading your main collection there is no indicator just a good guess you can make based on how long it usually takes, and remember if you change the assets in your collection it will change how long it takes to load. Also worth keeping in mind just because your test device loads it quickly doesn’t mean other low end phones will.

If your game loads pretty fast you can skip the progress bar loading screen completely, and just use your splash as the loading screen. With or without the “Loading…” text. You could omit this text, and just have it so that if they tap the screen it then show this “Loading…” text to reassure your users.

It’s worth noting some technical details about Android and iOS. If you make a large main collection and don’t have a loading screen - when your user opens your game they will be faced with just a black screen while they wait for the main collection to load. This is avoided by using a light weight collection that uses the Collection Proxy feature to then load and switch to the main collection.

When iOS apps load they first show a hardware splash image. This image is suggested to be the same image you first display to the user when you render your first screen too. They use this hardware splash to fake out users into believing that apps open faster than they really do. As soon as the app is ready your app takes over, and the best experience is to display the same image and then transition from it. These images are what you can define in the iOS section of game.project file. All of the different sizes are hardware splash images for the various models of Apple products.

You can also put loading screen inbetween loading large collections. I’ve not tested async loading yet, but assuming it works how I think it does if you know you are transitioning screens soon you could pre-load the next screen’s collection and have it ready to go to nearly instantly.

More information on Collection Proxies

I’m preparing a loading screen template and will include it in a future post.

8 Likes

Self hosting a pre-made push notification service. I’ve not used this, just sharing it as it may be useful to some Defold users out there.

Pushkin is a free open source tool for sending push notifications. It was developed with a focus on speed and enabling fast experimentation. Pushkin was mainly built for supporting online mobile games, but can easily be extended to any type of application. It supports both Android and iOS platforms.

Pushkin is designed to be a responsive tool. You can design your systems around Pushkin so it reacts to your game server, database server, client or really any service that can send a HTTP POST request. It is also easily scalable, because you can run as many Pushkin instances as you want. One instance is capable of pushing 500 messages per second.

http://docs.pushkin.io/en/latest/

2 Likes

Pro Tip: Don’t compose long messages in the text box here, do it elsewhere. Things can happen and your message eaten. :sweat:

9 Likes

Use shortcuts to find and open files for editing quickly.

In Preferences -> General -> Keys there is an option Open Resource.

This can be used to open a dialog which will allow you to search for a file to open. It can be any file, and it will be opened with default option. This can be useful if you are working with a big project, and don’t want to hunt for the file in the file tree.

You can change the shortcut for the Open Resource dialog too. I’m testing setting it as simply F1. Depending on OS and setup you may prefer some other shortcut.

Read through the other keys in the editor and experiment with them. Generally once you memorize shortcuts they can speed up your workflow.

2 Likes

Using layers, and ordering within layers based on y position. In some games, you want to have discrete rendering layers for objects. You also want to have objects on layers to be sorted based on y position so that higher objects on the plane are drawn behind objects which are in front of their y position.

Script by @Andreas_Jirenius

Download:

render_order.script (218 Bytes)

render_order.script source

local layer_z = { -0.9, 0.0, 1.0 } -- layer 1, layer 2, layer 3 with default z values

go.property("layer",1) -- exposes this value to be able to be changed in editor, defaults to 1

function update(self, dt)
	local pos = go.get_position()
	pos.z = layer_z[self.layer]-pos.y*0.0001 -- start with layer z default, modify it based on y position
	go.set_position(pos)
end

Add this script as a component to any game object you wish to sort based on layer and y position. You could extend it further for example by adding an additional optional offset property to make certain objects stay on discrete whole number layers but still be above or below everything else on that layer without needing to define more layers.

Remember that your camera z position matters for what is able to be seen by your camera. If you position at z positions behind your camera anything there won’t be visible and so won’t be drawn.

Adding scripts to objects has a runtime cost, and having too many scripts can cause you to hit the default script limit. If you want to sort or manage hundreds of bullets for example it would be better to do that from a single script and not have every bullet object have its own copy of the script.

13 Likes

Moving files and folders around directories within Defold. Create a folder in the wrong place? Want to move it somewhere else?

You can drag and drop folders and other resources, but this can be difficult to do properly. It’s more accurate to use the Move… option when you right click on any folder or resource.

Then select a folder to move to

Moving many files at once is possible. You can click a resource in a longer list, hold down shift after you have selected a resources and then click on another resource to select the second resource and anything between. Hold ctrl to select / deselect indivdiual resources once you have other selections active. Then right click and select the move option.

3 Likes

Basic tiled importer. This is basically the example @Andreas_Jirenius made in one of his videos + sloppy parts I did with testing it (but do not worry it will be polished more later). It is rough, but should be enough to get people started, and is more accessible to the public. On my big list of todos, I plan to make a generic importer that can more easily be added to projects and then expanded based on the needs of the project.

  • This method imports Tiled data to replace what is in a Defold tilemap. It’s a very good idea to use Defold’s built in tilemaps for tiles because they are already optimized for batch rendering.
  • Tiled can export .lua files for your maps. That is what this method imports.
  • Remember this is rough, if you want wait until I make a polished and more generic-usable version later.
  • Tiled has many features. When you import maps you’ll want to tailor what data you use based on your game.
  • Tiled has the x,y starting at the top left tile on its maps and is 0 based index. Defold has the x,y starting tile at the bottom left of its tilemaps and is 1 based index. You will need to flip and offset compensate data because of this.
  • Currently Defold does not allow you to define the size of tilemaps with scripting or with properties, it requires you to draw the bounds of your map.
  • The tile images used in example are http://opengameart.org/content/lpc-tile-atlas ok for example but you would want to use your own assets for a real project
  • Supports object layer data and creating game objects at correct position based on the data … you’ll want to add custom properties in Tiled and then pull them as you need them
  • The Tiled level is ugly purely for testing purposes
  • If you make fixes / improvements please share them

Updated: simple_tiled_importer_example.zip (537.6 KB)

Older: simple_tiled_import_example.zip (537.5 KB)

5 Likes

A couple of comments:

  1. Shouldn’t the tiled_importer.script be named tiled_importer.lua?
  2. Shouldn’t you require() the tiled_importer module from test.script?
  3. Now there’s a direct call to M.create_level() in test.script but I don’t see how the test.script would have access to M. Oh, wait now I see it. tiled_importer.script declares a global M. This is not really a recommended approach since there’s a high risk of something else also being declared as M and overwriting the tiled_importer.

I have put some suggested improvements here:

3 Likes

Yep, those are the sloppy bits. Thank you for the suggestions - I’ll get it cleaned up!

This kind of thing worked previously in other tests but it’s not working here. Any idea? I want to allow more dynamic map data loading.

function M.create_level(map_data_file, target_tilemap, map_tile_width, map_tile_height, tile_px_width, tile_px_height)
	local script = ("/main/levels/level_1.lua")
	local code = sys.load_resource(script)
	local def = assert(loadstring(code))
	
	--map_data_file = map_data_file or "/main/levels/level_1.lua"
	--local def = assert(loadstring(sys.load_resource(map_data_file)))

Edit: Tested more things and still not sure why it’s not working… it could be “solved” by loading JSON but I’d still like to figure how to make this work

Edit2: Here is sample where it’s working for the JSON decoded file but not for the lua how I would expect. I’m going to continue refactoring with the JSON method and hope someone can give hint on how to get the lua method working. Not a deal breaker.

master.zip (542.9 KB)

2 Likes

Simple JSON loading example. You can load JSON files from the file system, convert them into Lua tables with json.decode, and then use them as you would a Lua table. To be able to load files like this, they must be within a folder defined in your game.project

The code itself is very simple.

    local file = sys.load_resource("/main/json_files/level_1.json")
    local decoded = json.decode(file)
    print(decoded.layers[1].type) -- example of getting data

If you do not want to convert JSON into Lua tables you will have to parse it yourself. If the JSON data is malformed you will get an error.

json_loading_example.zip (2.9 KB)

5 Likes

Uploaded some improvements to original post. Still some more to do but that looks like correct direction right?

2 Likes

loadstring(code) will return a function that when invoked will run the loaded code and return any data from it. I think this is how you need to use it:

local def = assert(loadstring(code))()
4 Likes

That works! Nice! Good to know!

local script = ("/main/files/level_1.lua")
local code = sys.load_resource(script)
local def = assert(loadstring(code))()  
print(def.layers[1].type)

DEBUG:SCRIPT: tilelayer
3 Likes

Since Defold doesn’t yet have its collision information for tiles available to scripting directly (afaik), I’m adding support for tiled importer to get meta tile information for a special layer. Then when moving around games can check meta data for collisions or special things such as spawn rates for mobs.

Going to work on it a while longer before sharing new version.

3 Likes

Delayed function calls on a timer. A proper way to do this is in Defold backlog. It’s been suggested until then to use go.animate. This module by @britzl is better.

local timer = require ("main.timer")

function hej()
	print("hej!")
end

function init(self)
	timer.seconds(3, hej)
end


function update(self, dt)
	timer.update(dt)
end

7 Likes

Searching the site for Defold answers.

With Google, search the entire domain with this

site:defold.com keywords

It will search the public docs and the forum. Remember that Google doesn’t have super fresh results always so if you can’t find answers from that search the forum or the docs directly.

3 Likes

If you want to use distance field fonts be sure to remember to change their material too.

If you forget to you’ll end up with text looking like this.


2 Likes

If you are not using hot code reloading you absolutely should be. It can save you a ton of time when you are working on specific areas of your code without needing to rebuild over and over again. I changed my key map for hot code reload to F2.

3 Likes

Having different screens, loading different screens, switching between screens.

This post references this thread. As well as the official docs:

Think of collections as a way to represent a screen. Main menu, game, splash …

Then you have a central script which loads or unloads collections as you switch screens.

If you would like you could add a super light weight inbetween screen which acts as loading screen -
or have unique light weight loading screens depending on what kind of activities you are going to,
and some screens you go to you may already know they are super light weight and don’t need a loading screen inbetween.

Remember that some screens you may want to not be screens you switch to but ones which act as overlays.

  1. The parent object’s script of the collection proxies must ask for input if you want the child screens to be able to get input
  2. If you get the below error edit your .collection files in a text editor and change their name: from default - the file name is NOT this name

ERROR:GAMEOBJECT: The collection 'default' could not be created since there is already a socket with the same name.

Remember that even in the different screens you may be loading / unloading proxy collections as you need them for that screen.

Below is an example showing how to switch between screens - but as mentioned there are further improvements you can make.

ScreenSwitcher.zip (31.6 KB)

7 Likes