Skip to content

Native Defold crash when looping GO animations with regular panthera.OPTIONS_LOOP #37

Description

@NANAMINER

Summary

I am seeing a native Defold engine crash while playing Panthera GO animations with regular panthera.OPTIONS_LOOP.

The crash is not a Lua error. The game closes with a native crashdump, and the visible stack points to Defold timer/script callback execution. Based on isolation tests, the crash appears to be connected to Panthera's regular loop restart behavior for GO animations.

I am attaching:

  • A minimal Defold reproduction project.
  • A video showing the crash.
  • Screenshots.
  • Crash log text / call stack.
  • Notes from the original project investigation.

Minimal Reproduction Project

The attached repository contains a minimal scene with one hero.collection and one Panthera animation file.

The reproduction script intentionally does only this:

  1. Creates a Panthera GO animation state:
self.animation = panthera.create_go(hero_panthera)
  1. Starts idle with regular loop:
panthera.play(self.animation, "idle", panthera.OPTIONS_LOOP)
  1. Repeatedly switches between idle and move, also using regular loop:
panthera.play(self.animation, "move", panthera.OPTIONS_LOOP)
panthera.play(self.animation, "idle", panthera.OPTIONS_LOOP)

There is no manual movement, no manual rotation, no extra go.animate, and no go.cancel_animations in the final minimal repro. The crash still happens.

How To Reproduce

  1. Open the attached Defold project.
  2. Build and run it.
  3. Let it run for some time.
  4. Watch the console logs. The script prints animation switches like:
DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=80
DEBUG:SCRIPT: [PantheraCrashRepro] play idle switch=81
DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=82
  1. Eventually the native crash occurs.

Important: the crash timing is random. Sometimes it happens quickly, sometimes after many switches. On my machine, the minimal repro crashes reliably if left running long enough. In the original project, it was also reproducible reliably over time.

Expected Result

The animation should keep looping and switching indefinitely without a native crash. If there are any errors in the user's code, a Lua error should be logged to the console.

Actual Result

At a random moment, the game crashes natively.

Example crash log:

DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=80
DEBUG:SCRIPT: [PantheraCrashRepro] play idle switch=81
DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=82
INFO:CRASH: Successfully wrote Crashdump to file: /Users/nanaminer/Library/Application Support/Defold/_crash
ERROR:CRASH: CALL STACK:

ERROR:CRASH: 0   dmengine                            0x0000000104ad601c _ZN7dmCrash7OnCrashEi + 108
ERROR:CRASH: 1   libsystem_platform.dylib            0x000000018b583744 _sigtramp + 56
ERROR:CRASH: 2   dmengine                            0x00000001049a9138 _ZN8dmScript14InvokeCallbackEPNS_15LuaCallbackInfoEPFvP9lua_StatePvES4_ + 272
ERROR:CRASH: 3   dmengine                            0x00000001049b4920 _ZN8dmScriptL16LuaTimerCallbackEPNS_10TimerWorldENS_14TimerEventTypeEjfmm + 92
ERROR:CRASH: 4   dmengine                            0x00000001049b360c _ZN8dmScript12UpdateTimersEPNS_10TimerWorldEf + 248
ERROR:CRASH: 5   dmengine                            0x00000001049a7c64 _ZN8dmScript17UpdateScriptWorldEPNS_11ScriptWorldEf + 88
ERROR:CRASH: 6   dmengine                            0x000000010489d538 _ZN12dmGameObject16CompScriptUpdateERKNS_22ComponentsUpdateParamsERNS_22ComponentsUpdateResultE + 40
ERROR:CRASH: 7   dmengine                            0x00000001048a9a00 _ZN12dmGameObjectL23UpdateComponentFunctionEPNS_10CollectionEjNS_18UpdateFunctionTypeERNS_22ComponentsUpdateParamsE + 224
ERROR:CRASH: 8   dmengine                            0x00000001048a63f8 _ZN12dmGameObject6UpdateEPNS_16CollectionHandleEPKNS_13UpdateContextE + 516
ERROR:CRASH: 9   dmengine                            0x000000010488d030 _ZN8dmEngine4StepEPNS_6EngineE + 1456
ERROR:CRASH: 10  dmengine                            0x000000010488d670 _Z14dmEngineUpdatePN8dmEngine6EngineE + 28
ERROR:CRASH: 11  dmengine                            0x000000010488e298 _ZN8dmEngine7RunLoopEPKNS_13RunLoopParamsE + 92
ERROR:CRASH: 12  dmengine                            0x000000010488e224 _Z11engine_mainiPPc + 104
ERROR:CRASH: 13  dyld                                0x000000018b1bbe00 start + 6992

Environment

Reproduced on:

  • macOS 26.5 on MacBook Pro with Apple M4 Pro.
  • Defold native desktop build.
  • The original project also reproduced the crash in Web/HTML5.
  • The crash was also observed on a phone running the Web/HTML5 build.

Minimal repro project dependency versions:

dependencies#0 = https://github.com/Insality/defold-tweener/archive/refs/tags/6.zip
dependencies#1 = https://github.com/Insality/panthera/archive/refs/tags/runtime.7.zip

Defold version used in the current repro run:

Defold Engine 1.12.4

Investigation Notes

In the original project, the crash first appeared during active gameplay while Panthera GO animations were running. Initially the scene was more complex:

  • The hero GO was moved manually every frame.
  • Panthera played a looped GO animation on the hero using panthera.OPTIONS_LOOP.
  • Gameplay produced many bounces/hits and additional go.set_position, go.set_rotation, go.animate, and go.cancel_animations.
  • There were also enemies, deleted collections, and interrupted animations.

However, after isolating the issue, the minimal repro no longer needs those gameplay operations. It still crashes with only repeated Panthera animation switching and regular OPTIONS_LOOP.

Isolation Results

The strongest findings from the original project:

  • Disabling all Panthera animations: crash was not reproduced in the tested window.
  • Hero Panthera enabled, enemy Panthera disabled: crash reproduced.
  • Dead enemy go.delete disabled/skipped: crash still reproduced.
  • Hero idle-only Panthera: crash was not reproduced in the tested window.
  • Real hero move with regular panthera.OPTIONS_LOOP: crash reproduced.
  • Real hero move without loop (options = nil): crash was not reproduced after a long run.
  • Real hero move with panthera.OPTIONS_SKIP_INIT_LOOP: crash was not reproduced after a long run.
  • All Panthera loop animations changed to panthera.OPTIONS_SKIP_INIT_LOOP: long soak test did not reproduce the crash.
  • Final minimal repro: no manual movement/rotation/extra tweens, only idle <-> move switching with regular OPTIONS_LOOP, still crashes.

Current Hypothesis

The crash seems connected to Panthera's regular loop restart behavior, not just the animation data or gameplay code.

In panthera.update_animation, when a regular loop reaches the end, it does something like:

M.stop(animation_state)

if options.is_loop then
    animation_state.current_time = time_overflow
    M.play(animation_state, animation.animation_id, options)
end

Then regular M.play without is_skip_init performs reset/init work:

if animation_state.previous_animation_id then
    panthera_internal.reset_animation_state(animation_state, animation_state.previous_animation_id)
    animation_state.previous_animation_id = nil
end

if animation.initial_state then
    panthera_internal.set_animation_state_at_time(animation_state, initial_animation.animation_id, initial_animation.duration)
end

panthera_internal.set_animation_state_at_time(animation_state, animation.animation_id, 0)

So each regular loop boundary may do a dense sequence inside/around a timer callback:

  • cancel current Panthera timer;
  • stop GO tweens for the previous animation;
  • set previous_animation_id;
  • reset GO properties from the previous animation;
  • apply initial state;
  • apply animation state at time 0;
  • start new GO tweens;
  • create a new Panthera timer;
  • immediately trigger the new timer.

panthera.OPTIONS_SKIP_INIT_LOOP avoids the reset/init part on loop restart. In my tests, using OPTIONS_SKIP_INIT_LOOP was stable, while regular OPTIONS_LOOP eventually crashed.

Workaround

In the production project, I changed all gameplay Panthera loop playback from:

panthera.play(animation, animation_id, panthera.OPTIONS_LOOP)

to:

panthera.play(animation, animation_id, panthera.OPTIONS_SKIP_INIT_LOOP)

After this change, a long soak test with all Panthera wrappers enabled did not reproduce the crash.

This workaround seems effective, but regular OPTIONS_LOOP still appears unsafe in the attached minimal repro.

Notes About Repro Reliability

The crash does not happen at exactly the same switch number every time. It is random/timing-dependent.

Examples:

  • Sometimes the minimal repro crashes in the first few runs.
  • Sometimes it may take dozens of animation switches.
  • In one run, it crashed around switch 80+.
  • In the original project, it reproduced reliably over time.
  • On my MacBook Pro M4 Pro, the attached minimal project appears to crash consistently if left running long enough.

Because of this, please let the minimal project run for a while if it does not crash immediately.

Attachments

I am attaching:

Image Image Image
  • Crash log text.
Console log (from video) DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=94 DEBUG:SCRIPT: [PantheraCrashRepro] play idle switch=95 DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=96 DEBUG:SCRIPT: [PantheraCrashRepro] play idle switch=97 DEBUG:SCRIPT: [PantheraCrashRepro] play move switch=98 INFO:CRASH: Successfully wrote Crashdump to file: /Users/nanaminer/Library/Application Support/Defold/_crash ERROR:CRASH: CALL STACK:

ERROR:CRASH: 0 dmengine 0x000000010278a01c _ZN7dmCrash7OnCrashEi + 108
ERROR:CRASH: 1 libsystem_platform.dylib 0x000000018b583744 _sigtramp + 56
ERROR:CRASH: 2 dmengine 0x000000010265d138 ZN8dmScript14InvokeCallbackEPNS_15LuaCallbackInfoEPFvP9lua_StatePvES4 + 272
ERROR:CRASH: 3 dmengine 0x0000000102668920 _ZN8dmScriptL16LuaTimerCallbackEPNS_10TimerWorldENS_14TimerEventTypeEjfmm + 92
ERROR:CRASH: 4 dmengine 0x000000010266760c _ZN8dmScript12UpdateTimersEPNS_10TimerWorldEf + 248
ERROR:CRASH: 5 dmengine 0x000000010265bc64 _ZN8dmScript17UpdateScriptWorldEPNS_11ScriptWorldEf + 88
ERROR:CRASH: 6 dmengine 0x0000000102551538 _ZN12dmGameObject16CompScriptUpdateERKNS_22ComponentsUpdateParamsERNS_22ComponentsUpdateResultE + 40
ERROR:CRASH: 7 dmengine 0x000000010255da00 _ZN12dmGameObjectL23UpdateComponentFunctionEPNS_10CollectionEjNS_18UpdateFunctionTypeERNS_22ComponentsUpdateParamsE + 224
ERROR:CRASH: 8 dmengine 0x000000010255a3f8 _ZN12dmGameObject6UpdateEPNS_16CollectionHandleEPKNS_13UpdateContextE + 516
ERROR:CRASH: 9 dmengine 0x0000000102541030 _ZN8dmEngine4StepEPNS_6EngineE + 1456
ERROR:CRASH: 10 dmengine 0x0000000102541670 _Z14dmEngineUpdatePN8dmEngine6EngineE + 28
ERROR:CRASH: 11 dmengine 0x0000000102542298 _ZN8dmEngine7RunLoopEPKNS_13RunLoopParamsE + 92
ERROR:CRASH: 12 dmengine 0x0000000102542224 _Z11engine_mainiPPc + 104
ERROR:CRASH: 13 dyld 0x000000018b1bbe00 start + 6992
ERROR:CRASH:

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions