What should and shouldn't go in the update loop?

I am coding without the playcanvas editor, so I don’t use createScript at all. Rather I use the update handler from pc.Application. Almost all of my objects have a reference to the pc.Application, so they can all attach their own handlers to the update event.

My question is (this really applies to any engine) what should go in to the update handler and what shouldn’t?

For example, I created a first person camera. I added handlers outside of the update handler for keydown that calls camera.setPosition(x, y, z). But for rotating the camera I call this.camera.setLocalEulerAngles() within the update handler if free look has been enabled (bool check).

So I did camera movement outside of the update event and camera rotation within. They both seem to work. What is the general guideline? What if I want to just move an object around, does that go in the update event ?

1 Like

Hi @tones31,

That’s a good question. The update loop is basically a callback that’s called each the engine renders a new frame to be displayed on canvas.

Animation in games follows the same pattern as TV/movies: still images are displayed fast enough (20-60 times per second) to give the illusion of movement.

So, for any of your methods that involve something moving or changing something gradually in your scene, you should be using some form of the update method.

Your input handlers (keydown) will execute as soon as the input device registers new input (mouse click, mouse move, keydown etc).

Some other APIs have their own internal update method, for example Playcanvas tweens. To animate an object with a tween you setup its settings and then call start(). The tween library will start positioning/rotating/scaling that object once per frame until it reaches the final value.

I hope this makes sense.

2 Likes

Can you clarify this?

Let’s say PC guarantees to emit update 60 times per second in the perfect world. Are the PC input handlers also on this exact same loop (as opposed to document.addEventListener())?

I think so, but this is quite easy to test:

  • put one console.log() in your update loop
  • another one in your keydown event handler

And check how often each one fires.

Good idea… The answer is no! Update is 60 times per second, but mousemove event from the engine itself may be over 1000 times per second.

Thanks for sharing, it makes sense that event handlers will fire as soon as the input device fires the event. I am going to edit my initial message above.

Not sure how you can get 1000 mouse moves in between a frame render, testing it now seems quite impossible.

But if you would like to get input only once each time your app update method is called, check the FPS movement tutorial.

This pattern can easily work for this:

// update code called every frame
FirstPersonMovement.prototype.update = function(dt) {
    
    // Use W-A-S-D keys to move player
    // Check for key presses
    if (this.app.keyboard.isPressed(pc.KEY_A) || this.app.keyboard.isPressed(pc.KEY_Q)) {
        x -= right.x;
        z -= right.z;
    }

   // etc.

Thanks. It sounds like any time I want to update the display of the game, I should move that function within the update loop, otherwise things will not be in sync.

1 Like

What is important to get smooth movement is to take into account the delta time (dt) since the last frame has been drawn. This isn’t fixed, the engine will try to render frames as quickly as possible.

This ensure that each time the app renders a new frame, all entities are animated at a constant rate.

2 Likes

Wow, didn’t know PlayCanvas had Tween built-in! I’ve been following what the orbit-camera.js script does with an external Tween script, ran into issues with multiple Tweens stopping the other from updating and had to switch to calling tween.update in the script update() function. Good to know!

Hi @Chris,

Actually not built-in in the engine, but there is an easy to use official wrapper that extends the pc.Entity class.

1 Like

Oh right, I see that now.

1 Like