- Home /
Large # of gameobjects run smoothly or alternative?
I have been working on a building game project in unity, a Lego sort, and one problem that I have recently come across is size. Small numbers of these bricks go together with little lag, but then the frames drop as the brick count increases:
This image has about 1k bricks on the beautiful settings.
The bricks themselves have triggers on them that act as stud connections, and each brick has some script that handles connections and other such, all parented to an empty with a rigidbody (Set to isKinematic for now, so physics aren't playing a role in my frames). I would really like to know if there's a way to optimize this to allow for large scaling in the 10's of thousands of bricks, some trick about Unity's rendering/processing settings I don't know about, or maybe some mesh connection?
Any help would be appreciated, even if it the answer is find another engine
Use a couple of big meshes to render the blocks.
maybe this helps you getting an idea of how you could approach this:
Yes thank you, that will definitely help for future if I can properly scale, to add even more optimization. The only problem I see with it is that if all of my bricks are visible at one time, the system is still processing all those tris. I got it down significantly by hiding the triggers, which I didn't realize were such a huge part, but still run into hiccups at about 5000 at once.
as of right now during testing, it looks like unity culls pretty well on its own, keeping tri counts low as long as they aren't actually visible, but the fact that they are still there may have a significant effect.
Answer by Harinezumi · Mar 12, 2018 at 03:26 PM
Summary from comments:
- low performance can be caused by various things, the usual cuplrits being rendering, physics, scripts, and networking
- to find out what causes the performance issues run the profiler (Window menu -> Profiler)
- in the profiler the percentage of a row is not that important, it's the Time column that tells you if something takes too long
- in this case it turned out Behaviour.Update() (scripts) take 4.99ms, which is relatively a lot. Optimising scripts helped. One way to optimise scripts is to try to offload logic that doesn't run every frame from Update()
to coroutines
- to help with rendering many similar objects - as is the case with building blocks - batching (dynamic and static) and instancing (previously called geometry instancing) can help a lot (in this case it did). Batching can be turned on in the Player settings (Editor menu -> Project Settings -> Player), while geometry instancing can be turned on on individual materials (for those that support it, called "Enable GPU Instancing")
- don't bother with trying to manually discard sides of boxes that are not visible from your point of view, backface culling (run on the graphics card) automatically eliminates triangles whose normal faces away from the camera
- instantiating and destroying objects a lot can also cause poor performance, because they are costly operations, and allocate and deallocate memory that the GC needs to clean up. Instead, one can try using object pooling (there are various articles on the topic on the internet)
- to optimise physics, there are various rules. Firstly, NEVER directly modify transform.position
of a game object that has a RigidBody
on it, it is the most time consuming. Instead use Rigidbody.position
, or even better Rigidbody.MovePosition()
. Second, always apply changes to physics in FixedUpdate()
(or functions called from FixedUpdate()
), not from Update()
or LateUpdate()
- another physics optimisation is to approximate the collider of complex shapes with something simpler: either make the MeshCollider convex, or - if possible - use multiple primitive colliders, like Sphere- and BoxColliders
Original comment:
The issue can be graphics, physics, or the scripts. Run the profiler and check what takes so much time. In my experience 1k objects shouldn't bring the Editor to a halt, except if they have really complicated meshes or scripts on them.
My hunch is that the issue is caused by physics, the objects continuing to collide after they get connected. Note that even if you set a rigidbody to kinematic, even though it will not move, it does take part in collisions (as far as I know).
Looks like physics isn't a biggie, but behaviour update is? Does this mean that if I get rid of unnecessary update functions it will actually make it run that much better?
Taking the rigidbody off of the parent object gave me like 10fps back, pretty nice, so the idea of only giving it a rigidbody when needed is definitely on the list.
last note, in your opinion, would going as far as to make a cube object with six individual sides, and only render the sides on say the front half that you face, be a worthwhile optimization or just cause more problems and processing in the long run?
Based on the profiling rendering is the biggest issue. You could try turning on dynamic batching in player settings, as well as geometry instancing in the renderer/material of your objects (if I understand it correctly, you are rendering a lot of the same geometry, exactly what geometry instancing is used)
The percentage something takes is actually not that important, it's the time that matters. 4.99 ms in Behaviour.Update is quite a lot, so optimizing your scripts, trying to only run when needed (e.g. NOT using $$anonymous$$onoBehaviour.Update()) should probably improve how well it runs.
I would not care about marking sides of the boxes to be rendered or not, backface culling handles that for you (if the normal of a triangle faces away, the triangle is not even sent through the vertex shader)
Ah thanks again! Unless im missing something, dynamic batching was already turned on. Instancing is amazing and gives me at least 20fps after applying a material with it enabled. after running another test I was able to save 3 ms on update by getting rid of some pretty useless update functions. The only ones I can't get rid of are character input, is there somewhere better to put things like keydown and mousemovement than update?
Unity is typically pretty good about large numbers of objects, but anything you tell Unity to do in a Behaviour will be done for each object you have out there. Can you expand the profiler to see which specific script / function call is being most problematic and post that here?
thanks for the response, but as I said in the post above I was able to get rid of the lagging due to the update, sorry :/ but thanks for asking!