Defold 1.12.0 BETA

For now, we’ll leave this update as-is, as it’s still an improvement from before:

  • Allowing sprite frustum culling
  • fixed_update() called before update()
  • Internal code cleanup and optimizations around update flow

Our main focus was to get sprite culling working, and it sparked all the other changes due to code cleanup.
But I agree with your comment, we feel there’s more to be done, but we need to break it up into multiple tasks.

We’d like to revisit the bigger discussion about how the update flow should work in a task for next year, and we’ll collect information from our users on use cases, so that we can make sure we consider all scenarios.

9 Likes

I’m using it and haven’t noticed any problems in 1.12.0 yet. I’ll let you know if I do.

Works as expected for me in a project with a mix of regular, fixed and now late updates. I’m looking forward to the updated life cycle docs.

3 Likes

Found a small issue; tilesource animations don’t preview when I press the Space key. I’m using the latest 1.12.0 beta on Linux Mint. I just tried it on 1.11.2 and it works fine, so one more for the pile I guess, once you guys come back from the holidays!

Btw, Happy Holidays, Team Defold and a Happy New Year!

6 Likes

After the question from @Mathias_Westerdahl (below) I realise that I was wrong to post here as it is not related to this Beta. And the content is not useful for this topic (now removed), apart from the minor question about why these warnings now occur:

WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::arrayBaseOffset has been called by com.google.protobuf.UnsafeUtil$MemoryAccessor (file:/path/bin/DefoldBeta/Defold/packages/defold-6c05f82cfcc90267dbeb338dedcd1e12fdc5ff13.jar)
WARNING: Please consider reporting this to the maintainers of class com.google.protobuf.UnsafeUtil$MemoryAccessor
WARNING: sun.misc.Unsafe::arrayBaseOffset will be removed in a future release
2 Likes

Is this a beta issue, or do you have that with 1.11.2 as well?

1 Like

Just checked 1.11.2
I have made a mistake, the errors also occur in 1.11.2 The only thing that does not is the Unsafe warning.
Remiss of me. It is not a Defold ticket issue because it is a complete show stopper for me; therefore it would of been noticed if it was not just me. I am looking for clues for how to fix, probably after Christmas, everyone should be doing other-things now :slight_smile:

1 Like

The warning isn’t an issue. It comes from an external library, and it has already been reported (Java 25 complains when running bob.jar · Issue #11654 · defold/defold · GitHub).

It is not a Defold ticket issue because it is a complete show stopper for me;

Not sure what you mean here?

Defold was not working at all for me (aka show stopper) and since no one else has any issues the logical conclusion is that I am doing something wrong. This I think is the case now! It looks like I misunderstood at least some of the messages out of Defold. I need to find out what they mean and not just guess! For example Google AI tells me that:

2025-12-24 11:09:38.084 ERROR default    editor.scene - {:line 239, :message "skipping renderable", :pass-name "outline", :render-fn #object[editor.camera_editor$render_frustum_outlines 0x56c1e6da "editor.camera_editor$render_frustum_outlines@56c1e6da"], :ex-data nil}

Is an object being skipped in an outline render pass. So not related to my issue, and not a big deal, probably. I don’t understand javafx at all, I need to learn:-)

1 Like

A fix has been pushed, and should be available in ~1 hour.

3 Likes

I’ve just migrated a physics-heavy project to 1.12.1 and it’s working well. Thanks for these improvements!

A question that arose when migrating, related to recent 1.11 features:

What exactly does go.update_world_transform impact? I’m using it for custom physics, like when comparing the world-space positions of two objects. Is the only downstream effect of calling it making sure that go.get_world_position is accurate? Or does it also impact physics? For example:

physics.raycast(start_pos, end_pos, groups) -- hit obj_a
go.set_position(new_pos, obj_a) -- move out of the way of the ray
-- go.update_world_transform(obj_a) -- is this necessary?
physics.raycast(start_pos, end_pos, groups) -- does this hit?

I’m trying to mitigate the “view of world-transform physics is always a snapshot that’s one-frame back” issue, so that ideally regardless of whether I’m using physics.raycast or go.get_world_position, my view of the physical state in world coordinates is consistent and up-to-date.

A separate question about handling input now:

When will on_input be called, relative to fixed_update, update, and late_update? Are repeated inputs guaranteed to be sent at least once per update callback? My current input handler tracks state internally:

  • on_input → manage internal input state (and be sure to never miss a release, must get this bookkeeping right)
  • fixed_update → use the stored input state to update physics

I would love to delete a bunch of code, and to instead simplify to:

  • late_update → clear all input state
  • on_input → build up input state
  • fixed_update → use single frame of input state to update physics

Editing to add a third question I just ran into:

Similar to the input question, relative to the new lifecycle callbacks, when are physics messages like “contact_point_response” sent?

It will like you say make sure that go.get_world_position() is accurate, but I think if called in update() it will also impact the physics update since positions of kinematic and dynamic bodies have changes. @Mathias_Westerdahl and/or @Pawel can confirm this.

Input is handled before any of the update callbacks.

Yes, if you have repeat interval set to 0 in game.project

Physics messages will be sent after the physics engine has been updated.

We are working on updated documentation: Updated Application Lifecycle for Defold 1.12.0+ and added new diagrams. by paweljarosz · Pull Request #590 · defold/doc · GitHub

2 Likes

Hi everyone!
Could you please tell me the correct way to remove a font?

go.property("franxurter", resource.font("/assets/fonts/franxurter.font"))
go.property("far_roya", resource.font("/assets/fonts/far_roya.font"))
go.property("ttf_franxurter", hash("/assets/fonts/franxurter.ttf"))
go.property("ttf_far_roya", hash("/assets/fonts/far_roya.ttf"))

---@param self bootstrap
function init(self)
	font.add_font(self.franxurter, self.ttf_franxurter)
	font.add_font(self.far_roya, self.ttf_far_roya)
	msg.post(MAIN_PROXY, "load")
	self.last_input = socket.gettime()
end


function final(self)
	font.remove_font(hash("/assets/fonts/franxurter.fontc"))
	font.remove_font(hash("/assets/fonts/far_roya.fontc"))
end

i get error

main/bootstrap.script:28: bad argument #2 to 'remove_font' (hash or string expected expected, got no value)
stack traceback:
  [C]:-1: in function remove_font
  main/bootstrap.script:28: in function <main/bootstrap.script:27>

**Also, is it possible to leave the prebuilt font empty or with just one character, so that resources are loaded only from the TTF?
If I leave it with a single character, I get an error:
**

ERROR:GRAPHICS: OpenGLSetTexture(4339): gl error 1281: GL_INVALID_VALUE

Assertion failed: (0), function OpenGLSetTexture, file graphics_opengl.cpp, line 4339.
INFO:CRASH: Successfully wrote Crashdump to file: /Users/salavatrakhmanov/Library/Application Support/Defold/_crash
ERROR:CRASH: CALL STACK:

ERROR:CRASH: 0   dmengine                            0x0000000100552b64 _ZN7dmCrash7OnCrashEi + 112
ERROR:CRASH: 1   libsystem_platform.dylib            0x00000001992e3744 _sigtramp + 56
ERROR:CRASH: 2   libsystem_pthread.dylib             0x00000001992d9888 pthread_kill + 296
ERROR:CRASH: 3   libsystem_c.dylib                   0x00000001991de850 abort + 124
ERROR:CRASH: 4   libsystem_c.dylib                   0x00000001991dda84 err + 0
ERROR:CRASH: 5   dmengine                            0x0000000100597098 _ZN10dmGraphicsL16OpenGLSetTextureEPvyRKNS_13TextureParamsE.cold.11 + 0
ERROR:CRASH: 6   dmengine                            0x000000010028ae38 _ZN10dmGraphicsL16OpenGLSetTextureEPvyRKNS_13TextureParamsE + 4376
ERROR:CRASH: 7   dmengine                            0x0000000100461c78 _ZN8dmRender15AddGlyphToCacheEPNS_7FontMapEjyP9FontGlyphi + 984
ERROR:CRASH: 8   dmengine                            0x00000001004644cc _ZN8dmRender20CreateFontVertexDataEPNS_17FontRenderBackendEPNS_7FontMapEjPKcRKNS_9TextEntryEffPhj + 1500
ERROR:CRASH: 9   dmengine                            0x0000000100460b50 _ZN8dmRenderL22FontRenderListDispatchERKNS_24RenderListDispatchParamsE + 744
ERROR:CRASH: 10  dmengine                            0x0000000100455e30 _ZN8dmRender14DrawRenderListEPNS_13RenderContextEPNS_9PredicateEPNS_19NamedConstantBufferEPKNS_14FrustumOptionsENS_9SortOrderE + 3036
ERROR:CRASH: 11  dmengine                            0x0000000100458b18 _ZN8dmRender13ParseCommandsEPNS_13RenderContextEPNS_7CommandEj + 636
ERROR:CRASH: 12  dmengine                            0x000000010045d358 _ZN8dmRender26UpdateRenderScriptInstanceEPNS_20RenderScriptInstanceEf + 132
ERROR:CRASH: 13  dmengine                            0x00000001003736ec _ZN8dmEngine4StepEPNS_6EngineE + 1404
ERROR:CRASH: 14  dmengine                            0x0000000100373c74 _Z14dmEngineUpdatePN8dmEngine6EngineE + 32
ERROR:CRASH: 15  dmengine                            0x0000000100374940 _ZN8dmEngine7RunLoopEPKNS_13RunLoopParamsE + 104
ERROR:CRASH: 16  dmengine                            0x00000001003748c0 _Z11engine_mainiPPc + 104
ERROR:CRASH: 17  dyld                                0x0000000198f11d54 start + 7184
ERROR:CRASH: 

The syntax is wrong, you need to pass both font collection and the ttf font:

font.remove_font(fontc_hash, ttf_hash)

It should be possible to put a single character (e.g. ‘.’).
The game shouldn’t crash of course.
Please report the crash with a repro project on GitHub!

2 Likes

Done, thanks!

found issue with rtl ligatures

1 Like

I think it may be an issue with your font far_roya.ttf?
If I use Noto Sans Arabic (https://fonts.google.com/noto/specimen/Noto+Sans+Arabic?preview.text=قلک%20انعام&lang=fa_Arab), it shows fine for me:

Edit 1: Possibly it’s something with the Skribidi library that doesn’t understand the far_roya.ttf :thinking:
Edit 2: But it seems other tools struggle with that phrase? FarRoya Fonts Downloads - OnlineWebFonts.COM

3 Likes

Thanks!

These docs are a huge improvement over the current lifecycle page. If anyone else wants to check out a preview, here’s the rendered markdown.

On lua fixed_update vs internal physics engine “Fixed Update”

I noticed that lua scripts run fixed_update N times as step 1, then the actual physics engine runs its “Fixed Update” tick N times as step 3. Is this really how it’s designed? If so, won’t that cause impossible-to-fix problems for games where physics are important?

From the lua fixed_update perspective, the abstraction is that the game is running at a steady tick rate (say 60 Hz). The expectation is that after each of those fixed_update calls are made, the engine completes a physics “Fixed Update” tick to integrate the changes to physics / dispatch physics messages for resolution. That enables the abstraction of continuous, steady physics ticks. Without pairing a fixed_update with a physics engine tick, we lose the ability to actually have a proper simulation timestep, because the simulation becomes dependent on the framerate/dynamic update speed. For example:

Let’s say our fixed_update applies gravity to a kinematic sphere that is sliding down a 45-degree hill. Here’s a frame where N=2:

  • fixed_update sees sphere at position 00, moves down to 01
  • fixed_update sees sphere at position 01, moves down to 03 (gravity compounds velocity)
  • physics engine Fixed Update
    • on_message “contact_point_response” moves the sphere right from 03 to 33, projects velocity along the tangent
  • physics engine Fixed Update
    • collision already resolved, no movement, stays at 33
  • (new iteration of the update loop)
  • fixed_update sees the sphere at position 33

Now the exact same code across frames where N=1:

  • fixed_update sees sphere at position 00, moves to 01
  • physics engine Fixed Update
    • on_message “contact_point_response” moves the sphere from 01 to 11, projects velocity along the tangent
  • (new iteration of the update loop)
  • fixed_update sees sphere at position 11, moves to 12
  • physics engine Fixed Update
    • on_message “contact_point_response” moves the sphere from 12 to 22
  • (new iteration of the update loop)
  • fixed_update sees sphere at 22

Despite running the same code from the same starting situation, our first three fixed_update callbacks see this state:

  • N=2: 00, 01, 33
  • N=1: 00, 11, 22

Since the purpose of fixed physics updates is stability and determinism, it seems to me that either I misunderstand the in-progress docs and this isn’t how 1.12 works after all, or the plan for how fixed_update interops with the physics engine is infeasible / not really any improvement over just scaling dt. That’s essentially what is being done - just with more discrete steps and overhead. Batching 3 steps of (dt) might as well just be (dt * 3) in a single non-fixed update call, if there’s no physics engine tick between the fixed updates.

On the docs, @Pawel if you’re looking for any feedback:

  • Starting with a high-level overview of the broad phases is fantastic. The high-level diagram makes sense.
  • The start of the “Initialization” phase, including its diagram, weren’t clear to me initially, but the subsequent sections are solid. Maybe consider lifting the informative sections up like this by compressing the intro?
    • Initialization
      • Initializing the game is done in three phases: pre-init, collection init, and post-update: (no diagram)
      • Pre-init phase
        • The text & diagrams here are clear. I really appreciate this sentence in particular: “The first user-controllable entry point, at the end of engine initialization, is the call to the current render script’s init() function.” (TIL)
      • Collection init phase
        • Also clear.
      • Post update phase
        • “Since your init() code can post new messages, tell factories to spawn new objects, mark objects for deletion and perform many other actions, the engine performs a full Post Update pass next. This is the same pass that is performed after each Update Loop step.” … very useful clarification.
        • This seems important, and there are visual representations of message dispatch in the other diagrams, but I noticed that the post-update diagram didn’t show anything about this: “Note that the post-update pass includes a “dispatch messages” sequence”
        • The code sample and clarifying that a whole collection proxy lifecycle can complete before anything ever updates is interesting, but this part of the text should be deleted: “Studying the diagram above reveals that”
      • Dispatching messages
        • This section doesn’t fulfill the promise made in the intro (that the doc will be organized into 3 sections: init, update, finalize. Its contents are useful but it sits in a place where naturally an “Update” section should go. Since there’s already a paragraph about this in the “Intro” section, I would recommend tightening this section up & then reparenting it in a sub-section (### rather than ##) right after “This pass carries out message delivery” above. The “Dispatch Messages Phase” diagram can go, since the list below it is clearer and covers all the same information.
      • Update Loop
        • This is a good diagram. The clarifying text under it is helpful (clarifying that all types of user-controllable updates are represented by one block)
        • The sub-phases of the update loop should be sub-sections (###) instead of at the same level of hierarchy (##).
        • Input phase text is really well-written, and helped clarify for me some of the nuances of how input works in a concise way.
        • This part of the “update phase” text is hard for me to parse: “During the Update phase the Lua callbacks are called in the order in loops for each component type (usually script)”
        • This section mentions the recursive nature of collection proxies vs the “main collection” several times. It left me wondering how nested collections are treated. If I build my bootstrap collection out of many different collections, and each of them has sub-collections, how does the engine treat that? During runtime, are they all essentially one big collection/world?
          • From the text: “You should not assume that the engine updates objects belonging to the same collection in a certain order.” Does this imply that the engine does update objects belonging to different collections in a certain order?
        • Consider mentioning fixed_update directly in the physics sub-section, instead of in a sidenote.
        • All the instances of “if needed” can probably be dropped from the transforms section.
        • This text could be clarified: “Before each component-type update” … does that mean the update phase we’re talking about right now? Or the specific update() function? Or the fixed_update() function? etc.
        • “There is one additional final transforms update at the end” → at the end of what?
        • The descriptions and in-order tables for the update steps run are fantastic!
8 Likes

Thank you very much @Hunter_Loftis, I’m looking into your feedback now :wink:

1 Like

Wow late_update makes tracking physics objects with a smooth camera so much simpler! Thanks for that addition @ekharkunov

3 Likes