Coder Social home page Coder Social logo

age-of-sprites's Introduction

Age of Sprites - Sample project for NSprites package

RomeGIf

What this project solves

  • Registering render for each sprite
  • Registering properties-components for NSprites rendering
  • Rendering of all entities-sprites within 1 drawcall using texture atlas and passing tiling-and-offset values for each entity
  • Culling sprites outside of camera bounds
  • Screen sorting sprites with layers and dynamic / static sorting
  • Animating sprites using tiling-and-offset values change
  • Implementing 2D transforms to avoid unecessary data
  • +Poor example of producing units and building squads for strategy games

Requirements

Common solutions was step by step moved from here to separate NSprites-Foundation repo to be reused as a package. So solutions described below often references stuff which was initialy created inside this repo, though all links was edited to lead to foundation repo.

How register render happens

For this project I've used adding managed component to sprite entity to be able to register unique renders at runtime. Such solution doesn't scale well with growing count of existing sprites in scene. Though there are few possibilities to solve problem of managed components such as using components with fixed string GUID and then load managed data with AssetDatabase.

How register properties-components happens

There is nothing to say more then in docs. All registering comes with happens in PropertiesManifest.cs.

How rendering goes within 1 drawcall for different sprites

First thing is to use sprite atlasing. Then we come up with question how to render instances with same texture. Answer is simple - we just need pas texture's Tiling&Offset as property. I've used Reactive property type, because animation system writes to this component, so we need to sync updated data, even if some sprites never change theirs Tiling&Offset property. Then in shader we use simple function to locate our sprite on atlas

float2 TilingAndOffset(float2 UV, float2 Tiling, float2 Offset)
{
    return UV * Tiling + Offset;
}
// ...
varyings.uv = TilingAndOffset(attributes.uv, mainTexST.xy, mainTexST.zw);

You can easily obtain Tiling&Offset values using NSpritesUtils.GetTextureST(Sprite).

How culling happens

Culling system is simple as grab main camera, obtain it's view bounds and then check each sprite in parallel. If culled sprite is inside bounds then it should remove cull tag. If not-culled sprite is outside of bounds then it should get cull tag. To not render culled sprites we register [assembly: DisableRenderingComponent(typeof(CullSpriteTag))] in PropertiesManifest.cs. Animation and sorting systems also perform only not-culled sprites.

Tip: you can navigate to NSprites -> Toggle frustum culling system to enable / disable culling system if you want to test how it works.

How screen sorting happens

Shader makes a little trick described in this thread. It recieves some sorting value which is a [0,1] float and then just varyings.positionCS.z = sortingValue;. positionCS is SV_POSITION.

Sorting system lets us use any number of constant defined layers. In this project I've defined 8 layers, 2 of each I actually use. 0 layer all is for herbs and rocks, 1 layer is for soldiers, tents and flags. Sprites on 0 layer use static sorting which means that sorting happens only when new static-sorting entities was created / destroyed (chunk order version changed). Sprites on 1 layer uses regular dynamic sorting which happens every frame. Sorting system handle only sprites without cull tag.

How animation happens

Sprite per-frame animation is just changing sprite we render, so animation system just changes UVAtlas values over time. There is banch of ScriptableObjects and authorings to prepare animation data. It just contains frame count / distribution / duration / etc. At the end all data goes to blob assets. The best solution would be use HashMap in blob, but there is no built-in solution and community solutions unsupported, so every time I need switch animation I perform searching in blob array, though it can be improved.

How 2D transforms implemented

It is just a copy of Unity.Transforms package but for 2D needs. Though project doesn't use 90% of this functionality, because there is no parent-child relationship. Also I would not recommend bring such relationship to 2D rendering, because it complicate sorting a lot.

What happens in this example

There is few tents which are factories for units. They produce units over time. Free units search for squad which need units and then recieves it's position in squad. After all squads was filled with units new squad spawns. That is all.

Tip: you can navigate to NSprites -> Toggle draw squads for View window to see where squads exists, but it is expansive part.

age-of-sprites's People

Contributors

antoshidza avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.