🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Efficient crowd (audience) rendering

Started by
17 comments, last by Dan DAMAN 5 years ago

I'm looking for a way of rendering an audience in a decently sized stadium with about ten thousand seats. Usually not all seats will be filled. The project is using Unity3D

Currently I'm instantiating a GameObject with a skinned mech and armature+bone objects for each seat. Initially I simply animated them using Animator components on each but the framerate was unacceptably low. No real surprise there :)

What I have now is a smallish number of identical skinned mesh game objects with actual Animator components on them. I then copy the transform data from the armatures of the animated meshes to the armatures of randomly assigned audience members. While this is better it still takes 20ms or more per frame to do this. After rendering, overhead etc it leaves little to no room for actual gameplay  without dropping the framerate below an acceptable level.

The problem seems to be the process of copying/setting tens of thousands of individual positions+rotations from the animated objects' bones to the audience's. I've tried splitting the copying across multiple frames which improves update time and overall framerate but makes the audience animations look choppy.

Any ideas on how to either make this current implementation more efficient? Or any alternative solutions?

--------------------------Insert witty comment here!--------------------------
Advertisement

Baking them into sprites should help significantly.

I am an indie game developer who enjoys pixel art games.

So basically at a low resolution and basic contestant movement you have 40 frames per second?

On 6/28/2019 at 12:29 AM, Pepsidog said:

Baking them into sprites should help significantly.

I have some concerns about the sheer size of texture data that would produce but it's worth a shot. Thanks for the suggestion. I'll post back with how sprites work out.
 

On 6/28/2019 at 1:12 AM, Acosix said:

So basically at a low resolution and basic contestant movement you have 40 frames per second?

40 FPS with no player, no enemies, no gameplay etc. Just with the audience. Kinda expensive for what amounts to decoration. Remove the audience and the framerate jumps to ~160 FPS

Another idea I had is potentially copying bindposes on the SkinnedMeshRenderer or copying transform data so I'll probably try that too.

--------------------------Insert witty comment here!--------------------------

You missed the whole point of creating audience. Take a look at the development of NBA franchise from 2010 to 2019, especially the graphic modeling of the audience.

You noticed the difference between the 40 FPS and 160 FPS? Making a dynamic audience is hard to do and while the newest games don't have the flat picture audience of FIFA of the year 2000 and 2001, but making 100s of audience people moving all differently in total variety, talking between each other through humor and cheering by shouting, not to mention having cheering shirt and hats template colors for every single team is a lot of work.

To make it work you'll need at least very effective mesh modularity(as in code file modularity and not too large mesh sizes) and at least have make a couple of simple 3D programs first which are fully functional.

 
 
 
14 hours ago, Dan DAMAN said:

I have some concerns about the sheer size of texture data that would produce but it's worth a shot. Thanks for the suggestion. I'll post back with how sprites work out.

that is a fair point.  My idea won't really work for mobile, but try using the most compressed texture format.  It will look uglier, but it won't destroy memory.

I am an indie game developer who enjoys pixel art games.

13 hours ago, Acosix said:

You missed the whole point of creating audience.

This is unhelpful.

13 hours ago, Acosix said:

Making a dynamic audience is hard to do and while the newest games don't have the flat picture audience of FIFA of the year 2000 and 2001, but making 100s of audience people moving all differently in total variety, talking between each other through humor and cheering by shouting, not to mention having cheering shirt and hats template colors for every single team is a lot of work. 

This sort of thing would be what I would consider add on features for after I get decent performance out of basic rendering of characters with variable animations. I like to solve one problem at a time normally :)

--------------------------Insert witty comment here!--------------------------
5 minutes ago, Dan DAMAN said:

This is unhelpful.

I meant to say the point of making of  the audience is to  make smaller chunks of:
data, number of the audience people, perhaps even stadium size(like seats) if possible.

Quote

This sort of thing would be what I would consider add on features for after I get decent performance out of basic rendering of characters with variable animations. I like to solve one problem at a time normally :)

This is what I meant by chunks- like imagine code modularity, which I mentioned before There is a big difference in having 10Ks of codes 1-3 files and 10Ks of code in 200 files. Compile time is reduced, there is a smaller game executable, it is easier to view/organize/refactor/test.

Now take this code modularity concept and apply to the modularity of 3-dimensional objects infrastructure.
Even if

Like you said-go step by step. My point however is to use modularity, in both audience code implementation and taking steps in designing the audience design structure(s).

1 hour ago, Acosix said:

This is what I meant by chunks- like imagine code modularity, which I mentioned before There is a big difference in having 10Ks of codes 1-3 files and 10Ks of code in 200 files. Compile time is reduced, there is a smaller game executable, it is easier to view/organize/refactor/test.

The slowest version was a few dozen lines of code total using mainly Unity built in stuff. Your advice is good in a general sense but not relevant to the specific issue I'm trying to tackle. :)

The current problem is having an O(n) algorithm with way too big an n value. On that note, I have found another potentially feasible solution in Unity's job system. Specifically IJobParallelForTransform. A quick and dirty prototype has increased the framerate to 70 FPS. Hopefully I'll have something on that this evening or tomorrow.

--------------------------Insert witty comment here!--------------------------

Hi,

first of all: I have no idea about Unity (apart from knowing that is a Game Creation Toolbox/Engine ;) ) but maybe I can give you some inspiration.

So if I had to program that kind of stuff using OpenGL, I would try to use a simple animation system with not too many bones.

Let's say you have 20 different animations. Each of those animations should be composed of a real small set of keyframes to keep the data small. Then you basically need just two integers to describe each persons animation state. The first stores the current animation number (0-19) and the second the timestamp when it started. Since you want 10k+ people I would let the GPU do all the work. Apart from graphics, that's what they are for. Massive Parallelism.

Save the animation data in an array and send it to the GPU only once. Then initiate a compute shader that calculates the bone positions of each person that are in the field of view and randomly changes some animations that have ended. Render all visible persons with a single draw call.

The key thing about this idea is that only the animations/bone positions of visible persons are calculated. Since each animation is defined by a timestamp and the keyframes of the animation there is no need for calculating the states of non-visible persons to keep them going.

However, I don't know how much control Unity gives you to realize such a crowd system.

 

Greetings

This topic is closed to new replies.

Advertisement