Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.

How to easily create a scene with thousands of cubes, while constantly modifying their positional, rotational, and scaling attributes and still maintaining high levels of performance.

Photo by Renato Ramos Puma on Unsplash

Introduction

Previously, we showed the basic technical aspects of a Unity ECS implementation and the performance improvements it can bring to our project. Now, we will create more complex motion patterns for each of our Cubes, dig somewhat deeper into the coding specifics, apply simple performance optimization techniques and demonstrate their results.

Specifications

The hardware used for this article is a laptop from 2016, with 16 GB RAM, Nvidia GTX 960M graphics card and a quad core 2.6 GHz processor; the Unity Editor version is 2019.4.23f1.

Our Objective

In this project, complexity should be as low as possible, both in terms of code size and GameObject hierarchy. An empty scene with just a single main Camera will do. We don’t need any “spawner” GameObjects either, because all Entities will be spawn dynamically from within the System itself. Several thousands of randomly-sized Cubes will be injected into the Scene and the System will randomly animate each Cube’s Translation, Rotation and Scale attributes at the same time.

The Components

We need a set of Components to represent the three basic motion vectors; Translation, Rotation and Scaling. Each of those Components supports keeping its own state for the next Job iteration. The Scaler and Translator components also support boundaries to their allowed range of principal values. Using the GenerateAuthoringComponent attribute, there is no need to provide a separate IConvertGameObjectToEntity implementation; Unity automatically generates the appropriate component data for each Entity.

https://medium.com/media/41f2668ff67b690a8126a5acaaeeec32/href

The Cube Prefab and the Material

We also need a standard Prefab and a simple Material applied to it, so that we can batch our spawned Cube entities together and facilitate even greater performance gains during rendering. No surprises here; the Material is just a single-color opaque selection, running under the Standard shader.

Image 1: Cube prefab and Material configuration

Our Objective

Contrary to typical GameObjects, Entities in Unity ECS do not include a Transform component by default; instead, they can have a LocalToWorld component attached to them (see References [4] and [5]). The Value of that LocalToWorld component, a four-by-four matrix of type float4x4, is used to calculate the precise positioning, rotation and scale for the Entity it belongs to, so that this Entity can visually be rendered in our Scene.

Image 2: LocalToWorld Component for a selected Entity rendered in the Scene

After having our Cubes spawned into the Scene, the goal is to randomly and constantly modify each Cube’s LocalToWorld.Value data inside our scheduled Job, in order to create a highly performant ”crazier cubes” effect.

The System and the Job

Our System implementation is directly derived from Unity.Entities.SystemBase. The Entities that we want to include in the effect, will have four Components attached; LocalToWorld (intrinsic), Scaler, Rotator and Translator. This means that we can easily filter them out before accessing them. A standard EntityQuery constructed inside the OnCreate() method and applied into our Job, will suffice.

Also, within the same method, we resolve the Cube prefab by parsing the contents of the /Resources project folder according to the prefab’s name. That way, we don’t even have to add an explicit Editor reference to the Prefab itself. Details can be seen in Image 1 and Snippet 2.

https://medium.com/media/0128e41248dab59b88e43d6ec58c787a/href

It is also important to note that for the effect to work properly, we will be modifying the Translation, Rotation and Scale (TRS) values for each one of the rendered Cube instances simultaneously. During each call of the IJobChunk.Execute() method implementation, we calculate the new Translation, Rotation and Scale values separately, use them to obtain a new TRS transformation matrix and then assign that matrix to the Value member of the LocalToWorld Component. Then, the new TRS values are stored in the Component instances in order to be used in the next IJobChunk iteration.

https://medium.com/media/4b869dd86c140fcfaa0abff6598998c0/href

In contrast to the previous article (see Reference [1]), no confusing “drag — and — drop” operations have taken place in the Editor to connect the Cube prefab to an IConvertGameObjectToEntity class, no “spawner” empty GameObjects have been added to the Scene and only two code files have been used to implement the ECS pattern; one for the Components and one for the System. This makes the whole project setup a lot simpler and much easier to memorize.

The full source code can be found in Reference [2].

Simple Optimization

The fact that the custom Material we created in a previous step will be used on all spawned Entities, can contribute to significant performance gains during gameplay. Just enabling GPU Instancing on the Material, is enough to batch thousands of draw calls together and almost double the frame rate on the specified laptop for a viewport size of 1480 x 680 pixels.

Image 3: Rendering performance gains by enabling GPU Instancing on the custom Material

https://medium.com/media/20cfa7d5f4025d3853e46f065e353c5e/href

Conclusion

Unity’s DOTS is a powerful tool that can become extremely useful when our Scene involves thousands of similar Entities rendered at the same time. Still, it does not have to be complicated or difficult to learn, so this demo project is intended as a quick and easy “manual” for Unity DOTS implementations of much larger size and complexity.

References

  1. A simple guide to get started with Unity ECS
  2. Project source code
  3. Unity Entities v. 0.11.2 specification
  4. Unity Entities v. 0.11.2 Transform System specification
  5. Demystifying Transforms in Unity ECS
  6. Unity GPU Instancing Manual


Crazier Cubes: a simple, performance-optimized scene using Unity DOTS. was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Marios Koutroumpas

How to easily create a scene with thousands of cubes, while constantly modifying their positional, rotational, and scaling attributes and still maintaining high levels of performance.

Photo by Renato Ramos Puma on Unsplash

Introduction

Previously, we showed the basic technical aspects of a Unity ECS implementation and the performance improvements it can bring to our project. Now, we will create more complex motion patterns for each of our Cubes, dig somewhat deeper into the coding specifics, apply simple performance optimization techniques and demonstrate their results.

Specifications

The hardware used for this article is a laptop from 2016, with 16 GB RAM, Nvidia GTX 960M graphics card and a quad core 2.6 GHz processor; the Unity Editor version is 2019.4.23f1.

Our Objective

In this project, complexity should be as low as possible, both in terms of code size and GameObject hierarchy. An empty scene with just a single main Camera will do. We don't need any "spawner" GameObjects either, because all Entities will be spawn dynamically from within the System itself. Several thousands of randomly-sized Cubes will be injected into the Scene and the System will randomly animate each Cube’s Translation, Rotation and Scale attributes at the same time.

The Components

We need a set of Components to represent the three basic motion vectors; Translation, Rotation and Scaling. Each of those Components supports keeping its own state for the next Job iteration. The Scaler and Translator components also support boundaries to their allowed range of principal values. Using the GenerateAuthoringComponent attribute, there is no need to provide a separate IConvertGameObjectToEntity implementation; Unity automatically generates the appropriate component data for each Entity.

The Cube Prefab and the Material

We also need a standard Prefab and a simple Material applied to it, so that we can batch our spawned Cube entities together and facilitate even greater performance gains during rendering. No surprises here; the Material is just a single-color opaque selection, running under the Standard shader.

Image 1: Cube prefab and Material configuration

Our Objective

Contrary to typical GameObjects, Entities in Unity ECS do not include a Transform component by default; instead, they can have a LocalToWorld component attached to them (see References [4] and [5]). The Value of that LocalToWorld component, a four-by-four matrix of type float4x4, is used to calculate the precise positioning, rotation and scale for the Entity it belongs to, so that this Entity can visually be rendered in our Scene.

Image 2: LocalToWorld Component for a selected Entity rendered in the Scene

After having our Cubes spawned into the Scene, the goal is to randomly and constantly modify each Cube's LocalToWorld.Value data inside our scheduled Job, in order to create a highly performant ”crazier cubes” effect.

The System and the Job

Our System implementation is directly derived from Unity.Entities.SystemBase. The Entities that we want to include in the effect, will have four Components attached; LocalToWorld (intrinsic), Scaler, Rotator and Translator. This means that we can easily filter them out before accessing them. A standard EntityQuery constructed inside the OnCreate() method and applied into our Job, will suffice.

Also, within the same method, we resolve the Cube prefab by parsing the contents of the /Resources project folder according to the prefab's name. That way, we don't even have to add an explicit Editor reference to the Prefab itself. Details can be seen in Image 1 and Snippet 2.

It is also important to note that for the effect to work properly, we will be modifying the Translation, Rotation and Scale (TRS) values for each one of the rendered Cube instances simultaneously. During each call of the IJobChunk.Execute() method implementation, we calculate the new Translation, Rotation and Scale values separately, use them to obtain a new TRS transformation matrix and then assign that matrix to the Value member of the LocalToWorld Component. Then, the new TRS values are stored in the Component instances in order to be used in the next IJobChunk iteration.

In contrast to the previous article (see Reference [1]), no confusing “drag — and — drop” operations have taken place in the Editor to connect the Cube prefab to an IConvertGameObjectToEntity class, no “spawner” empty GameObjects have been added to the Scene and only two code files have been used to implement the ECS pattern; one for the Components and one for the System. This makes the whole project setup a lot simpler and much easier to memorize.

The full source code can be found in Reference [2].

Simple Optimization

The fact that the custom Material we created in a previous step will be used on all spawned Entities, can contribute to significant performance gains during gameplay. Just enabling GPU Instancing on the Material, is enough to batch thousands of draw calls together and almost double the frame rate on the specified laptop for a viewport size of 1480 x 680 pixels.

Image 3: Rendering performance gains by enabling GPU Instancing on the custom Material

Conclusion

Unity’s DOTS is a powerful tool that can become extremely useful when our Scene involves thousands of similar Entities rendered at the same time. Still, it does not have to be complicated or difficult to learn, so this demo project is intended as a quick and easy “manual” for Unity DOTS implementations of much larger size and complexity.

References

  1. A simple guide to get started with Unity ECS
  2. Project source code
  3. Unity Entities v. 0.11.2 specification
  4. Unity Entities v. 0.11.2 Transform System specification
  5. Demystifying Transforms in Unity ECS
  6. Unity GPU Instancing Manual

Crazier Cubes: a simple, performance-optimized scene using Unity DOTS. was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Marios Koutroumpas


Print Share Comment Cite Upload Translate Updates
APA

Marios Koutroumpas | Sciencx (2022-11-08T13:50:31+00:00) Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.. Retrieved from https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/

MLA
" » Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.." Marios Koutroumpas | Sciencx - Tuesday November 8, 2022, https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/
HARVARD
Marios Koutroumpas | Sciencx Tuesday November 8, 2022 » Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.., viewed ,<https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/>
VANCOUVER
Marios Koutroumpas | Sciencx - » Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/
CHICAGO
" » Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.." Marios Koutroumpas | Sciencx - Accessed . https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/
IEEE
" » Crazier Cubes: a simple, performance-optimized scene using Unity DOTS.." Marios Koutroumpas | Sciencx [Online]. Available: https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/. [Accessed: ]
rf:citation
» Crazier Cubes: a simple, performance-optimized scene using Unity DOTS. | Marios Koutroumpas | Sciencx | https://www.scien.cx/2022/11/08/crazier-cubes-a-simple-performance-optimized-scene-using-unity-dots/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.