Jump to content

Online game optimization


RNull
 Share

Recommended Posts

Hello everyone,

So I have been developing this game for the last month. It's an online rpg which I have been wanting to develop for quite some time now. I am very aware that the project is pretty challenging so instead of resolving issues after, I am trying to anticipate and ask questions before. I am pretty sure some of you guys already have had to deal with the things I am dealing so why not ask for a hand :D .

I have been very cautious performance-wise with the graphics. I have set quite a tight poly-budget and am trying to work things out from there. Models are a maximum of 3k triangles and textures a maximum of 512x512 resolution  Also all of my static meshes are joined into one, I believe joined meshes are more performant than instances ( If I am wrong please tell me ) . All of the dynamic meshes are either instances or clones depending on whether they have a skeleton with animations or not. Shadow maps for static models are baked and for dynamic models are  at 256 resolution ( Probably will be configurable client side ) . I have been also looking for the possibility to implement LOD but I still haven't, same for Octrees. I am reusing materials as much as I can or joining them into multi-materials when I can't to reduce drawcalls.

In the networking part, I am trying to lower as much as I can the quantity of information passing from server to client and vice-versa. Also I am lowering the size of the packages into the bare minimum. Most of the heavy computations are done server side just to lower as much as I can the CPU usage from the clients. My maps are divided into small mini-maps to lower the quantity of players staying at one map at the same time. The architecture is scalable just to be ready if sometime the game will be over-populated ( :P ) .

Now, my question is pretty simple, is there anything I am missing or are there any further optimizations I should keep in mind ? I am very open to suggestions, I know of the challenge the web poses when developing this kind of game so I really appreciate any thoughts or opinions in the matter.

Thank you and Best Regards,
RelativeNull.

 

Link to comment
Share on other sites

5 hours ago, hunts said:

Just tweaking the screen resolution

check this demo:

https://jsfiddle.net/nzexh6a6/17/

https://jsfiddle.net/nzexh6a6/18/

 

what's the fps difference?

Yes I am aware of that, however I don't think someone should rely on resolution to improve the fps. That should really be a last resort as forcing users to use a portion of the screen may not be ideal.

Link to comment
Share on other sites

2 hours ago, RelativeNull said:

Yes I am aware of that, however I don't think someone should rely on resolution to improve the fps. That should really be a last resort as forcing users to use a portion of the screen may not be ideal.

@RelativeNull hey I'm doing the exact same thing here! I've got a game targeted for mobile and have been really trying to squeeze out the last bit of performance gains. maybe we can exchange ideas and experiences. Are you targeting desktop or mobile?

 

I think you are already doing a lot of right things that I found useful as well. A few things I can probably add:

1. Disable webgl's antialias and use fxaa. 

2. Joining all static meshes into one - I think this depends on how many meshes there are, and how many of them are constantly out of the camera. By merging all the meshes, I think we are basically saving all the overhead of processing individual meshes but this single draw call would end up sending more vertex data to the GPU which at some point would eventually exceed the savings.

3. Keep in mind that JS is single threaded and any heavy chunk of work should ideally be split up into smaller chunks or processed during loading/transition screens, otherwise they cause frame drops during your gameplay.

4. I found that mesh selection can be really heavy. So freezeWorldMatrix whenever possible, and for meshes that are always inside the camera, do set alwaysSelectAsActiveMesh. 

5. Recalculating bounding info can also be quite heavy. We do mesh.getBoundingInfo().isLocked = true for all the meshes whose bounding info doesn't change. 

6. Make use of the solid particle system for dynamic but repetitive objects. It's better than instanced meshes in most cases. We used it for all sorts of visual effects and it's awesome. 

7. Be aware of that garbage collection can be a major cause of frame drops. See https://stackoverflow.com/questions/18364175/best-practices-for-reducing-garbage-collector-activity-in-javascript for a list of best practices to reduce GC load as much as possible. I pay special attention to anything that's in the main loop of the game and try to avoid creating any object, e.g. BABYLON.Vector3. I usually create a global object and modify it inside the main loop instead of creating a new one in each update. 

8. Profile the game with chrome developer tools frequently to identify bottlenecks.

That's what I can think of right now. Hope it's useful!

 

By the way, how do you do dynamic shadow for dynamic objects? Can you share more about that? Currently we calculate shadows for all static meshes. And for dynamic objects (characters that have animated skeletons for example) we fake a round shadow with a plane... Is there a good way to do cheap dynamic shadows?

Link to comment
Share on other sites

17 hours ago, Baker Xiao said:

@RelativeNull hey I'm doing the exact same thing here! I've got a game targeted for mobile and have been really trying to squeeze out the last bit of performance gains. maybe we can exchange ideas and experiences. Are you targeting desktop or mobile?

 

I think you are already doing a lot of right things that I found useful as well. A few things I can probably add:

1. Disable webgl's antialias and use fxaa. 

2. Joining all static meshes into one - I think this depends on how many meshes there are, and how many of them are constantly out of the camera. By merging all the meshes, I think we are basically saving all the overhead of processing individual meshes but this single draw call would end up sending more vertex data to the GPU which at some point would eventually exceed the savings.

3. Keep in mind that JS is single threaded and any heavy chunk of work should ideally be split up into smaller chunks or processed during loading/transition screens, otherwise they cause frame drops during your gameplay.

4. I found that mesh selection can be really heavy. So freezeWorldMatrix whenever possible, and for meshes that are always inside the camera, do set alwaysSelectAsActiveMesh. 

5. Recalculating bounding info can also be quite heavy. We do mesh.getBoundingInfo().isLocked = true for all the meshes whose bounding info doesn't change. 

6. Make use of the solid particle system for dynamic but repetitive objects. It's better than instanced meshes in most cases. We used it for all sorts of visual effects and it's awesome. 

7. Be aware of that garbage collection can be a major cause of frame drops. See https://stackoverflow.com/questions/18364175/best-practices-for-reducing-garbage-collector-activity-in-javascript for a list of best practices to reduce GC load as much as possible. I pay special attention to anything that's in the main loop of the game and try to avoid creating any object, e.g. BABYLON.Vector3. I usually create a global object and modify it inside the main loop instead of creating a new one in each update. 

8. Profile the game with chrome developer tools frequently to identify bottlenecks.

That's what I can think of right now. Hope it's useful!

 

By the way, how do you do dynamic shadow for dynamic objects? Can you share more about that? Currently we calculate shadows for all static meshes. And for dynamic objects (characters that have animated skeletons for example) we fake a round shadow with a plane... Is there a good way to do cheap dynamic shadows?

Hey, thanks for the amazing answer, this is exactly the kind of feedback I was looking for. I will really take this as a reference when I will be tuning in the performance. I am actually targeting both mobile and desktop. Is your game multiplayer or single player ? I would love to share experiences. What are your results from the extra optimization taken?

2. Probably we need to understand the compromise here. I currently have some small scenes with few objects so I am not yet into the inflection point. Probably @Deltakosh can provide some info here :) ?

6. I am curious what repetitive objects do you substitute with particles? Can you provide an example ?

How do you calculate shadows? You definitely want to bake the shadows in the terrain texture for static objects, you can do that in Blender for example. About the dynamic objects, I am currently using the shadow generator with a 256 resolution, however I am aware that it can be hugely optimized further. Shadows even in that resolution triple my draw calls so it is far from ideal. In any case, I have also baked the ambient occlusion map which probably might be enough and compensate for the lack of shadows depending on the game.
 

Link to comment
Share on other sites

@RelativeNull Every optimization up there was a significant improvement for us. They made our game from almost unplayable to smooth 60 fps on mobile. 

Our game is async multiplayer, so no realtime networking. But at some point we might add some realtime elements to it with websocket. Can I come to you for advice then? :) Btw what's the networking model of your game? 

Regarding the use of SPS, see these gameplays as examples. Each of these effects is made with a single Solid Particle System and performs really well. 

 

 

 

https://imgur.com/CHId1jO

https://imgur.com/IMoUlIR

https://imgur.com/gFJcFtE

Link to comment
Share on other sites

@Baker Xiao Can you do some sort of breakdown of this real-world example that you're doing with SPS?  Perhaps just some genericized psuedo-code to learn from?  

There is a lot of expertise that can be great for learning how the intricate bits of Babylon work in production situations.

Link to comment
Share on other sites

21 minutes ago, Rook said:

@Baker Xiao Can you do some sort of breakdown of this real-world example that you're doing with SPS?  Perhaps just some genericized psuedo-code to learn from?  

There is a lot of expertise that can be great for learning how the intricate bits of Babylon work in production situations.

Sure! I'd love to share what we did once we're done with our deadline... :) 

Link to comment
Share on other sites

1 hour ago, Baker Xiao said:

@RelativeNull Every optimization up there was a significant improvement for us. They made our game from almost unplayable to smooth 60 fps on mobile. 

Our game is async multiplayer, so no realtime networking. But at some point we might add some realtime elements to it with websocket. Can I come to you for advice then? :) Btw what's the networking model of your game? 

Regarding the use of SPS, see these gameplays as examples. Each of these effects is made with a single Solid Particle System and performs really well. 

 

 

 

https://imgur.com/CHId1jO

https://imgur.com/IMoUlIR

https://imgur.com/gFJcFtE

Yeah I am not minimizing any of the points. Please do, I'll be happy to share with you whatever I know of the topic :) . I am following an authoritative server model. Btw your game looks amazing! I would love to try it, do you have any demo or a link where people can try or not yet? Are you guys a game studio or just a team of friends :) ?

Link to comment
Share on other sites

@Baker Xiao Well just let me know when you have anything to share, I would love to try it out.

As for libraries/engines I am not using any, well except for socket.io but I mean, thats the minimum in my opinion. Uhmm yes it is very complex, I have already had experience in developing it so I was able to complete most of the networking in 1 week but still I am debugging and optimizing.

About the investment, I believe you will have to rewrite some of your code to match the multiplayer architecture. I can send you a couple of documentations ( It's not that there are many around anyway :P ) that you can use as a starting point.

In any case, if anytime you are going for it, be sure you have everything figured out else, you may rewrite things again and again.

Link to comment
Share on other sites

One more trick I just found out recently was the use of Spector.js https://spector.babylonjs.com/. You can directly see how many draw calls were made and what each of them drew exactly. 

Using this I found that the way I drew our GUI using pixi.js was causing way too many draw calls. All our images are from a single spritesheet so I thought they would be drawn with a single draw call, but it turns out that having a lot of text objects in the scene graph would break the batch because pixi.js would render things in the same order they were added to the scene. So having (image, text, image, text, image) would be 5 draw calls, but (image, image, image, text, text) would be a single one... Using this technique we now draw the entire GUI with a single draw call and the improvement on mobile devices was pretty huge. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

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