2D Toolkit Forum

2D Toolkit => Support => Topic started by: siroosec on September 05, 2013, 05:23:44 pm

Title: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 05, 2013, 05:23:44 pm
Hi!
I recently started using 2D Toolkit, and before anything else, I must say it's awesome! Thanks a lot!  :)

Currently I'm working on a card game, and I came across few issues.
The game is intended for retina iPad has 400 cards. So lots of 2048x2048 atlases will be used for them, and I'm almost certain current devices can't handle that easily and that's just our cards! Since we will have 40 cards in scene which can be of any combination, many atlases may be loaded in ram and vram only for 1 or 2 cards so huge amount of memory will be wasted that just isn't acceptable.

We initially thought we have to use planes for them and load card texture with Resources.Load(). But then we saw tk2dSpriteCollectionData.CreateFromTexture and tk2dBaseSprite.CreateFromTexture< T >. So here are my questions.

1. Is there any way to use 2D Toolkit's atlas generation in runtime? And will it have same performance as collections created in editor?
I think we could salvage the code used in editor atlas generator but that would be a last resort. It's kind of over the edge even as a last resort.
(If yes, I also like to know can I make it async or do it partially in coroutines so I can have a loading screen?)

2. If no, does a sprite have any overhead? I mean which one has better performance? A sprite created by tk2dBaseSprite.CreateFromTexture< T > or simple plane?
(Since we are going to have 40 cards and each one has a separate texture.)

3. If sprite is still better, is using tk2dBaseSprite.CreateFromTexture< T > code to create a method that replaces current sprite component with a new one instead of creating a new GameObject ok? Or it may cause problems?
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: jmcguirk on September 05, 2013, 06:32:06 pm
We happen to also be building a mobile card game using Tk2D :)

Trying to lump card textures together into a tk2d sprite collection likely isn't the best option (as you've noted) - you'd be loading in the atlas for mostly a single card.

We've gone down the route of an atlas-per card - which ups your draw calls since you won't be able to effectively batch them - but if we're talking about 40 draw extra calls for 40 cards, its probably fine unless you're targetting ancient hardware

It's probably wise to do the atlas generation offline rather than trying to do a .CreateFromTexture at runtime.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 05, 2013, 07:50:33 pm
Thanks for the reply!

I don't know why it didn't even come to my mind but it looks like a brilliant idea! Just if card sizes are close to a greater power of 2, very little memory would be wasted and I think its definitely better than  tk2dBaseSprite.CreateFromTexture< T > and simple plane. You used your atlases in one collection right?

But then again I think creating a collection from texture would be a better solution. You can do it in a short load screen (err... I'm still not sure if I can do it async but I think in worst case scenario I can draw 2-3 cards per frame on a texture in a coroutine using Texture2D.SetPixels) and then use tk2dSpriteCollectionData.CreateFromTexture to batch them in a single collection and atlas.

But as I said, it kind of looks like a last resort.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 06, 2013, 01:47:59 pm
If you're going to do that, try to avoid SetPixels... its ridiculously slow and synchronous :) You can get the same result using Render targets - it will be quite a bit faster.  You can pre-allocate your render textures, create a sprite collection from it with the sprites chopped up appropriately. On game load, simply draw into and fill up the pre-allocated slots.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 07, 2013, 07:40:15 am
Yes, that looks even better. I think I'll go with that. Thanks a lot! :)

But it would be awesome if 2D Toolkit managed the atlas generation in itself one day. Or since render texture needs Unity pro, something like an add-on for 2D Toolkit that could manage it. I think many users can use such thing to significantly improve their performance.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 07, 2013, 09:26:15 am
Yea but thats the point - doing it at runtime without render textures, any alternative method would be very very slow...
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 07, 2013, 10:01:06 am
I know. I mean some code in goodies or in another package (since render texture needs pro and 2D Toolkit is supposed to work with free) that handles this issue using render texture. The reason I'm asking this is because I think 2D Toolkit's atlas generation algorithms have matured and you can create a more optimized atlas comparing to some one who doesn't know how atlas generation works.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: mitralone on September 09, 2013, 08:36:11 pm
Just thinking out loud without seeing your cards. Would it be not possible to generate cards on the fly if certain parts of the cards are shared? If it was regular playing cards, I think just putting the four symbols, the images for the Jack Queen and King would suffice to generate all 52 cards. Oh and a suitable font for numbers.

Sounds interesting to hear how you guys will solve this. 400 cards in a game though, I am curious.
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 10, 2013, 07:28:31 am
Unfortunately I don't think we can. Our cards are football cards, and we plan to have about 16 teams. So each card should have a different player's picture, and we have 5 levels of each card. What we currently are trying to do is to bake as much data as we can in a simple PNG (picture, name, team and country), and generate data that can change (Power, level and ability text) with tk2dTextMesh at runtime.

So the main problem is still managing atlases and collections of the baked PNGs. I'm currently going with render texture and it looks fine. (I've simply done some test and it's not fully implemented so I can't say for sure.) But still I can't get rid of the feeling that I'm treading on a dark path !!!  :P
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 10, 2013, 10:13:12 am
I'm pretty sure RTs will work fine in your case. I've wanted to implement this as a core feature more than once, but most of our customers don't have Unity Pro so that makes it a very niche feature.
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 11, 2013, 08:46:50 am
I agree. We've got pro license just recently too.
But if I may suggest, it would be awesome if you could implement this functionality in an extra package that can be imported on top of 2D Toolkit. (Maybe make a card for it in road map?  :P 8) )
Anyway Render Texture and  tk2dSpriteCollectionData.CreateFromTexture worked for me in this case. I'm marking it as solved.
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 11, 2013, 10:52:11 am
Added a card to the trello!
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 11, 2013, 12:59:22 pm
Awesome! :)
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 09:43:52 am
I just faced another issue which made me return to this topic.
I need to have 3 or 4 atlases in the collection since a lot of mobile devices wont allow textures bigger than 2048x2048.
How can I create a collection with multiple atlases at runtime?
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 26, 2013, 10:08:50 am
You can't out of the box, it wasn't an anticipated use case - you can modify CreateFromTexture to deal with it though - basically, you'll have to pass multiple textures, create multiple materials, etc but otherwise straightforward.
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 10:28:24 am
I'll try that! Thanks a lot!
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 10:38:07 am
By the way something just hit me!
Can I edit an existing collection's atlas textures and expect it to show new atlases properly?
Since all of my sprites are cards with same shape and dimension. So if I replace a single card in the atlas with another and then apply it, its place shouldn't be affected at all.
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 26, 2013, 11:55:12 am
Yup thats correct
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 01:16:10 pm
Awesome!

Just one question! How can I find a sprite's corresponding atlas (I'm using multiple atlases) and corresponding area on atlas?
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 26, 2013, 01:42:02 pm
its in the UVs. For runtime generated ones, there will be always 4 UVs, and it will be rectangular. For normal collections on the other hand, its a bit harder as there can be any number of UVs depending on how the sprite gets tesselated.
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 01:51:57 pm
I checked the UVs but they were floats so I thought they can't be it. So I suppose I have to multiply the UV numbers to atlas size right?
Also how can I get the right texture when I'm using multiple atlases?
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 26, 2013, 02:00:45 pm
Yes, multiply by atlas dimensions to get pixel coordinates, get the right texture using spritedefinition.material.mainTexture
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: siroosec on September 26, 2013, 04:45:02 pm
I got it to work! I found Texture2D.PackTextures that packs all textures in one texture and returns their regions as Rect[]. (It uses a different convention for its Rects compared to what SpriteCollectionData.CreateFromTexture uses but its easy to convert it. Just convert coords from bottom-left based to top-left based and multiply rect variables by texture size.)

Just one problem remains. How can I make my collection to have colliders for its sprites?
Title: Re: [Solved] Runtime sprite generation from texture, Behaviour and Performance
Post by: unikronsoftware on September 27, 2013, 10:11:55 am
It'll be easier to simply create your own colliders here, than to try to automate anything. Just adding a boxcollider after its created a mesh should create it at the right size...
Title: Re: Runtime sprite generation from texture, Behaviour and Performance
Post by: hougenit on December 04, 2013, 01:41:04 pm
We happen to also be building a mobile card game using Tk2D :)

Trying to lump card textures together into a tk2d sprite collection likely isn't the best option (as you've noted) - you'd be loading in the atlas for mostly a single card.

We've gone down the route of an atlas-per card - which ups your draw calls since you won't be able to effectively batch them - but if we're talking about 40 draw extra calls for 40 cards, its probably fine unless you're targetting ancient hardware

It's probably wise to do the atlas generation offline rather than trying to do a .CreateFromTexture at runtime.



Have you solve the problem?I also have this problem,can you help me ?thank you