Jump to content

Weird Behavior in Phaser 3


Ahmed Khalifa
 Share

Recommended Posts

I am working on a project that uses exactly 1 group, couple of containers (around 30) containing a picture from a tiny texture and a text, and 2 graphics object.

When I select Phaser.WEBGL (Phaser.AUTO also selects WebGL), the game slows down after one minute or something. The game frame rate drop to almost 5 fps. I though there is something wrong with my code at the beginning and tried to optimize calling functions and other parts but with no affect on the final result. When I changed to Phaser.CANVAS, the game is very fast and maintaining 60 fps. 

I don't know if that is a bug in the framework or misuse in my code. I am testing on chrome browser on a Mac Book from 2015.

here is a link of the game using canvas: http://akhalifa.com/testing/reduce/canvas/

here is a link of the game using webgl: http://akhalifa.com/testing/reduce/webgl/

 

Link to comment
Share on other sites

I profiled the WebGL version for 30 seconds and in that time it spent 1631ms scripting, 124ms rendering, 225ms painting and the remaining time doing nothing. In order words, it was 91% idle. Which sounds about right for a relatively simple game like this.

The game uses a number of Text objects, so it'd be well worth swapping to use bitmap text, as each Text object causes a batch flush in WebGL. Also, make sure your Graphics objects aren't being re-drawn to each frame (i.e. if you draw something new to them, clear them first, then draw, otherwise they build up and up over time, causing loads of memory - I didn't see this in my profile though, so I don't think you're doing it)

Check you don't have any Chrome extensions installed that may be getting in the way? And profile it for yourself to see where the time is being spent.

Link to comment
Share on other sites

Thanks Rich, I will definitely try using bitmap fonts but shouldn't it slow down that much even if I am using around 30 normal font objects? It is weird that it didn't slow with time with you. Did you start profiling after the game started (after loading)? As the loading take long time and the game start to slow down after it start by a minute or something. May be it slows down when u play in it, try to remove letters to have a correct English word.

I will test the bitmap font and see although I just wanted to use normal font. Also is updating Phaser.GameObject.Text text is it intensive from GPU point of view (as I change two text objects every frame)?

Link to comment
Share on other sites

I just tried using Bitmap fonts and no difference same weird problem. And I found out that tint is not working in canvas (all bitmap text are white).

Just play the game for a minute in webgl and you will see the slow down (remove letters from the sequence to get a correct english word), tried different computers and same problem happens at all of them. I even restarted the computer.

Link to comment
Share on other sites

Tint is WebGL only.

I didn't play the game at all, I just let it run in the profiler (I started profiling after loading, not before) and didn't see any slow down on my Mac or PC, but this could easily be something else GPU / driver / extension related.

You need to profile it and see what's causing the lag.

Link to comment
Share on other sites

I just did profiling I don't know if these values are normal or not.

4430.4 ms Scripting
346.1 ms Rendering
658.5 ms Painting
3473.6 ms Other
64904.0 ms Idle
 
The average frame rate is 15 frames
 
Getting the tree call, I can see the rendering consume most of the time. Attached a picture of the call tree.
 

Screen Shot 2018-08-23 at 1.39.47 PM.png

Link to comment
Share on other sites

3ms spent on rendering per frame is absolutely fine.

Here's 30 seconds of me "playing" (I've no idea what you do in the game, so all I did was randomly click the letters)

image.png

A lot of script processing going on, but very little else.

The Chrome FPS meter stays at solid 60fps, never dropping a single frame until the progress meter (or whatever it is? a timer bar?) starts to get really small. For about the final 20 seconds before it runs out the FPS drops down lower and lower, ending around 40fps for me. As soon as the timer bar resets to full again it shoots right back up to 60fps and remains there until it gets small again.

Clicking the letters seems to make no difference to this, it just appears to be when the timer bar gets tiny.

Isolate whatever you're doing with that bar, as I reckon it's the cause.

There are no plans to add tint support for Canvas, no.

 

 

 

Link to comment
Share on other sites

Solid 60fps here (as I'd expect to be honest, it's hardly doing much):

var config = {
    width: 800,
    height: 600,
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    scene: {
        create: create
    }
};

var game = new Phaser.Game(config);

function create ()
{
    var graphics = this.add.graphics();

    graphics.fillStyle(0x00ff00, 1);

    graphics.fillRect(0, 300, 800, 64);

    this.tweens.add({
        targets: graphics,
        scaleX: 0,
        duration: 20000,
        ease: 'Linear',
        repeat: -1
    });
}

Maybe something else is going on in the game code when the timer gets small?

Link to comment
Share on other sites

That's weird because nothing different since the beginning.

So I start to try to corner the problem and I think I found it. So the background is 1x1 pixel that is scaled to cover the whole screen. Every frame, I redraw it using the correct color (green or red) without calling clear based on the current status in the map. When I commented this part, everything become very fast. So I added the clear in and everything is still fast. Is the graphics object keep track with all the previous drawings and recall all the drawing calls for every render? If that is the case, it make sense that it slows down near the end as it accumulated a lot of fillRect calls since the beginning of the game. I thought without calling clear, it just redraw the object on a texture on the previous drawings and use it.

Link to comment
Share on other sites

Graphics objects work using a command stack. So if you create a Graphics object, then draw a rectangle to it every frame without clearing it, after 1 second you'll have 60 rectangles, after 2 seconds 120 rectangles, and so on. It doesn't take too long before the GPU has to do a huge amount of work to draw all of these rectangles. If the Graphics object is constantly changing then it should be cleared each frame. Or, if all you're doing is scaling it (like in my code above) then that's fine, just draw once on it and then scale it per frame instead.

Link to comment
Share on other sites

@Ahmed Khalifa Unfortunatelly, I also needed tint for BitmapText. Not beacuse I like it, but because sponsors still want to support old devices and for some of them, running in canvas is only solution. Finally, I wrote article on how to add this functionality to Phaser 3: http://sbcgames.io/phaser-3-adjust-bitmaptext-to-support-tint-in-canvas-rendering-mode/ It works for static BitmapText, but will not for DynamicBitmapText. Whole magic behind tint in Phaser 2 / PIXI is, that it creates small canvas for tinted sprite and renders tinted version into it. It rerenders it when sprite frame changes, etc. It than takes this prerendered canvas to display it on screen instead of frame from atlas. In Phaser 2 BitmapText is tinted character by character. In my solution whole tinted text is prerendered - this is reason, why it will not work with dynamic text.

Link to comment
Share on other sites

  • 5 months later...
  • 2 weeks later...
On 2/24/2019 at 2:27 AM, aylictal said:

thank you for this post (i'm late as ever) but i ran into this issue with a strokeRect call and it for sure will happen the same way as a fillRect call where if you redraw without clearing it, it will tear your performance to shreds over time :(

It really doesn't.

Link to comment
Share on other sites

  • 3 years later...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...