- Home /
Low FPS despite simple scene
I have an issue with an unusual low frame rate even though the rendered scene doesn't seem to be that complex.
I'm plotting a 3D barplot where each data point is represented by one cube. https://imgur.com/a/wGk4GLU
The problem is, that if I move the player such that the whole plot is visible, the framerate drops to about 25fps. I noticed that the batch count goes up to ~7k and the Verts to 195k The process that uses up most time in the profiler is https://imgur.com/a/CMHPrrC
Does anyone know how to improve the performance of this one? Things like static batching aren't an option for me since I need access to the properties of the cubes at runtime (change their size, color etc.)
Well, you answered your own question. You have a 'simple' scene with thousands of mesh renderers. You could try to enable batching or instancing, but most likely you will have to redesign the whole thing. Why do you need thousands of renderers there? Are you stacking cubes on top of each other instead of stretching them? Is the whole floor made of 'data points'? Also notice in the profiler, that actual rendering takes 3.4% of the frame time, so the expensive task is something else. Could be culling. Try to show us profiler screenshot that shows the actual expensive task
Hey thanks for your quick reply. I'm quite new to the whole rendering/optimization part of unity so I'm probably thinking too simple here: Each data point (I have about 1k) is one instance of a GameObject which is a simple cube and one script attached. The cubes are strechted to get the correct height. The floor also consists of data points so I cant replace it with just a flat plane.
What do you mean by thousands of renderers? Individual Objects that are rendered?
Here is the complete profiler: https://imgur.com/a/0SVT1PI
I was wondering about the 3,4% too. But I assumed that the low number just represents one call of it so when it is called 7k times it just adds up (even though it doesnt seem to do this linearly). Here is also a screenshot of the timeline https://imgur.com/a/ZJYoPTF
The two lines below the RenderLoopJob are actually thousands of small very short calls of BatchRender.Flush and Render.$$anonymous$$esh respectively
Answer by Pangamini · Sep 03, 2020 at 03:57 PM
To reduce draw calls, Try to enable instancing on your material. Also make sure that every data point uses the same material. If you need some minor changes to the material, make sure it's an instanced property in the shader and that you are using PropertyBlocks. You could also switch to deferred rendering to avoid separate depth pass, or perhaps disable shadow casting. You could completely disable the datapoints that have zero value (the floor) while rendering a simple floor. Looks like most data points are just producing the floor. To reduce culling overhead, you could try to draw your meshes 'manually' with UnityEngine.Graphics.DrawMesh (or better DrawMeshInstanced), assuming that most of the graph is in the camera frustum most of the time.
Hey sorry for getting back to you so late. I tried enabling GPU instancing on the material, but this made it much worse. When the plot was rendered the framerate dropped to about 3fps.
I thought about disabling shadows, but this would reduce the look quality a lot. You are definitley right about the floor, but the 0 values are still data points plus I might want to have multiple plots at the same time so I want to find a solution for handling a lot of block anyway.
I looked into the Draw$$anonymous$$esh function but the documentation said:
Use Draw$$anonymous$$esh in situations where you want to draw large amount of meshes, but don't want the overhead of creating and managing game objects.
The problem is, that I need every object to be a gameobject so that the player can interact with it. Just drawing wouldnt be enough.
Just disable data points that show zero value, let it fallback to the simple ground quad mesh.
I want to find a solution for handling a lot of block anyway
means 'get rid of 95% of shit you don't need to render, so you can render 20 plots instead of one'
You can still use Graphics.Draw$$anonymous$$esh even if you have gameObjects with colliders. You'd just use Draw$$anonymous$$esh instead of $$anonymous$$eshRenderer components, basically doing some sort of super-simple DOTS renderer - I use something similar in a project to render hundreds of thousands of trees
Answer by tadeseus · Sep 08, 2020 at 08:39 AM
Found a solution. I'm using MaterialPropertyBlock http://thomasmountainborn.com/2016/05/25/materialpropertyblocks/
There are still some bugs, but the performance works like a charm :D
"Also make sure that every data point uses the same material. If you need some $$anonymous$$or changes to the material, make sure it's an instanced property in the shader and that you are using PropertyBlocks." You just skipped that, I guess
Every data point was using the same material, but without the $$anonymous$$aterialPropertyBlock, Unity creates a new material for each block if I modify the color at runtime.
Well, yes. And that means it's not the same material anymore
Answer by N-8-D-e-v · Sep 08, 2020 at 02:12 PM
I had this problem a while back, in the player settings (if on standalone) uncheck use default resolution
Your answer
Follow this Question
Related Questions
Reducing draw calls 0 Answers
Please help in optimizing a project! 1 Answer
Batching Nightmare, What affects dynamic Batching!? 0 Answers
What do I add to the LOD Renderer in MonoBehaviour? 2 Answers