SetPixel help!

Forgive me I am not very good at this and I am just learning 3d and graphics.

I am building a top down 2d game. My terrain has several features.

Instead of having 1 object per tile per feature I wanted to stack bitmaps on one object using SetPixels and telling it to ignore the white areas of the images.

So say I have a square that’s just red in color that is 16x16 pixels.
Now I want to plop on top of it another 16x16 image BUT only 4x4 in the center are colored blue. The rest are empty pixel areas.

Like going in Photoshop using the magic want to select the area not in your image, deleting that area, and saving the image. You should have the image and the checkered background.

So RED box 16x16 and I plop another 16x16 image that is mostly empty except the center 4x4 which is BLUE… I want the blue to write over the red but the transparent part to do nothing.

I have been looking for answers for 3 days now online and I can’t find any except this thing called Alpha. But I haven’t found any reference on how to tell SetPixels to not write over the alpha?!?

		Texture2D mapTexture = new Texture2D(textWidth, textHeight + mapShift);
		
		Color[][] tiles = new Color[tileColumns*tileRows][];
		
		for(int y=0; y < tileRows; y++) {
			for(int x=0; x < tileColumns; x++) {
				tiles[y * tileColumns + x] = tileAtlas.GetPixels(x * tileDimX, y * tileDimY, tileDimX, tileDimY);
			}
		}
		for(int x=0; x < mapDimX; x++) {

			//.765626 is the measurement of X to shift the hexes over so they fit
			xFloatShift = 0.765626f * (x * tileDimX);
			xShift = (int)xFloatShift;		
			for(int y=0; y < mapDimY; y++) {
				Color[] p = tiles[Random.Range(0, (tileColumns-1)*(tileRows-1))];
				mapTexture.SetPixels(xShift, y * tileDimY + mapShift, tileDimX, tileDimY, p);
			}
			if (mapShift == 0)
				{mapShift = tileDimY / 2;}
			else
				{mapShift = 0;}
		}
		mapTexture.filterMode = FilterMode.Point;
		mapTexture.wrapMode = TextureWrapMode.Repeat;
		mapTexture.Apply();

i don’t really understand your problem. if you want transparent regions in your tiles why not just use alpha channel in the textures?
if you want to define other colors as transparent you need to do the logic yourself for example get a pixel from both tiles/textures and decide in logic which value should be shown.
note that for transparency you need to use the colors alpha and an shader which can handle transparency (fe a particle shader could do).
also there are some 2d packages in the asset store one even free. and unity is working on a 2d solution also which may come in a future update.

That’s the thing I don’t know how to do that and I haven’t found a post on it. The images have the alpha. I just don’t know how to use the code. I am new to Unity.

Why can’t you just set the alpha to #FFFFFF (white) and do the call. And it ignores writing that color?!?! Seems like it should be simply for a flat 2d image.

when you simply copy the colors into the texture (setpixels) they are not added to the previous color they overwrite the previous color. thats what i mean you must selectively copy the values when they are transparent.
if you want some kind of blend/transparency effect simply draw the tiles separately (could still be one mesh) and use a transparency shader which does the alpha calculations for you.

So I have to do it pixel by pixel? Using “SetPixel” not “SetPixels” and manually tell it “don’t write white”?

Because I don’t see how to use SetPixel"s" to do the same thing.

Alpha channels don’t work. The tiles I am using are hexagon which of course is written on a square tile. So when I set the pixels it still write over the previous pixels with transparent pixels wiping them out. It doesn’t write certain pixels and turns off others within the same object.

set pixels does what the name says. it sets the pixels of the texture (assigning them). why do you think it would take into account values stored inside?

i guess you need to do it this way when you insist to do it with this technique. but i think its improper and i would prefer either a texture per tile/hex or even better to create a single mesh out of the hexes where all quads display their tile via uv coordinates (texture atlas).

I don’t know how to do that. I’m pretty novice at this. I’m a 2d game maker using a 3d tool. Im used to drop the bitmap shift it set alpha that’s it. Swap memory.

BTW cant create many objects. The map is too large.

then look at (as already suggested) a 2d solution: Unity Asset Store - The Best Assets for Game Making (but i have no experience with them).
the texture class is not really suited for this kind of stuff.

if you don’t mind using dx11 have a look at this. it uses a geometry shader to put a hex at every vertex of a simple mesh. i have used this once to create a round hexmap of radius up to 147. the vertex colors could indicate the terrain type and the shader sets the proper uv’s for them.

if you can’t use this approach you can still manually create a mesh with a quad for every tile and the uv coordinates are set for the terrain type to index the correct position in the texture.

in both cases you need some calculations to detect the correct hex at a position (fe mouse over). this is quite task and maybe you should do some tutorials first before jumping deep into your project. if you lack the basics you are running to the forum with every “simple” question and this just demotivates you.

I actually did something different based on idea you said so thanks. I instantiated and destroyed the map as I went along. So the viewing area is 15x12 hexes but the actual data map can be huge. Its for a 2d top down strategy game. I shift objects and if they go off the side of the screen they get destroyed. The new slot gets instantiated.

Works well, cut my CPU usage by 90% since I don’t redraw the map like in traditional 2d games.

it would run even faster when you don’t destroy and instantiate the objects but (de)activate them and reuse them. this is called object pooling and there are some packages in the asset store.

i also like to divide data and display. you need to have the map itself in memory all the time anyway (moves, ai, pathfinding) but the display can be limited to what is seen.

I don’t need it to run SUPER fast, its a turn based game. I just need it to work. Right now I actually have to slow it down. Its a scrolling map.

… 1 hour later

I think I see how your way can be done. I move the camera, check the relative position of the camera to the map tile and if its < X or Y or whatever then turn that tile on or off. That way it doesn’t do update every stream. But then I still have to chance hundreds of times if they are in range of the camera. These maps are huge ~350x250 with 7 layers of roads, rail, resources not to mention 200+ units on the map.

Its quite a lot of objects.