Understanding new render script and camera projection

Before Defold 1.6.2 (when new render script was introduced) I needed only to write:

msg.post("go#camera", "acquire_camera_focus")
msg.post("@render:", "use_camera_projection")

And camera would follow the game object where it was attached. Now, the behaviour changed and in the very same project (platformer tutorial), when I post “use_camera_projection” → I get black screen.

When I post only to camera (without posting to render socket) I get behaviour from before - the view is following the camera attached to that go (which I’m moving around with keys - it’s a hero go)

Do you know already what changes in the render script cause this?

The other problem is that when the camera is attached to the game object I’m moving around - there is a noticeable lag:

Apparently, it is not visible on the gif, it’s visible on a real monitor though :confused: But you can notice some stuttering when it’s falling down.

On my screen it has visibly two sprites in two different positions (so quick, that it’s probably frame after frame) both when jumping or moving left/right, like, you know, the sprite is “doubled”, changing position really quickly in reference to the camera, or it’s the camera that is doing so in reference to sprite/go.

With the old script I didn’t have such issues :frowning:

Repro:

To the project: https://github.com/paweljarosz/defold-platformer-tutorial

Add camera to the hero game object, below separate game object (to move the camera):

image

And add line: msg.post("go#camera", "acquire_camera_focus") to the hero.script init().

I’ll check and come back to you

1 Like

I opened your project in Defold 1.6.0.
I’m testing in 1.6.0 version just to make sure that everything works the same as before. It’s easy to do because the new render script is compatible with an old Defold
Steps I do:

  1. Open project
  2. Add go and camera to it
  3. Add
msg.post("go#camera", "acquire_camera_focus")
msg.post("@render:", "use_camera_projection")
  1. Run and

Why?
let’s take a look:


Here is camera and it looks from (0,0) somewhere…
Let me fix it:

and now it works fine:

Now if I put it into hero object it follows hero:

like this
Dec-29-2023 20-49-19

When I change render script to the new one in this project and in Defold 1.6.0 - it works the same way.
Here is my modified version I’m playing with:
new-render-script.zip (247.8 KB)

This is the first part, where we see that the new render script works the same way as the old script in 1.6.0


I can reproduce this issue you see, and I reproduce it with old render script and in 1.6.0 (again, I test in 1.6.0 to make sure it’s not a new change and isn’t changes related to the new render_script)

I’m able to record it with my phone and camera in 60 fps mode:

But screen capture doesn’t help here and it looks more like jittering:

Which makes me think that the issue somehow related to the monitor update.
I found that if I turn off Vsync in game.project - it works perfect.


To make sure, I repeat my test with the old and the new render script in 1.6.3 beta, and got exactly the same results for both cases.

3 Likes

Now I want to ask you @Pawel and @R0ck0.R4m4 (because of Camera Help) what OS you both use? Because I’m testing it on MacOS.

2 Likes

Windows 11 currently, I will follow your reproduction once again :wink:

EDIT:

Thank you for describing the steps, I followed them from scratch and I noticed:

  1. First issue I had is with the msg.post("@render:", "use_camera_projection") that was giving me black screen - I indeed misplaced the camera like you described and only now I noticed the issue… :sweat_smile: After making it correct (and I increased difference between Near and Far to see the actual frustum instead of almost “flat” plane in Editor preview) everything is as expected.
  2. After this is solved the jittering issue is no longer appearing no matter the version and render script - because I’m using the correct camera projection? At this point, I don’t know how I possibly managed to make default projection “follow” the character by only msg.post("go#camera", "acquire_camera_focus") :thinking:
  3. As constant jittering is now almost impossible to be noticed, I check turning Vsync on/off - and indeed really rarely, when Vsync is on, there might appear some stutters, but didn’t as recorded above. When it is off, I didn’t notice any yet. Later on, I will try to test also on different monitors.
2 Likes

Still have a problem here :confused:

I started my tutorial again, did as follows:

Defold 1.6.2, default render script, Windows 11.
Added hero->go->camera
Moved go to contain everything in camera’s frustum.
Added the 2 msg.post code lines.

msg.post("/go#camera", "acquire_camera_focus")
msg.post("@render:", "use_camera_projection")

Now testing with:

Vsync On: “constant” jittering, as in my previous posts

Vsync Off: I noticed there is sometimes some jittering happening, even if the Vsync is turned off - not “constant” though, but somehow random, once per few seconds. Shown below:

The laptop’s screen is 165Hz IPS QHD - maybe this is an issue? I bought it when the new render script was introduced, so therefore I suspected it at first, but maybe it’s a hardware issue?

If so - how to fix it?

Still no luck in finding out why it’s happening :frowning: Do you maybe have some ideas?

Have you verified the behavior is not present in Defold 1.6.1?

What if you print the dt from update(), do you see any significant changes in the delta times?

I also switched monitors a few weeks ago and then started to notice jittering very similar to the one you’re having. Turning off vsync seems to remove the jittering completely for me. The problem is I cannot isolate my problem to Defold – it’s happening in all glfw applications I’ve tried on this monitor.

2 Likes

I tired this and also get flickering. I am on Linux with a 60HZ display.
I suggest creating a branch with as much stuff removed as possible, that still has the problem.
Turning on Physics-debug significantly increasing the amount of flicker which occurs.
I added an update(self,dt) to print the variable dt (fixed_update is used in this game).
The flickering did not appear to correlate with significant dt variations. dt dropped as low as 0.0007 and as high as 0.05 and was usually .016

Edit: Setting Display-Update-Frequency to 60 (default 0) seems to help a lot.

1 Like

It helped me also. I didn’t see any flicker/jitter for a while now with it set to 60. Even though the monitor is described as 165Hz - when I set it to 165, the issue is visible and the sprite looks “duplicated” because flickering happens all the time. 60 - it works flawlessly. 0 - sometimes jittering happens.

I wish to understand it why something like this is happening, because I will be using it in the tutorial and I want to explain it to the viewers :sweat_smile:

I see three behaviors:

  1. :rage: First is constant flickering (a “doubled” sprite) I explained in the first post above - somehow connected to the speed of the moving sprite (the faster it moves, the more visible is distance between two sprites)
  2. :cry: Second is “sometimes” jittering - happens from time to time and looks like a “one frame lag”
  3. :smiley: Third is what I expect to see - smooth movement.

Here are my tests with numbers inside corresponding to the above behaviors (so a higher number is better) in terms of set Vsync, Defold version and set Update Frequency:

Frequency 1.6.1 - Vsync On 1.6.1 - Vsync Off 1.6.2 - Vsync On 1.6.2 - Vsync Off
0 1. :rage: 2. :cry: 1. :rage: 2. :cry:
60 3. :smiley: 3. :smiley: 3. :smiley: 3. :smiley:
165 1. :rage: 1. :rage: 1. :rage: 1. :rage:

So you see, it is not regarding Defold version (nor render script) but the Vsync and Update Frequency settings.

This a very common issue not just with Defold. Unity had this for DECADES. The camera is updating faster than physics and not getting the correct position to follow due to asking the physics engine for positions twice in a single frame. Much of what you see being “fixed” in other engines is interpolation of the camera in order to smooth jittering. This allows for faster frames rates while keeping physics at 60hz. Forcing the game to display at 60hz means the physics and visual stay in sync frame by frame. So two paths to follow, smooth your camera and keep higher refresh rates or lock physics and display together. You can find issues in all game engines with this.

5 Likes

I thought it should only regard dynamic objects, where position of the object is tied with the collisionobject - but I’m using only kinematic collision object to get info about environment (ground contact) and jittering is happening while I’m moving left/right or jumping/falling (no ground contact), so I don’t understand why sprite inside game object that is controlled by the script and position is set using go.set_position, which should have nothing to do with physics engine, is having such problems?

I thought it’s separated and I though that this:

is not valid here, because camera follows game object (being its child), not a collision object (which is child of this game object)

EDIT.

So I’m using fixed_update() to set hero’s position and when I switch to regular update() there is no jittering problem, BUT there is problem with detection collisions:

Here’s when Update Frequency is 60, later 165 (where it’s visible that multiple particelfx are triggered and on my monitor the characters “stutters”):

So anything different than 60 is problematic (I think physics update is at 60 Hz, right? )

EDIT 2.

Above is happening when Physics->Use Fixed timestamp is ON.
When I turned it Off, there is no problems in detecting collisions for Display->Update Frequency set to 60 nor 165, BUT there is collision detection problem as pictured above with it set to 0.

1 Like

Did you run your tests in the editor? If so what happens in a release build?
Debug In the editor (and out) update_frequency = 0 I get significant flicker within 15sec, without moving the player. With a release build this went away, but I can’t prove a null result!

The other thing to consider is physics setting and scale, you have it set at 1, probably should be 0.02 or 0.01, for the size of your sprites.

You set_position() in the update loop and the on_message() loop. It is common to do this. I guess it is probably fine to do this, I just wonder if there are any nuances of the application lifecycle that might cause glitches. Just a guess.

1 Like

Yes, all it regards testing in Editor [ Project->Build ]

I will try release and debug builds soon.

So far, I also noticed a significant influence of Use Fixed Timestep and type of update function (regular - update(self, dt) and fixed: fixed_update(self, dt) )used:

1.6.2

update function: regular regular regular regular fixed_ fixed_ fixed_ fixed_
Vsync: :white_check_mark: :white_check_mark: :x: :x: :white_check_mark: :white_check_mark: :x: :x:
Use Fixed Timestep: :white_check_mark: :x: :white_check_mark: :x: :white_check_mark: :x: :white_check_mark: :x:
Update Freq - 0 :smiley: :boom: :smiley: :smiley: :boom: :smiley: :boom: :rage: :rage: * :cry: :cry: *
Update Freq - 60 Hz :smiley: :smiley: :smiley: :smiley: :smiley: :smiley: * :smiley: :smiley: *
Update Freq - 165 Hz :smiley: :boom: :smiley: :boom: :smiley: :smiley: :rage: :rage: * :rage: :rage: *

asterisk: * - I couldn’t jump in that setting! :smiley: So when Use Fixed Timestep is false, but we are using fixed_update() function - I was referring to this in my previous video.

:rage: - continuous jittering/lagging of sprite against camera
:cry: - sometimes jittering happens, single frame lag
:smiley: - everything is smooth regarding sprite/camera synchronisation

When I add:
:boom: - there are problems with collision detections (multiple collisions detected and continuous problem on ground contact)
So sometimes, everything is smooth, but collision detection is problematic… :confused:

So generally - Using Fixed Timestep or not is really affecting issues with collision detection

Hmm, adjusting physics scale might really solve the issue, I’ll check.

Hmmm, maybe, but get_position() is in the same function, very close to each other, but indeed, the collisions are handled in on_message - and this is what is problematic sometimes, as in the table above. I don’t know though how to mitigate this :confused:

When I untick “Use Fixed Timestep” in game.project in combination with changing

function fixed_update(self, dt)

to

function update(self, dt)

I get no more jittering and working collision detection in all your above cases except for
Vsync: Off + Update Freq: 0.

This seems to be the settings in this platformer tutorial as well: https://github.com/defold/tutorial-platformer

1 Like

Turning off fixed update results in on_input() running multiple times between calls to fixed_update(). This results in self.ground_contact being true so self.velocity.y gets reset to zero, resulting in no jump.

Your code works with fixed update and update frequency set to 60, so I would go with that in your (excellent) tutorials, as this is all valid and fine. Don’t try to be perfect, the law of diminishing-return will get you!

5 Likes

Using regular update without Fixed Timestep on and Vsync turned on works as intended with this project for me. This is the default settings when starting a blank project in Defold as well. I would leave them set like that so a beginner can recreate this from scratch without having to make changes to the game project file.

3 Likes

I just don’t want to share something that will be causing troubles for a lot of people :smiley: Hence, the last video is not published yet, but now, after thorough testing I have more or less a clear idea on how to provide it to the viewers and not overcomplicate it :wink:
Thanks! :heartpulse:

2 Likes

In general you want all of your code executed once each frame. That means VSync On (no multiple runs between screen refreshes), regular update() (Use Fixed Timestamp off) and hoping that the game doesn’t run slower than the refresh rate.

To further ensure that the motion looks smooth you need to update the camera position after you know your character position. In game engines that sometimes might be problematic because not always you know when during the frame the physics engine code or the kinematic player update code executes.

Moreover if the speed of your character ends up being fractional (e.g. 3.5 px per frame) that would also result in visual jitter.

The fixed_update() function in my opinion is more trouble than it worth for platformers.

4 Likes