Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Other [4.0.0] NSprites - sprite rendering package

Discussion in 'Entity Component System' started by Tony_Max, Nov 29, 2022.

  1. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    203323912-3f0aec5a-543d-4145-bf8f-42e07af2d124.gif
    NSprites
    is an open-source sprite rendering package. It uses
    ComputeBuffers
    to sync data between your entities and GPU and
    Graphics.DrawMeshInstancedProcedural
    to render entities.

    Requirements
    • entities v1.0.0-pre.65+
    • unity 2022.2+
    When you might want to use it
    • Your project operate with numerous of sprites so you wanna make them native entities. + You want to have your sprites as individual entities.
    • You want to minimize drawcalls, even probably render the most part in the same drawcall.
    When you might not want to use it
    • You don't want to write your own instancing shaders
    • You want more progressive solution with built-in animation / culling / etc systems. (you still can look at NSprites Foundation project or Age of Sprites sample project)

    Readme and documentation on GitHub project. Also check Foundation with samples and tools to work with this package.

    Notes
    This package doesn't contain any animation / culling / sorting / etc systems. So package provides very core feature - sprite rendering with automatic compute buffer data management. Though such systems can be easily built on top of it. You can inspect samples and use some tools by looking at sample project and foundation (which includes animation / sorting / culling / base rendering).

    The main reason of such a pure solution is because developers often want to have unique code architecture and I don't want to unnecessary limit anyone, because you may have no need in sorting at all, you may want to have simple sorting or nested sprites sorting or implement clever performant sorting algorithm (same with any other high level system).

    Changelog
    v4.0.0
    Remove
    RegisterRender
    overload with no
    Bounds
    parameter.
    This commit brings breaking changes. To upgrade to this version you need now use overload with explicit bounds parameter.

    v3.2.0

    * storage now test if archetype with same id already registered and log an error if it is
    * client code now can clear storage which disposes all render archetypes (for example when you change game level and no more need previous archetypes)

    v3.1.7

    * Code refactoring
    * Fix sprites didn't get rendered until 1st reallocation

    v3.1.2
    Fix wrong reallocation with min capacity step greater than
    1


    v3.1.1
    Fix invalid data sync for
    EachUpdate
    mode properties

    v3.1.0
    Update to entities 1.0.0-pre.65. Error / obsolete API fixing.
    * Fix asmdefs errors
    * Fix using obsolete API in NSprtiesUtils baker AddSpriteRenderComponents method

    v3.0.4
    Fix add rendering components methods missed
    PropertyPointerChunk
    component

    v3.0.3
    Add
    DebugSystem
    (editor / development build only) which detect missed property-components for sprite renderers and wrong
    PropertyPointer
    /
    PropertyPointerChunk
    composition (if it somehow was setted wrong)
    You can use
    NSPRITES_DEBUG_SYSTEM_DISABLE
    to fully disable debug system from compilation if you don't need it

    v3.0.1
    Minor internal changes of how
    PoprertyPointer
    /
    PropertyPointerChunk
    baked to entity

    v3.0.0
    You can use any blittable component as shader
    StructuredBuffer<T>
    property. Previously only 1-filed component could be used. Update details. Using components as properties details.
    Upgraid guide: There is no more
    PropertyFormat
    so all your
    InstancedPropertyComponent
    should be used without
    PropertyFormat
    parameter. So for example
    [assembly: InstancedPropertyComponent(typeof(SpriteColor), "_color", PropertyFormat.Float4)]
    becomes
    [assembly: InstancedPropertyComponent(typeof(SpriteColor), "_color")]


    v2.3.0
    * You can now also register Mesh (quad by default as previously) and render bounds per render using new
    RenderArchetypeStorage
    methods.
    * Added
    NSpritesException
    for better exception analysis

    v2.2.4
    Bug fixes / improvements

    v2.2.0
    Add Window -> Entities -> NSprites window where you can inspect NSprites data. More.

    v2.1.0
    Add baker extension method for adding sprite render components driven by baking system. From now client code can use this.
    AddSpriteRenderComponents(int id)
    from baker code.

    v2.0.0
    Upgrade codebase to 1.0 API. Details.
    Upgrade guide: to register renders you should now
    use SystemAPI.ManagedAPI.TryGetSingleton<RenderArchetypeStorage>(out var renderArchetypeStorage)
    instead of accessing directly to system instance like
    var renderSystem = World.GetSystem<SpriteRenderingSystem>();


    v1.1.2
    Minor typos / obsolete API / bug fixes + improvements

    v1.0.0
    Release version. From this point package has documentaton on github wiki and also samples.

    alpha-v.2.0.0
    Last alpha version when package was in deep developement. This version is hardly differ from next versions. It can be only used with entities v0.17 and has no documentation nor samples.

    I highly appreciate any discussions / critique / questions / bug reports / pull requests!
    You can join NSprites discord channel to fast contact with author and other package users!


    204523105-7cabb122-954c-4fb0-97bc-becb27d2d2b9.gif
     
    Last edited: Jan 11, 2024
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,754
    Looks pretty good?
    What is your stress test max number of sprites, that you can render?
     
    officialfonee likes this.
  3. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    With just pure package installed and just entities with properties it was near to 1kk sprites at screen with stable 60fps. It was 7 properties (1 of those writes whole 1kk capacity buffer each frame) for each entity-sprite. But it is hard to break performance for such things, because most of the time system just asks chunks do they have any component / order changes. But in real world for 2D rendering there is often sorting problems which usually bottleneck.
     
    Last edited: Nov 29, 2022
  4. psuong

    psuong

    Joined:
    Jun 11, 2014
    Posts:
    126
    Out of curiosity, how are you handling sprite animations? Are you shifting the UVs in your ComputeBuffer per frame?
     
  5. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Exactly. I know how much frames I have, theirs distribution and durations and then just calculate current UVs
     
    bb8_1 and psuong like this.
  6. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
    when i build android wiith il2cpp, has a error message
    upload_2022-11-30_10-42-5.png
     
    dannyalgorithmic likes this.
  7. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Yep, I've fixed it. Obviously it was
    _camera
    which somehow gets null ref in runtime but in editor all goes well. So for now I've added lazy initialize during
    OnUpdate
    .

    Btw, what the preferred way in 0.51 and in 1.0 to work with hybrid objects like camera? Should I put it to subscene and assume that all will ok in build?

    Also one another issue I see in android build is soldier's idle animation gets wrong UVs. Algorithm is very primitive, so I believe it is rendered texture, maybe unity's sprite atlas is to advanced and perform some different magic for different build targets, so maybe I should try another atlas solution, cause that isn't 1st issue with sprite atlas (if it is of course).
     
    dannyalgorithmic likes this.
  8. SirStompsalot

    SirStompsalot

    Joined:
    Sep 28, 2013
    Posts:
    112
    Following with profound interest. I'd be looking for 1.0 (upon release) support. Some of our animations are rather complex and sprite rendering is one of those tasks that we definitely don't want to do ourselves so we haven't completely committed to building our game with ECS and this sound like the incentive. Great job!
     
    Tony_Max likes this.
  9. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Rapidly answering I think there is not so much things in 1.0 which NSprites should integrate/update, so probably it can already be used with 1.0. Though I will update project soon.

    UPD: 1.0 has changes in
    IJobChunk
    , so there is no more
    firstEntityIndex
    parameter. Though it is simple to get per-chunk index offsets with
    EntityQuery.CalculateBaseEntityIndexArrayAsync()
    .
    I use this parameter to write data Chunk -> ComputeBuffer in parallel for each-update properties.
     
    Last edited: Dec 5, 2022
    Laicasaane and charleshendry like this.
  10. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
    Waiting for this project update to 1.0
     
    Tony_Max likes this.
  11. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    358
    Hi. How is the update progressing? Btw, thanks for your work!
     
    Tony_Max likes this.
  12. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    I was close to publish minimal compatible with entities 1.0 version, but stacked a little with this. Today will try to restore assets, check all working as expected and publish update.
     
    Laicasaane likes this.
  13. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    94
    I'm definitely interested in something like this for my 2D top down RPG maker esque game.
    Can I do tilemaps with this? As in, can I batch together 16x16 sprite tiles into one entity?
     
  14. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Since this package doesn't limit you what shader to use (it just require shader to be instanced compatible), you can built whatever you want.

    What you mean batching 16x16 sprites in one entity? (I mean what should it be? shared texture? solid renderer?) How would you organize data for tilemaps in ECS? And how you expect render will perform?
     
    Last edited: Dec 12, 2022
  15. PolarTron

    PolarTron

    Joined:
    Jun 21, 2013
    Posts:
    94
    I think what I mean is more of a feature request connected to a larger workflow I want to achieve.

    Essentially I want to have Tile Chunks in my 2d, top down, networked multiplayer game. Tile data is stored in a Dynamic Buffer on each chunk entity and the data stored in each element is just a simple byte defining the index to be used in a texture atlas lookup.

    Code (CSharp):
    1. public struct VisualTile : IBufferElementData
    2. {
    3.     public byte Index;
    4. }
    16x16 is a rough estimate of how many tiles I want to store in each chunk. So each chunk is roughly 256 bytes.

    Whenever the dynamic buffer is changed the data is copied into a compute buffer which is then sent to the shader responsible of rendering a single plane of 16x16 tiles using a texture atlas. I don't know much more than this but it's an API that I would really love to have in a package like this.
     
  16. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    358
    That looks quite problematic. I guess for the meantime I'll stick with the hybrid approach.
     
  17. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    I'd rather try to split such workflow to 2 parts - editor authoring and runtime.
    • Let runtime be just single sprites, because they are already updated per chunk changes any data you declared as sprite's property. You still would use atlas and have all rendering as solid drawcall. One really downside I see about rendering tilemap as bunch of individual sprites is probably a lot of overdraw, because it is still bunch of quads.
      As baking result sprite entities would have just differ TexST on atlas depending on byte index, which can be even cut of in the end of baking process.
    • Editor authoring should mimic unity's palette drawer (at best) or just have the same structure. Like map object, grid , etc. Then just implement a little bit of bakers which will create sprite entities.
     
    Laicasaane and PolarTron like this.
  18. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    It was some kind of unity buggy dark magic but after project recreation all works fine. From now package supports latest entities update.
     
    Laicasaane and charleshendry like this.
  19. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
  20. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Few things we can worry about WebGL compatibility in this project are
    • GPU instancing, which isn't supported by WebGL v1.0, but now unity uses v2.0+, so should be fine. Though not all browsers supports v2.0 WebGL.
    • URP package provide support for WebGL without further details
    • Input System package supports WebGL with some not related for this project details
    • DOTS (entities) supports WebGL with many issues I've seen on this forum. For example people find incompatibility with using Hybrid Renderer (not used in this project of course). So from this point it requires testing
    So theoretically it can be built as is for WebGL
     
  21. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
    Thanks for your reply!
    Yesterday I tried to open Age-of-Sprites project, but had some error messages, I find my unity version is unity2022.2.0f1.
    now project not supported it ?
     
  22. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    358
    Wow, thank you. There are some warnings about the use of obsolete APIs. Are you going to fix them as well?
     
  23. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Do you mean warnings in sample project? If so I've already fixed it in latest commits. I see no warnings from NSprites scripts.
     
  24. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    358
    The warnings mostly come from RenderArchetype.cs
    For example:
    upload_2022-12-15_10-12-6.png

    The first line was using the deprecated `.Has` where the parameter isn't passed by ref.
     
  25. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Done. Seems like warnings appears only with embedded packages, I was working with git fetched package for a while.
     
    Laicasaane likes this.
  26. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Sorry, missed your reply. Maybe project was outdated from latest entities / unity release. Though right a moment ago I've checked building Age-of-Sprites on Windows / Android with entities 1.0.0-pre.15 / unity 2020.2.0f1. All opened and built without any issues.
     
    Last edited: Dec 18, 2022
  27. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
    Hi,
    When i update new codes, my project can not work well, it seem into endless loop.
    So sad!
     
  28. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    After I've checked project I have few assumptions why you may encounter with such behaviour. First of all I can't reproduce endless loop right after entering playmode. So it may be some really hard calculation somewhere in editor
    • It can be huge UI draw if you have Entities Hierarchy opened, because in Age of Sprites there are massive entities spawn right at start of the game. I can't do anything with that. My solution is just to not use this window when we have frequent entities creation.
    • It can be huge console error messages display + you have incorrect properties setup, so NSprites throwing errors from jobs. Put throw inside job wasn't best idea, so I plan to remove it from jobs and write editor only debug system which will invoke warnings if you have entities with particular render ID but without needed properties to render.
     
    Last edited: Dec 20, 2022
  29. showwho

    showwho

    Joined:
    Jun 18, 2013
    Posts:
    19
    Yeah, you are right.
    when i close Entities Hierachy window, it can work well.
    but it also has some errors.
    upload_2022-12-21_9-20-43.png
     
  30. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    It tells that
    AnimationSettings
    singleton component doesn't exists. This singleton component generates during subscene baking in AnimationSettings gameobject. So maybe you should somehow trigger baking process, try open / close subscene (Rome_SubScene) or simply update / reload it.

    UPD: solved here
     
    Last edited: Dec 30, 2022
  31. Ksanone

    Ksanone

    Joined:
    Feb 7, 2015
    Posts:
    41
    Awesome package.

    I have a question - when I bring in a default cube into a subscene it is no longer visible in the editor. I noticed some Unity.Rendering components are missing - is there a system removing these and how can I stop this behaviour?
     
  32. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Thanks for your praise.

    NSprites package can't produce such behaviour, because there are no baking logic at all except extension methods in
    NSprites
    class.

    If you talking about Age of Sprites project which is a sample project for using this package, then I'm sure issue happens because of
    RemoveDefaultTransformComponentsSystem
    which is a baking system and it removes all default Unity.Transform components without any filtering, because this project doesn't use hybrid renderer at all. So there is few options how to avoid it.
    • Implement bake time only filtering component (will implemement this as soon as I can implemented already)
    • Disable
      RemoveDefaultTransformComponentsSystem
    • Import NSprites into empty project + bring scripts you need from NSprites Foundation folder of Age of Sprites project
     
    Last edited: Dec 30, 2022
  33. Ksanone

    Ksanone

    Joined:
    Feb 7, 2015
    Posts:
    41
    You're right, I was using the AoS project. Also I think it might have something to do with Entities Graphics not being installed. The only reason I wanted to use the default cube though was for visualising objects in the scene. The sprite renderers only seem to update at Play time? Is there a way to update the sprite renderer system to account for movement in the editor?

    Again amazing work, really useful since it seems Unity will not be looking at 2D ECS for awhile.
     
    Tony_Max likes this.
  34. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    SpriteRenderingSystem
    should update both in edit and play time. So sprite entities should be visible in game / scene view. Can you please inspect entities hierarchy window when you in edit mode?
     
  35. Ksanone

    Ksanone

    Joined:
    Feb 7, 2015
    Posts:
    41
    sprite moved in editor.png sprite position updates on play.png
     
  36. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Ksanone likes this.
  37. Djadavin

    Djadavin

    Joined:
    Dec 3, 2016
    Posts:
    3
    Hello.
    I downloaded latest Age of Sprites from Github.
    And all sprites are not rendered.
    Entities exist and updated but not rendered.
    No errors or warnings in console.
    I use Linux.
    Screenshot from 2023-01-26 18-52-29.png Screenshot from 2023-01-26 18-52-49.png
     

    Attached Files:

  38. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Have you success experience of using this project any before or it is first time?
    Also, can you please open FrameDebugger and check if rendering even performed?
     
  39. Djadavin

    Djadavin

    Joined:
    Dec 3, 2016
    Posts:
    3
    Found solution.
    It wasn't rendering on OpenGL but when I switched to Vulkan it worked perfectly.
    Frame Debuger dont work with OpenGL on Linux

    Screenshot from 2023-01-27 12-47-14.png
     
    Last edited: Jan 27, 2023
    Tony_Max likes this.
  40. winterSteve25

    winterSteve25

    Joined:
    Dec 9, 2021
    Posts:
    3
    I have just installed the NSprite and NSprite Foundation package, I am on unity verison 2022.2.5f1
    when I tried adding the SpriteRendererAuthoring monobehaviour to a gameobject inside a subscene with the default parameters used in Age of Spritse its giving me a bunch of errors.

    upload_2023-2-6_21-31-28.png

    upload_2023-2-6_21-31-44.png
     
    Tony_Max likes this.
  41. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    You see this error, because you have no properties registered. You can check it by opening Window -> Entities -> NSprites and see that there are no properties under YourWorldName -> Properties. You should register your components as properties.
    upload_2023-2-7_18-57-22.png
    This is how it should look like when properties / renders registered properly
    upload_2023-2-7_18-58-14.png

    In Age-of-Sprites sample project it registered by solid file like code below
    Code (CSharp):
    1. using NSprites;
    2.  
    3. [assembly: InstancedPropertyComponent(typeof(MainTexST), "_mainTexSTBuffer", PropertyFormat.Float4)]
    4. [assembly: InstancedPropertyComponent(typeof(WorldPosition2D), "_positionBuffer", PropertyFormat.Float2)]
    5. [assembly: InstancedPropertyComponent(typeof(Scale2D), "_heightWidthBuffer", PropertyFormat.Float2)]
    6. [assembly: InstancedPropertyComponent(typeof(Pivot), "_pivotBuffer", PropertyFormat.Float2)]
    7. [assembly: InstancedPropertyComponent(typeof(SortingValue), "_sortingValueBuffer", PropertyFormat.Float)]
    8. [assembly: InstancedPropertyComponent(typeof(Flip), "_flipBuffer", PropertyFormat.Int2)]
    9.  
    10. [assembly: DisableRenderingComponent(typeof(CullSpriteTag))]
    I'm sorry, Foundation project becomes confusing, because I doubt about how to deliver those asssets smart. You may want to use your custom components as properties for shader or use another shader to use with existing components, I can't predict, and since property name can't be registered multiple times (not component but shader property itself) I've decided to not include property manifest file to Foundation.

    What do you think about it? How it can be organized better?

    Also I will add more informative exception when system can't find property name you trying to pass. (UPD: done)
     
    Last edited: Feb 8, 2023
  42. winterSteve25

    winterSteve25

    Joined:
    Dec 9, 2021
    Posts:
    3
    Oh I see, maybe just mention it on the NSprite Foundation repo or have a pop up when you install the package, like odin inspector information panel. Not sure how they did it though. My bad if it is mentioned somewhere and I just missed it. When I downloaded the Foundation package I just expected it to have a default setup that I can use and work. In no means am I trying to disrespect your work, the NSprite package seems amazing it just slightly confusing here and there especially because I am very unfimiliar with writing shaders so I was just looking for something to get started with and maybe using it as an example learn and figure out some stuff on my own. Anyways thank you so much for the response and the amazing package!
     
  43. winterSteve25

    winterSteve25

    Joined:
    Dec 9, 2021
    Posts:
    3
    I have added the manifest and it has fixed the error. However, nothing is rendering, there are no errors eithers.
     
  44. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    No, it wasn't mentioned, that is my miss.
    What render pipline do you use?
     
  45. Sirius64

    Sirius64

    Joined:
    Jan 15, 2020
    Posts:
    7
    Thank you for releasing it. Great job, love it.
    Some feedback, maybe it will be somewhat useful - my WIP project is similar to Age Of Sprites example. I used NSprites with all versions of Unity 2022.2 up to 2022.2.7, with entities 1.0.0-pre.15, currently gradually upgrading towards 1.0.0-pre.44.
    I tested NSprites with GTX 1650 and i5-10500. Tried it with GTX 750 and FX-8300, and tested stuff with my friend's laptop, so also that. Using URP 14.0.6 with 2D renderer.

    The overall impression is positive. Great performance and I like how it's designed, offering solutions, but not insisting on them. There were some difficulties to figure out how to do stuff at the beginning, but at the same time - having a project with an example helps a lot.

    Of the properties that are currently being used on the sprite-entity in my project - two floats, three float2 and three float4.

    Also, I'm not using any kind of sorting system. Instead, my own shader with Z position set to each instance based on it's Y coordinate. So - hardware sorting. Also, if necessary, I add sorting value as offset instead of layer-based approach. Different, but does the job.
    This way displaying up to ~1-3 million sprites being sorted and everything else is somewhat cheap. I guess the role of overdraw will be more in play here, rather than anything else. Which is natural. (Here, look). Thoroughly tested.

    This is also the reason why I don't use any kind of culling system - because drawing sprites is cheap and culling them with provided workflow instead introduce structural changes as it requires you to add/remove components. Stuff like that always becomes more and more taxing if more entities introduced. Perhaps enabelable component alternative would fit here better, so far, from my experience in other systems with enableable - it's great.

    Speaking of structural changes I'm using a couple of sprite atlases, and that was a relatively peculiar' experience for me, because I use my own version of provided sprite registration system. Mostly the same, but I try to register entities only if the entities with the same material and texture have not been registered before. It works much better than doing this every single time.
    Would be grateful to see a built-in solution for registering sprites on a per-type basis. Some sort of sprites-library that you could reference to instantiate sprite entities as cheap as possible. Well, or something like that..
    'Experience was peculiar because though I haven't really messed with this stuff too much yet, that is because I was busy with other areas of my project, mostly pathfinding, but most of all - because registering entities oddly feels like something rather more confusing. More than once I had my sprite entities not displayed in the build for various reasons. Usually it was me messing up registration stuff or how it might differs from what unity does in editor vs in build. Remember recent Unity bug with scriptables? Yeah, I also managed to run into that.
    Sometimes had this weird issue with unity saying that I've been writing to buffer multiple times(Eh?), which would stop sprite rendering. Definitely happens way more often in build, and mor often on lower tier hardware while you spawn lots(couple thousands) of entities. Still not sure what that's was about and how to properly reproduce that.

    Another thing that I did, I locally changed SpriteRenderingSystem draw function to one with larger boundry.

    archetype.Draw(renderArchetypeStorage.Quad, new Bounds(new Vector3(0f, 0f, archetypeIndex), Vector3.one * 300000f));

    That's because sprites are drawn only within the specified boundaries. If you use the default value(1000f) - sprites will not be drawn further than 500 units from the zero coordinate. That would be the case for example project and what not.

    I am also using parent2D system just to display shadows under my sprites, since my entities use additional height property - that changes their visual position as if jumping/flying, but not their sorting or shadow position.

    Well, that's about it. Thank you.
     
    Last edited: Feb 19, 2023
    charleshendry likes this.
  46. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    Wow! Thank you for your feedback and words! I love this level of details with video included!:cool:

    Yeah, I'm going to use such approach in my own project. The reason I've come up with sorting like that is because I was trying to avoid Z shifting at all in scene view. But you're totally right it's better solution.

    I was thinking about using enablable components but I can't integrate them, because data sync performed on chunks without any entities filtering and enableable components is just chunk mask.

    That is a complex thing. I was thinking about implement simple per-material register system. But there is some cons of doing so. While shader stays the same you may want to use different
    PropertyUpdateMode
    for renderers with same materials. So I can't really just return ID without option to force register. And maybe the answer in in "force" word - just make additional method
    ForceRegisterMaterial
    to avoid duplicate checking. Anyway I didn't come to answer, but ready to further discussion ;)

    Wow! I've totally forgot about this thing. This should definitely be setted up through system's singleton. It comes from ancient version of rendering system from 0.17 entities version.
    UPD: Fixed with new register methods which can now obtain
    Mesh
    and
    Bounds
    (look at
    RenderArchetypeStorage.RegisterRender
    )
     
    Last edited: Feb 21, 2023
    Sirius64 likes this.
  47. Sirius64

    Sirius64

    Joined:
    Jan 15, 2020
    Posts:
    7
    Ah, that makes sense.
    Sure, so what I did about that was, as for now - my own int value which serves as a hash key for registration. This key represents the entire block of data, so both - material and properties set. I just assign value used for key myself as unique integer per sprite type. But such value could actually be something based of GetHashCode(), just if you want to assign something more readable from user perspective.
    So, I create my own prefab, slap it to my spawner - which registers that prefab to best of my abilities and then I try to spawn already registered entity. Which somewhat works and performes better.
    The reason why I was thinking about this to be along with regular approach as an out-of-the-box way of registering sprites is that I trust you way more than myself in terms of how data is registered and delivered into the rendering system in your package. Besides, IMO, I am actually not sure why you would wanna try to register every single sprite on spawn in first place anyway - since chances of every single spawned entity-sprite having an unique material & properties block is next to non-existend. Hence, indeed, some sort of per type sprite registration on demand, before you even start to instantiate stuff.
     
    Tony_Max likes this.
  48. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    358
    I've implemented a centralized registration system where Material & Properties pairs will be pre-registered in batch at the first frame. This system will also store sprite render ids in a NativeHashMap whose keys are special IDs I designed to map other things too. So from the second frame onwards, I can just spawn entities with sprite render ids easily retrieved from this NativeHashMap. Plus it can work in bursted jobs too!

    The cons may be it will be counter-intuitive at designing time if the character is complicate. But I have yet reached that stage.
     
    Last edited: Feb 20, 2023
    Tony_Max likes this.
  49. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    349
    RegisterRenderSystem
    (https://github.com/Antoshidza/NSprites-Foundation/blob/main/Base/Systems/RegisterRenderersSystem.cs) from Foundation includes prefabs in query, so only already existed on scene and prefab entities would be touched, but not every created sprite. Yes, if you have megacity 2D with millions of exisiting sprites on scene then yes, it requires more clever solution like on baking process collect all unique renders to register and produce for example 1 additional entity per unique render to register, or another way to create some singleton with buffer component containing all register instances.

    Am I undestanding your point right?

    The only thing you can break is to register same ID as different renderers, but even this way rendering system will just render same entities twice (or N times, depending on amount of registering same IDs). It even can be implemented as feature if you want use different shaders for same entities like for minimap (sure there are better way to do this)
     
  50. Sirius64

    Sirius64

    Joined:
    Jan 15, 2020
    Posts:
    7
    Eh? Please, excuse me if I don't convey my idea that well or if I was confused somewhere myself. Thank you for your attention anyway, let me try again, if you will.

    Referenced RegisterRenderSystem from NSprites foundation uses Query to get every single entity that has SpriteRenderDataToRegister and SpriteRenderID, just to remove first component, change stuff in shared component and if I recall correctly, also to add other components. Might actually misremember last part.
    This happens not on demand, that happens in system Update along with check if such ID doesn't exist in _registeredIDsSet. And all of that not with ECB, not in burst, just by EntityManager.
    Which is all bad. You really don't wanna do it if you have better way.
    There is effectively no need for millions of sprites sitting in some bloated city scene, no, you could as easily get your frame budget way to busy with just 10k sprites overall, just if you don't understand what's going on, since as out-of-the-box - exactly every single created entity-sprite is, indeed, being unnecessarly touched. Even in case when same ID already was registered before. Then, all such system does - adds unnecessary structural changes, which you already had some, since you instantiated stuff.

    So, again, It be at very least smarter to do stuff mentioned above just once, one single time instead, do that on prefabs and then spawn them with SpriteRenderID that already has appropriate ID that was set in previous step, thereby no need to remove or add something again.
    When we do that, creating new sprites obviously consumes less performance, but of course. Which probably should be the case for everyone and what sounds not only like optimization but also sounds exactly like something that should be an another builtin workflow, if not main one by design. Because rendering it's not only about displaying thing, but also about how you get there.
    If we can't do everything at baking, well, then how about if user bake entity and afterwards at some point calls some method, it goes trough the necessary procedure, it checks LinkedEntityGroup and here you go, now instantiating your prefab is fast and you could spend all this spawn performance to do more of something really cool instead.
    Yay for something cool.

    Still don't get what's wrong with that, but I don't insist. It would be just very kind of you to at least consider such as an option to implement.
    Also, I'm pretty sure that two entities rendering in one place because of same ID is far from the only problem that you can run into with visuals, because one just shouldn't understimate ablity of people like me who way to often develops at sleepless nights to mess up something.
    Besides, DOTS is already somewhat hadcore on it's own anyway, not even speaking of how it changed along it's bleeding edge path. In this context - systems like yours is something that makes this community million sprites better, you know. Hopefully not for everyone to create just yet another crimsonland/vampire survivors/alien shooter though.