1 MILLION animated sprites at 60 FPS

Hello everyone, today I want to show you what I’ve been working on the past few days, to celebrate my 100 stars(thank you:roll_eyes:) on the SpriteSheetRenderer repo on GitHub.

With this system, you can render a huge amount of animated sprites at very high FPS(1 million animated sprites at 60fps)

C# 4 required

Get it on GitHub

I created 3 demos where you will find a simple tutorial on how to bulk/single instantiate and also a fractal visualization.

In this update, I rewrote the API to make it super easy to instantiate sprites

public Sprite[] sprites;
  public void Convert(Entity entity, EntityManager eManager, GameObjectConversionSystem conversionSystem) {
    // 1) Create Archetype
    EntityArchetype archetype = eManager.CreateArchetype(
             typeof(Position2D),
             typeof(Rotation2D),
             typeof(Scale),
             //required params
             typeof(SpriteIndex),
             typeof(SpriteSheetAnimation),
             typeof(SpriteSheetMaterial),
             typeof(SpriteSheetColor),
             typeof(SpriteMatrix),
             typeof(BufferHook)
          );

    // 2) Record and bake this spritesheet(only once)
    SpriteSheetManager.RecordSpriteSheet(sprites, "emoji");

    int maxSprites = SpriteSheetCache.GetLength("emoji");
    var color = UnityEngine.Random.ColorHSV(.35f, .85f);

    // 3) Populate components
    List<IComponentData> components = new List<IComponentData> {
        new Position2D { Value = float2.zero },
        new Scale { Value = 15 },
        new SpriteIndex { Value = UnityEngine.Random.Range(0, maxSprites) },
        new SpriteSheetAnimation { maxSprites = maxSprites, play = true, repetition = SpriteSheetAnimation.RepetitionType.Loop, samples = 10 },
        new SpriteSheetColor { color = new float4(color.r, color.g, color.b, color.a) }
      };
    // 4) Instantiate the entity
    Entity e = SpriteSheetManager.Instantiate(archetype, components, "emoji");
  }

Update an entity:

SpriteSheetManager.UpdateEntity(e, new Position2D { Value = float2.zero });

Destroy an entity:

SpriteSheetManager.DestroyEntity(e, "emoji");

To get some insight on how I made this system, you can check this post

Let me know what do you think about this and feel free to use it inside your game/prototype

23 Likes

Nice! I played with your older version a little so I’ll have to play with this one now.

Not sure if it’s just me, but all the DEMO’s were broken when I tried them. I had to change the sprite mode on the Material to multiple and then slice the sprites. Then each of the DEMO’s were missing a script with the sprites. Had to add the “MakeSpriteEntites” script to the “BulkSpawnSprites” DEMO, set the size to 16 and then add all the sprites (same for all).

The fractal one gave me a spinner in Unity for over 5 seconds just to go to around 16,000 entities… strange.

I got 600,000 at about 65 FPS… 800,000 brought me down in the 50’s.

I’m on an AMD FirePro D300 2 GB (Mac Pro).

Not bad for a mid-tier graphics card from six years ago :smile:

1 Like

Yeah, it’s held up pretty well. I like working on the Mac.

I’m more impressed that somehow @belva1234 got 1 Million entities on a Mid-2015 MacBook Pro (stated on github). If that’s default pro video card, that’s only a Radeon R9 M370X, which is slightly less powered than my FirePro’s (dual D300’s).

Hi, yeah that spinner is because of the quadtree algorithm and also I use the single instantiate API which is not ideal for bulk spawning.

Mmm that’ s wired… did you have burst compilation on?

Yeah, burst compilation is on. I’ll maybe look into it later.

After following the previously mentioned steps to replace the missing scripts, slice the material and add the sprites, I’m getting this runtime error: “Invalid stride 1 for Compute Buffer - must be greater than 0, less or equal to 2048 and a multiple of 4”.

What version of Unity and what version of packages does this require? I had to make several changes to the code, such as changing the four entityQuery.SetFilter(…) lines to entityQuery.SteSharedComponentFilter(…) in SpriteSheetRenderer.cs as the former does not exist in the latest version of Unity 2020.1.0a19.2395, Entities version 0.5.0-preview.17, which I imagine may have contributed to the aforementioned error.

Would appreciate any insight, I’d love to see just how far you’ve pushed DOTS on my 1080ti. :smile:

Well yes, I’ haven’t upgraded to 2020 yet, my test was done in 2019.3, once unity will officially release 2020 I will upgrade to it!

Also, if you all have any questions, feel free to ask them in my discord channel, I will reply to you as soon as possible: Nero's Adventure

Hi, great project!
Is it usable on mobile devices?
Obviously not at this scale but still.

Thanks

Hello, yeah sure dots works on mobile too, and the shader I made is compatible with all mobile devices.

Edit: Some OpenGL 3.0 devices don’t support StructuredBuffer in Shaders: https://discussions.unity.com/t/702195/2

Repost here

I have Issue with Delete Entities from Scene,
When delete entity the system still Render a sprite from Buffer.

SpriteSheetManager.DestroyEntity(entity, “emoji”);

Also Project Attached.

PS: And I wonder why we need in SpriteSheetRenderer.cs

processable = GetEntityQuery(ComponentType.ReadOnly(), ComponentType.ReadOnly());

Here is Simple Demo Project:
[200k dynamic animated sprites at 80fps]( 200k dynamic animated sprites at 80fps page-4#post-5486256)

Hi, that query along with other queries were leftovers from previous code that I wrote and forgot to remove(I cleaned it, in this new version), I also took time to fix the sprite destruction and build a demo for it.
I also wrote a super simple system to clean old buffers that I will optimize as soon as I can.

Awesome. I’m looking for a better way to render sprites with ecs. I’ll take a look at it tonight. How does the camera work? Is it orthographic?

Need to remember that this system using StructuredBuffer in a Shader and some Mobile devices not support it.

1 Like

Hello, yes, the camera is set to orthographic!

Hello guys, I’ve updated the repo to unity 2019.3.1 and to the latest version of entities, I also reorganized the project so there are no more missing scripts or assets dependencies when you load some scene.

Script dependencies are fixed once for all, there were some missing metafiles for some wired reasons.

There is a known issue with the strides, and I’m working on it,
thanks everyone for reporting it to me!

1 Like

Hello guys, it’s been a while since my last update, I was stunned by the love that this repo is receiving and I will try my best to keep updating it and fixing all the bugs you’ll send me on Github.

Today I have a great update, I made an animator system to better manage and play with the animation.

The concept is that you have a ScriptableObject used as containers to store information about animations, and you can then put multiple animations inside a Custom Animator.

You can use a custom animator to easier create an animated sprite, without having to manually create all the needed components.

I made a demo where you can select different animations and see the result in real time.

I also updated the project to unity 2019.3.5f and fixed a stride error many of you were having, let me know what do you think!

1 Like

To be honest, I didn’t take a close look at the project yet (the video looks quite impressive, though ^^). You currently have the Unity project your using for development in you repository.
To simplify the use of it, besides providing it in the asset store, you could restructure this project to be a Untiy package. What would need to change:

  • the main repository would contain the package structure, see the Unity manual about custom packages

  • assembly definitions are required, but it’s basically just creating a file in Unity and adding the dependencies

  • the dependencies to the DOTS packages would need to be defined in the package.json

  • Unity Project:

  • either manage it in a separate repository

  • the package would be included via git submodule

  • or just have it locally

As mentioned, the main advantage is the ease of using it - the package only contains what belongs to the package, and it’s easy to include.

Besides that, good luck with the further developments. :wink:

1 Like