So basically the problem seems to be that it’s only changing some of the provinces to the nation’s color, is that correct?
Actually, if the floating point issue is the reason for the problem, some of my recommendations for efficiency might help solve the problem, as well, so I’ll go ahead and overview them.
First thing that jumps out at me is GetPixel(). There’s a certain amount of overhead in getting information out of a texture, so every time you call GetPixel() you’ll incur that overhead - and here you’re probably calling it, what, a million times? If you use GetPixels() instead before your loop, you’ll only incur that overhead once. And it’ll also make your loops a little easier. Now each pixel, instead of being represented by two floats, will be represented by a single integer - this is both faster and more reliable.
Color[] provinceMapPixels = provinceMap.GetPixels();
for (int p=0; p < provinceMapPixels.Length; p++) {
Next up is pixellist. Now, to make this fit with the GetPixels change, you’ll want to make this list a List now. One thing about List<> is that it benefits from knowing ahead of time about how large it might end up being, which you can specify by sending a number in the constructor (e.g. pixellist = new List(1000); ). If you don’t do this, then it will be forced to guess at what its capacity will be, and anytime you exceed that capacity, it must make a new guess at the size (I think it doubles the size each time?), grab a new chunk of memory and copy over the old values to it, and this takes time. Normally it’s not a lot of time, but when you get into the hundreds or thousands of items it can add up having to do this copying thing 10 or 20 times, for every province. You don’t have to get the capacity exactly right, but the closer you get the less often it will have to resize itself to fit the ever-growing list of pixels.
So make this a List, initialize it with an approximate capacity when you create the list, and line 18 will now look more like:
province.pixellist.Add(p);
Now I’d like to look at lines 16-17 and replace them with a dictionary lookup. Before you start looping through the pixels, let’s loop through your provinces and generate a Dictionary<Color, Province>. Now, rather than looping through the provinces for every single pixel, you can just use provinceDict[someColor] and it’ll go straight to it - dictionaries are quite fast. The setup would look something like:
var provinceDict = new Dictionary<Color, Province>();
foreach (Province province in _Economy.provinceArray) {
provinceDict.Add(province.color, province);
}
Then to access this, you can use provinceDict like I said above, but I’ll also add a safety check:
Color thisPixel = provinceMapPixels[p];
Province thisProvince = null;
if (provinceDict.ContainsKey(thisPixel) ) {
thisProvince = provinceDict[thisPixel];
}
else {
Debug.LogWarning($"Pixel number {p}, color {thisPixel} was not found in our province list!");
//break;
}
This will print out a warning every time it comes across a pixel that doesn’t correspond to a province. Now, this first time you run it, you probably want to uncomment that “break” line, because I’m guessing if there’s one then there will be thousands of these log statements, and just printing the log statements will take a considerable amount of time. This is one potential spot where your original algorithm may have been breaking. If you’re expecting pixels that don’t fit in any provinces (Maybe the ocean pixels? idk) then you should skip the whole “else” section there, but be advised that in that case you won’t be alerted to whether or not this problem is a problem. (Maybe you could create a fake “province” to which you add all pixels that don’t fit any other province, and then paint that province’s pixels onto the final result, as a test?)
So that takes care of optimizing the reading of the map. Now for writing of the map, this should be pretty easy, as it’s just the inverse of what we’ve done already - just liek GetPixel vs GetPixels, SetPixel repeatedly is much slower than SetPixels once.
You might wish to call GetPixels again to get changemap’s pixels, but if changemap’s initial state looks the same as provinceMap, then you may as well just use the Color[ ] array you already have. In either case, loop through your provinces like you’re doing now, and you can do this:
foreach (int thisPixelIndex in province.pixellist) {
pixels[thisPixelIndex] = province.owner.color;
}
....
changeMap.SetPixels(pixels);
changeMap.Apply();
This replaces the whole conversion of a Vector2 back into integers, which is one of the potential spots where your original algorithm may have been breaking.
Now, if you’ve done all this, you’ll have a much faster algorithm that should accomplish much the same thing as your first one, with two risky lines being made less risky. It’s possible the logic error is somewhere else, in which case, head on back here and we’ll dig a little deeper into your data structures to see if there’s an issue with those. But at the very least, you’ll be able to see the results without what I imagine was a multiple-second (at least) lag on Start() with the old algorithm! Hell, this one might be fast enough to be almost realtime.