What would be the most efficient way to do flashing for sprites similar to how Mario flashes when he gets a star in Super Mario Bros.? Is this possible to do with a shader? I’ve included two examples of the effect I need. Thank you.
What would be the most efficient way to do flashing for sprites similar to how Mario flashes when he gets a star in Super Mario Bros.? Is this possible to do with a shader? I’ve included two examples of the effect I need. Thank you.
when sprites do it, its just a palette swap/change. An easy way to do something like that in unity is to change the color of the material.
That tints all the colors on the sprite by the same color. I need to be able to replace colors individually.
The best way to do it depends on the actual effect you want to achieve. I’d do the above two differently. I couldn’t give a recommendation without seeing your artwork and a mockup.
why not just use a sprite sheet and animate through it like the sprite sheet is setup?
If the effect is simple, as with Mario and Mega Man, that would be an inefficient use of memory. It would be easy to deal with, though, so it’s a more efficient use of time, if you have the memory to spare.
That is the artwork I’m using and it’s the exact effect I want to achieve. It’s for the Unity port of Super Mario Bros. Crossover.
The characters will be moving while flashing and if I use a separate sprite sheet for each possible color combination it will take up way too much memory.
Why not have a full animation for each state and each mode? Then just transistion as required.
I need to be able to set the colors with code because they change depending on many different factors. What I’m really looking for is an efficient way to replace colors multiple times per second.
Why not have one block of sprites in greyscale. Then adding color should be no biggie.
Ah-hah! That’s why I recognized your avatar! Why are you porting? How is that not shut down by now?!
I need more information on that. Are there set color palettes, as above, or are there going to be wildly lerping values?
Also, are you able to use a quad for each pixel, or is that too much of a pain? As far as I can imagine, that would be the most efficient route, but if you don’t have a workflow for it, it doesn’t matter.
I don’t see how that makes sense. The colors aren’t just being multiplied in.
Lots of reasons, but mainly because Unity is cool and I wanted to learn how to use it.
All of the color palettes are set ahead of time. Basically I have an array of source colors and an array of colors that need to be set to depending on what’s happening.
I use one quad for each sprite, so it probably wouldn’t work to use one for each pixel. I’m open to trying different things though. I haven’t really started making the game yet so my workflow is not fully set yet.
If you have a grey scale base, then you can add some type of shader, or adjust the color itself. The greyness or lack there of will just give greater or lesser intensity.
Here’s what I recommend. If you take this approach, I’d like to hear your workflow, because I think I was a bit slow at it, using lots of eyedropper, magic wand with low tolerance/discontiguous, and one pixel marqueeing.
You’ll make two textures. One of them (the one that looks like the character) is Alpha 8, to be memory efficient. You find out how many colored areas you need (11 for Mega Man, by my calculations. 10 actual colored areas, plus one for the cutout), and select the next higher power of two up. Divide 256 by that, and you’ll know how far apart to space the greyscale values in the key textures (16 bits apart for mega man). I used white as the color to discard, but the shader can be modified to deal with whatever. White or black should yield the fastest results.
You’ll then need to populate a texture with actual color values. This can be set up in row or columns, but I used rows. Take a look at these screenshots, and check out the package. You might get what’s going on by doing that, but ask any questions otherwise. If you’re using Windows, you’ll have to force OpenGL; we can work on that if necessary. I recommend manipulating the “Key Y” slider, for fun and illustration, after opening the scene.
How does this approach compare to what you did in Flash?
P.S. I added the border because Unity actually expands all textures to powers of two, distorting pixel art. You’d probably want to set up the border differently.
899359–33626–$Mega Color.unitypackage (22.6 KB)
Wow, that is crazy Jessy. Thank you for going above and beyond with all your hard work. Since I know nothing about shaders and am pretty new to Unity, I have tons of questions.
First, let me show you how I was doing it in Flash. Here is Mega Man’s 16-bit sprite sheet.
And I have a separate file for each character that takes care of all the color replacing and flashing. This is what it looks like for 16-bit Mega Man:
I’m not gonna explain exactly how it works, but the main point is that the left column is the colors on the sheet. It gets those colors, then replaces them with the colors to the right depending on what’s going on. In Flash, I just replaced the colors directly on the sprite sheet (equivalent to Unity’s Texture2d.SetPixels method).
The thing I noticed about your proposal is that there is no row with the original colors, so I don’t understand how it knows which color to replace each shade of gray with. Also, does it need to be gray, or is it possible to use it the way I have it set up on the sprite sheet. A lot of my sprite sheets are made by fans, and it’s just easier to work with if I don’t have to modify the colors on the sheet.
Is this shader fast enough to use on everything even when it’s not flashing? Because I change colors of stuff depending on what level it is, but it doesn’t change again until the level is over. I was gonna use Texture2d.SetPixels for that, but I was just wondering if it’s possible to use this or if that will cause the game to run too slow.
Anyway thank you so much for helping me out.
The shades of gray are stored as 0-1 values. Black maps to the left pixel of the color values sheet, and goes up in increments of 16 bits (.0625 of the way across the sheet). It would probably be best to have the second color be at 1/32 + 1/16, instead of just 1/16, so that the color is sampled right in the center of the texel, but I forgot to do that. It still worked out. Like I said, I didn’t do a fast job of it. Also, the order of greyscale values and colors is totally arbitrary. I kind of worked from the outline, to lighter areas, ending with the face.
I don’t know how’d you do it with your sheets, in a shader. I googled it, and came up with Farfarer doing something very similar to what I posted here! If it’s fast enough to script texture changes, do that. If you need to offload work to the GPU, you could try scripting a conversion to what I did, in the Editor. It looks like you could get away with rows/columns of 128 pixels.
It’s not very heavy, nor is most any shader used for 2D stuff. I might switch to a standard unlit cutout/blend shader, when possible, if you’re concerned about battery, though. But the blending or “alpha testing”, which are unavoidable if you don’t “model” the pixel art with denser meshes, would be the potential bottleneck.
Thanks for allowing me to live some of my childhood fantasies, with SMB Crossover!
I bet I could convert the sheets to the gray version when the game is started so that I could still use my current sheets. I already saw that other post, but I didn’t understand it. But it does look like it’s a similar technique. I noticed in that post that he decided to use the red and green channels to get more than 256 colors. I’ll have to look into that.
I was really just trying to see what my options were for the color changing, so thanks for enlightening me a bit. If I decide to go this route I’ll probably have more questions. This technique would be faster than using set pixels and swapping textures continuously right? Also why would my rows and columns be limited to 128 pixels? My current palette sheet for Mega Man is 264 x 801 pixels because it holds colors for all of his skins.
Edit: Actually, I don’t think I’d ever need more than 256 colors on the source sheet.
That’s my prediction, but it depends on how much is changing per-frame. It doesn’t matter how efficient your algorithm for changing pixels is, if you need to send a lot of texture data to the GPU all the time. If you can keep textures cached near the hardware that works with it, the speed of light won’t be as much of an antagonist to you. Also, I don’t know any way that a CPU could keep up with the GPU lookup approach I offered, but whether that amounts to a time difference that matters to a human, I don’t know. You’d have to profile your own game, which involves much more than just the actions this thread is about. If you’ve already got some textures and code that works, try it out and see if there’s any reason to try to improve performance.
I was basing 128 on what I see in your color replacement sheet. I see blocks of 24x6 (144), but as far as I can tell, there are 7x6 blocks that aren’t doing anything, which gets you below 128. There may be other unnecessary areas, or I may be totally off-base on this, due to my incomplete understanding of it.
I don’t have any code written yet, that’s why I was trying to figure out which approach would be faster. I don’t have Unity Pro either so I can’t profile it, and I don’t have any Apple devices to test mobile performance. I don’t really understand which parts the CPU does and the GPU does.
The only way to learn about it is to try it though. Thanks for your help.
An easier method may be to have a shader which simply swaps around the RGB values, giving you:
RGB
RBG
GRB
GBR
BRG
BGR
etc… that’s a fair few flashy colour cycling combinations and should look sufficiently retro? it is also pretty easy to do in a shader? As for overall brightening (flashes etc) you can just multiply them up.
Just a thought!
Although I am mega impressed by Jessy’s idea above and would use that.