2D counter design question and draw calls

I was looking for advice on performance and possible pitfalls. i know that I’ll have to try it to see for sure and plan to do multiple layers for the initial development since it’s easiest. I want to release on PC and mobile.

A typical counter has a base, symbol and multiple areas which have different decals on the outside these decals do not overlap.

One simple option would be to use multiple layers (9 I think) one for the base, one for the symbol and one for each decal. A second option would be to use one layer and a scratch bitmap and draw the decals on it when anything changes on the unit. I think it would also be possible to use a shader that would use the different offsets into the texture decals for each of the symbols. That option seems like it would be more complicated to program.

My question is whether there is an easier way to do this that I’m missing? And is there any reason to favor one of those approaches over the others? I know that I’ve had problems using dynamically loaded bitmaps in the map, they turned out fuzzy, so the second option is probably out unless someone knows why that’s happening. It also seems to be the most likely to have hard to diagnose problems and uses the CPU the most.

My prototype for the map uses something similar with about 20 layers for the map.

Any advice appreciated.

Well that’s easy! Here you go:

DO NOT OPTIMIZE “JUST BECAUSE…” If you don’t have a problem, DO NOT OPTIMIZE!

If you DO have a problem, there is only ONE way to find out. Always start by using the profiler:

Window → Analysis → Profiler

Failure to use the profiler first means you’re just guessing, making a mess of your code for no good reason.

Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

https://discussions.unity.com/t/841163/2

Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

Notes on optimizing UnityEngine.UI setups:

https://discussions.unity.com/t/846847/2

At a minimum you want to clearly understand what performance issues you are having:

  • running too slowly?
  • loading too slowly?
  • using too much runtime memory?
  • final bundle too large?
  • too much network traffic?
  • something else?

If you are unable to engage the profiler, then your next solution is gross guessing changes, such as “reimport all textures as 32x32 tiny textures” or “replace some complex 3D objects with cubes/capsules” to try and figure out what is bogging you down.

Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

This sort of speculative optimization assumes you’re properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.

You should probably get started. In my experience games will actually not write themselves. Here’s a great way to get some forward momentum and feel good about your project: ask yourself “Can I?” and go from there.

Like this guy does… it’s awesome!

Imphenzia: How Did I Learn To Make Games:

1 Like

Thanks for taking the time to do the detailed advice and I agree.

However, this isn’t a question on optimization, it’s a question on architecture. When I have done optimization in the past, it’s been localized changes after profiling. I try to write code that’s maintainable and only optimize areas that need it.

I’m a firm believer in KISS. I don’t want to add all the code I would need to for the dirty flag and lazy loading, etc. if I don’t need to, but if i might need it, I would much rather build it from the ground up and do the extra work now, during the initial build, than to try to shoehorn a major change like that in.

That’s not a simple performance tweak but some more serious rework of the architecture. I’d much rather add in the initial logic while I’m building the initial scaffolding than try to shoehorn it in later so I thought I’d see if anyone had done some similar work and which way they went.

I’m not following what the question is here. You tagged it tilemaps but don’t seem to be discussing that, you’re in the 2D forum but seem to be discussing general graphics rendering i.e. shaders, decals, “scratch” bitmaps (presumably you mean RenderTextures) etc.

This thread sounds more at home in Graphics sub-forums than the 2D forum as the 2D here isn’t the 2D nature of the screen or Texture2D etc. I can, of course, move it there if you wish.

First, thanks to everyone for responding, it’s made me rethink my design and how to get around the potential obstacles.

Thanks but it belongs here. I’m just not doing a great job of explaining it. I’m from a C++/Windows/Drawing bits to the screen with a test project using OpenGL background and don’t have the terminology down yet.

I am working on creating a new wargame based on an older Windows/C++ game. Some of the scenarios are huge with lots of counters and territory. That game draws everything on the screen with bitblts. My current iteration is based on using hexagonal tilemaps and multiple layers, one for the base layer and overlaying it with other layers for the roads, rivers, coastlines, etc. For the map, it has translated fairly cleanly from using routines that draw on the tiles into separate layers on the tilemap and letting the GPU sort it out ;).

I’m working on adding the counters which are also built up in layers. I use a shader on the base layer to change the colors of the counters and I know shaders are capable of a lot more. I misused the term decal, by that I meant the different symbols on the outside of the counter, not the textures used on 3D figures.

A naive implementation (which I’m going to try first) would be to paint up to nine bases slightly offset for the stacking followed by up to 10 more layers with the various icons displayed on the counter. I’ll also need a virtual counter class to orchestrate moving counters.

By the time I’m done with this test, I’ll probably be using about 60 different tilemap layers plus the UI draw calls. In theory, I could use a lot fewer if I wanted to aggressively use RenderTextures to aggregate unit layers into one texture but that means adding dirty logic and being careful about not introducing delays that I’d rather avoid or add early in the process if I am going to need it.

This design seems to me like it’s using a lot more layers than the tilemap would typically use, so I was hoping to see if this way of using it would face any major roadblocks before I got deep into it just in case someone knew of practical limitations to the number of layers I’m going to use with this technique.

Unless someone screams that I can’t do this for some reason or has a better method (simple and less likely to have performance issues), I’m going to try it and see. I figured that posts are cheap, so I might as well see if anyone had advice first.

Talking this through has made me realize that I don’t have to do it one way or the other, all layers or all Rendertextures. Instead of a flag on the counter that it’s dirty and needs to be rebuilt I can use a dirty flag on the display indicating that it needs to be rebuilt and to use the logic I’m building now until the background task sets the flag to false. That means that unless things are totally broken with this method, I won’t need nearly as much rework as I was afraid of. It would still work, although possibly slowly, with this process and switch to the faster one when available, instead of blocking while it recreated all the rendertextures. I can put all the dirty logic into the VirtualCounter and VirtualMapTile objects.

Here is an example of what it will look like. There are more details on the counters than shown here.
9234933--1290213--upload_2023-8-19_9-19-40.png

9234933--1290210--upload_2023-8-19_9-17-38.png

That’s great! Go make a scene, copy / paste parts of that image, chopping it up into sprites, putting in fake placeholder texts, UI sliders, just GO NOTS

Then go Ctrl-D about 100x times or more, scattering them all over, however many units you expect to have at once… finally add some particle systems to it, maybe some extra placeholder UI…

Drop a camera in looking at it, put a “camera drag by mouse” script on it and build it and run it on the target hardware.

Basically, create whatever you think will give you a simulacrum of what is keeping you awake with optimization anxiety every night. It shouldn’t take you more than a half hour if you move fast.

From that you can begin to learn something.

Now double everything, just Ctrl-D the entire hierarchy and build it again.

How is it running?

Now Ctrl-D it again. Still okay on target hardware?

Double it again. Double it AGAIN… now it is 16x times bigger than you originally projected.

For extra credit make a button onscreen that doubles ALL OTHER GameObjects at runtime (using Instantiate() on the root of the entire hierarchy) and save some building time.

Now you possess first-hand back-of-envelope approximations for what your problem space looks like from a performance standpoint on actual target hardware.

Anything else is either speculative optimization or get-working-on-it-avoidance.

1 Like

I’m an expert at avoidance :wink:

It’s actually easier than that since I’m doing things programmatically with minimal use of the editor beyond startup.

Thanks,
Ralph

1 Like

Me too… but I realized I met my match when I started programming… it is amazing the amount of patience that a program or bug or problem can have. They have ALWAYS been able to out-wait me.

Like I have a bug and I avoid fixing it, thinking “I’m gonna wait that sucker out and make HIM give up first…” and the bugs never do give up. I always have to go fix them. It’s the craziest thing. :slight_smile:

There’s also that dread that if you work hard enough you can evict him. You’ll then find out that he invited over a couple of friends through the back door while you were hustling him out the front door!

Impressive suite of games, kudos!

Let me reframe that for you my friend: that is job security. :slight_smile:

Thanks! I have a lot of fun making them and refining them every single day.

My games and work in these forums are two ways that help me stay up to speed on all parts of Unity for my work!