This framework provides sprite rendering system compatible with Entities package (unity ECS).
Basically it sync whatever entity component you want with GPU data to perform instanced rendering. As a result all entities with same Material can be rendered with single drawcall.
- Using power of 💥DOTS💥 to render numerous of sprites
- Using any public to you per-entity component with predictable data format as shader instanced property
- Data update strategies to avoid unnecessary CPU load
- Edit-time rendering (subscene only)
For more detailed information please read project's wiki 📘
// registrate components as properties at assembly level anywhere in project
[assembly: InstancedPropertyComponent(typeof(WorldPosition2D), "_pos2D", PropertyFormat.Float2)]
[assembly: InstancedPropertyComponent(typeof(SpriteColor), "_color", PropertyFormat.Float4)]// registrate render with ID, Material, capacity data and set of properties
var renderSystem = World.GetSystem<SpriteRenderingSystem>();
// don't registrate same renderID
renderSystem.RegisterRender
(
renderID,
material, // material with [Enable GPU Instancing] enabled and shader supporting instancing
null, // override for MaterialPropertyBlock if needed
128, // initial ComputeBuffers capacity
128, // minimal capacity step for ComputeBuffers
"_pos2D", // world 2D position property
"_color" // color property
);// initialize sprite entity with all needed components for rendering
entityManager.AddSpriteRenderComponents(spriteEntity, renderID);
// WorldPosition2D and SpriteColor are example client's components
entityManager.AddComponentData(new WorldPosition2D());
entityManager.AddComponentData(new SpriteColor(Color.White));Also shader you're using should be compatible with instancing. Check my example shader gist. The main idea is to use StructuredBuffer<T> _propertyName. Though it is possible to use instanced properties with ShaderGraph, so you may try your option. For local example shader main part can look like:
// ...
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
StructuredBuffer<int> _propertyPointers;
StructuredBuffer<float4> _color;
#endif
// ...
Varyings UnlitVertex(Attributes attributes, uint instanceID : SV_InstanceID)
{
// ...
#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
int propPointer = _propertyPointers[instanceID]; // this is internal package property to point right data during component sync
float4 color = _color[propPointer];
#else
//fallback if somehow instancing failed
float4 color = float4(1,1,1,1);
#endif
// ...
}SpriteRenderingSystem sync registered entity components with ComputeBuffers to send data to GPU and then renders entities with Graphics.DrawMeshInstancedProcedural. System also controls how ComputeBuffers reallocates if capacity exceeds. Sprites are simple entities with no limits of what components you use.
Check sample project - Age of Sprites
This sample project covers basics of rendering with NSprites. Use it to get a main idea of how stuff can be implemented but not as production-ready solutions.
- Unity 2022.2.0f1
- Entities v1.0.0-pre.15
- Window -> Package Manager -> + button -> Add package from git url
- Paste
https://github.com/Antoshidza/NSprites.git
cdto your project's/Packagesfolder- git submodule https://github.com/Antoshidza/NSprites.git
I wish this project will be helpful for any ECS early adopters! So feel free to send bug reports / pull requests, start discussions / critique, those all are highly appreciated! You can contact with my discord account! Also there is a thread on unity dots forum!


