I Compared Jmonkeyengine 3.6 with Godot 4.2

I did this because I was looking for some physics stress tests. So, as a user of JME3, I did it on my own.
Titile of Video on Youtube: Godot Engine 4.2 Vs jMonkeyengine 3.6 SDK Physics Performance Test. Bullet Physics Vs Jolt Physics.
Read Description.
If you guys want to test Godot 4 with the default physics engine (based on bullet) it can handle upto 900 to 1000 physics rigid bodies.
I love JME and I will use it. But I think I need to learn more to contribute. I will try if I could !!
Thanks Guys. This community is actually helpful. I came to this engine every time because of you guys. Its not just java you know its the language many programmers love. I found JME in 2018 and until now I watch many video related to it. visit monthly WIP and more. I will try to make a game with JME. Life is so hard and time is short. I have many dreams and many desires !!


Hello @javaFor3dGames!

I’m interested in learning how JMonkeyEngine physics performance might be improved.
However, the YouTube link you posted took me to a video comparing Godot 4 with Unity.
Did you study JMonkeyEngine performance at all?


Copy this text and search on YouTube by pasting it in search.

Godot Engine 4.2 Vs jMonkeyengine 3.6 SDK Physics Performance Test. Bullet Physics Vs Jolt Physics

The link I provided to tell you that in Unity vs Godot 4 video The default Godot 4 physics engine was able to handle 1000 physics cubes before fps dropped to 4.
But in jme vs Godot 4 video. Godot 4 with jolt physics engine was able to handle UpTo 3100 rigidbodies. If you set physics ticks per seconds to 50Hz you can get more performance.

Simply you can type " Godot 4 Vs Jmonkeyengine". There will be only one video I have uploaded. You will see the thumbnail which I have uploaded in this post. My channel name is Gamecoder77.

What I have done in this test is:

I just modified the Hello Physics Tutorial from the Jmonkeyengine documentation.
When user clicks left mouse button there will be one new brick generated. The text is also replaced by a brickCounter integer variable every time a brick is created. First brick is generated with the SimpleAppInit() code. all others with input.

I was just looking for a delay timer tutorial how it works. Timer class you may know better than any other jme user. Because I. Unity I have used Time.time etc to delay something to happen. So, to save time I used input method in jme to just not get more frustrated with reading how to do something with only code. I love this engine and I love Java. Thanks for reading this. Let me know if I have done something wrong!

Curious why you wouldn’t just include the link in your post instead of giving detailed instructions on how to find it.

Seems to me like the first post summary is:
“I made a video and want you guys to check it out. Here’s the link to a completely different video. Here’s a picture of what my video looks like, though.”

Wondering if there is a good reason.


Thank you for correcting the YouTube link. My observations:

  • The JME test shows a sudden reduction in FPS (from 59 to 17) at around 350 blocks. Before that point, FPS appears to be limited by Vsync.
  • The Godot test shows a gradual reduction of FPS, reaching 30 at around 1800 blocks.
  • In the video, each test was run just once. I wonder how reproducible the results are.
  • Which JME physics library was used: jme3-jbullet or Minie?
  • Is the source code for each test available?
  • Assuming there’s a CPU bottleneck, I’d like to know how CPU usage is split between graphics and physics in these tests.
  • Do both tests use the same physics time step?
  • The JME test uses textured bricks, whereas the Godot test uses non-textured bricks. Because of this, it’s unclear how to compare the measured FPS.
  • Due to different brick shapes and camera angles, the JME test keeps the majority of the bricks in the viewport, whereas in the Godot test, fewer bricks are visible at a time. Because of this, it’s unclear how to compare the measured FPS.

Test 2 is done. I’m sending you the link.

Check out the following things in Godot 4 vs JME test.

  1. Godot is using Vulkan as Backend renderer called Forward+
  2. Godot window size is 1280x720 and the JME size in my test is 800x600 like or so
  3. Godot is using Jolt Physics which is faster than Bullet in many tests done by many devs
  4. But If I use Godot Bullet Physics it will be like 900 to 950 max rigid bodies it can handle at 5 to 6 FPS.

All I say is that people from Unity who left Unity Engine and Now using other Free & open source engines criticising these engines like Godot, Stride Engine (aka Xenko) and other engines which are using Bullet physics. After testing Jolt they have completely switched to it. There is some reasons why I previously dicussed about the Bullet and other options (Jolt, ReactPhysics3D etc_.

This test looked implausible to me, so I ran it myself.

The original poster, in his video, shows jMonkeyEngine dropping textured boxes onto a textured surface, whereas his Godot example is plain coloured boxes onto a plain coloured surface. I tried to reproduce his Godot example. In the video I’m dropping one box each time around the update loop, which is a little fast; in the code pasted below, I drop one box every hundred milliseconds… As you’ll see, even dropping one box every update loop, there’s no slowdown below the 60 FPS I’ve asked to until I’m tracking over 1700 boxes, and at 3,000 boxes I’m still seeing above 30 FPS.

My code is as follows:

(ns examples.beginner-tutorials.hello-dropper
  "Adapted from Ertugrul Cetin's Clojure version of https://wiki.jmonkeyengine.org/docs/3.3/tutorials/beginner/hello_physics.html"
  (:require [java-time.api :refer [after? instant millis plus]]
            [jme-clj.core :refer [add-control add-to-root attach attach-child
                                  bitmap-text box bullet-app-state call* cam
                                  defsimpleapp detach-all-child geo get*
                                  get-state gui-node load-font look-at
                                  material rigid-body-control set* set-state
                                  setc sphere vec3]])
  (:import (com.jme3.math ColorRGBA Vector3f)))

(def brick-length 0.5)
(def brick-width 0.5)
(def brick-height 0.5)

(def interval
  "Drop interval in milliseconds"

(defn init-materials []
  {:wall-mat (set* (material "Common/MatDefs/Misc/Unshaded.j3md") :color "Color" ColorRGBA/Red)
   :stone-mat (set* (material "Common/MatDefs/Misc/Unshaded.j3md") :color "Color" ColorRGBA/Gray)
   :floor-mat (set* (material "Common/MatDefs/Misc/Unshaded.j3md") :color "Color" ColorRGBA/Blue)})

(defn- make-brick [loc box* wall-mat bullet-as]
  (let [brick-geo (-> (geo "brick" box*)
                      (setc :material wall-mat
                            :local-translation loc)
        brick-phy (rigid-body-control 2.0)]
    (add-control brick-geo brick-phy)
    (-> bullet-as
        (get* :physics-space)
        (call* :add brick-phy))))

(defn- init-floor [bullet-as floor floor-mat]
  (let [floor-geo (-> (geo "Floor" floor)
                      (set* :material floor-mat)
                      (set* :local-translation 0 -0.1 0)
        floor-phy (rigid-body-control 0.0)]
    (add-control floor-geo floor-phy)
    (-> bullet-as
        (get* :physics-space)
        (call* :add floor-phy))))

(defn drop-brick [bullet-as box* wall-mat] 
    (make-brick (vec3 0 (* 20 brick-height) 0) box* wall-mat bullet-as))

(defn simple-update [_tpf]
  (let [{:keys [box boxes boxes-text bullet-as last-drop wall-mat]} (get-state)
        now (instant)]
    ;; (println (format "Last drop `%s`; now `%s`." last-drop now))
  (cond (nil? last-drop) (set-state :app :last-drop now)
        (after? now (plus last-drop  
                      (millis interval))
                ) (do
                       (set* boxes-text :text (format "%d boxes" boxes))
                       (drop-brick bullet-as box wall-mat) 
                       (set-state :app :last-drop now)
                       (set-state :app :boxes (inc boxes))))))

(defn init []
  (let [bullet-as (bullet-app-state)
        bullet-as     (set* bullet-as :debug-enabled true)
        box*      (box brick-length brick-height brick-width)
        floor     (box 10 0.1 5)
        gui-font    (load-font "Interface/Fonts/Default.fnt")
        size        (-> gui-font (get* :char-set) (get* :rendered-size))
        boxes-text  (bitmap-text gui-font false)
        boxes-text'  (-> boxes-text
                        (set* :size size)
                        (set* :text "Starting...")
                        (set* :local-translation 300 (get* boxes-text :line-height) 0))]
    (attach-child (detach-all-child (gui-node)) boxes-text')
    (attach bullet-as)
    (setc (cam) :location (vec3 0 16 24))
    (look-at (vec3 2 2 0) Vector3f/UNIT_Y)
    (let [{:keys [wall-mat stone-mat floor-mat]} (init-materials)] 
      (init-floor bullet-as floor floor-mat)
      (drop-brick bullet-as box* wall-mat) 
      {:box box* 
       :boxes 1
       :boxes-text boxes-text'
       :stone-mat stone-mat 
       :wall-mat wall-mat
       :bullet-as bullet-as})))

(defsimpleapp app :init init :update simple-update)

That sounds much better. I wonder if there is a way to run the test in headless mode, so none of the graphics-related stuff gets in the way.


I have posted the plain color cube test also.

1 Like

What are your PC specs.
And kindly post java code. If you can. Upload your project on GitHub with Java Ant. Not with Gradle or something else. Kindly if possible provide me jmonkeyengine sdk project with Java ant on GitHub paste link here. So I can test it. I want to make a game and it will require many npcs fighting each other in groups.

1 Like

Ant is not really widely used these days. You’re unlikely to get people to provide things built with ant

OK, I reran the same code on my little laptop this morning. The laptop has 16Gb, 4 processor cores, no separate GPU, total 17,559 bogomips:

simon@oculist:~/workspace/jme-clj$ sudo dmesg |grep -i bogo
[sudo] password for simon: 
[    0.064370] Calibrating delay loop (skipped), value calculated using timer frequency.. 4389.82 BogoMIPS (lpj=8779648)
[    0.070178] smpboot: Total of 4 processors activated (17559.29 BogoMIPS)
simon@oculist:~/workspace/jme-clj$ free -m
               total        used        free      shared  buff/cache   available
Mem:           15943        5735        2640         805        8712       10208
Swap:            975           1         974

On this machine there’s slowdown after about 800 boxes, and by 2000 boxes it’s down to 20 frames per second.

I ran the performance monitor, and noted that when slowdown occurred the process was saturating one processor core, while the remaining three were lightly loaded. This implies the physics engine is not parallelising its operations at all.

So clearly a physics engine which did parallelise better could do better. As you can see from the screenshot, I’m currently using the jbullet physics engine. @sgold, does Minie parallelise better? @ertugrulcetin, how is your current work on converting jme-clj to Minie going, and could you use help?

Note: to run my code, first install leiningen. Then do the following:

git clone https://github.com/simon-brooke/jme-clj.git
cd jme-clj
git checkout develop
lein repl
(use 'examples.beginner-tutorials.hello-dropper :reload)
(start app)

Thanks. Let me test. Can you exactly tell what processor and GPU your laptop have.
Like Core i ??? Processor model etc. and also GPU intel iGPU model ?
I am using very old hexa core Xeon X5670 Processor which can handle many things smoothly for low poly games. I am using Unity and Unreal 4 on this machine. with 14GB RAM and 2GB Nvidia GTX 1050.

Hi all.
I made my own little test for this with jME3.6.1 and Minie-8.0.0.
Here is a video and some links of the build application for windows and linux.

Windows: jme-physics-test-windows.zip - Google Drive
Linux: jme-physics-test-linux.zip - Google Drive

Physics settings:

And the video:

And my PC specs:
INFO: OpenGL Renderer Information

  • Vendor: Intel
  • Renderer: Mesa Intel(R) Xe Graphics (TGL GT2)
  • OpenGL Version: 4.6 (Compatibility Profile) Mesa 23.2.1-1ubuntu3.1~22.04.2
  • GLSL Version: 4.60
  • Profile: Compatibility

Thank you very much. Great work

My desktop machine has

simon@mason:~$ sudo dmesg | grep -i bogo
[    0.397885] Calibrating delay loop (skipped), value calculated using timer frequency.. 7186.51 BogoMIPS (lpj=14373024)
[    0.533913] smpboot: Total of 12 processors activated (86238.14 BogoMIPS)
simon@mason:~$ free -mh
               total        used        free      shared  buff/cache   available
Mem:            62Gi       2.5Gi        58Gi        22Mi       2.9Gi        60Gi
Swap:          976Mi          0B       976Mi
simon@mason:~$ lspci | grep VqGA
06:00.0 VGA compatible controller: NVIDIA Corporation GP104 [GeForce GTX 1070] (rev a1)

In other words, this is a nearly ten year old machine I built to play The Witcher III; it’s not state of the art.

What’s clear when watching the monitor is:

  1. The physics engine does not just camp on one processor the whole time. Rather, it moves around between processors;
  2. It does, however, only use one processor at a time;
  3. Processor load scales fairly linearly with the number of boxes released;
  4. It is when the processor it’s using saturates that frames start to drop;
  5. Memory usage is not an issue, with this level of objects.

Thanks for doing this.

With your executable, on my desktop, I’m seeing frames per second drop below 60 at about 1,700 boxes, and above that number the framerate drops quickly, to 14 at 2,000 boxes. However, none of the processor cores is completely saturating (although it’s close), so while processor performance certainly is a bottleneck, it may not be the only one.