Primary tabs

Comments by User

Saturday, September 12, 2020 - 18:11

fatiher12,

Your game has a nice side-scroller feel and the graphics are good. The controls are a little difficult to manage. I would recommend work on the controls a little more and add more levels, maybe add some additional mechanics as you go up in level.

Sunday, July 26, 2020 - 01:18

@withthelove

Almost forgot, I had to use extension methods to define Equals() for the Unity Color32 struct because it was failing through to using default object Equals(). That was another significant issue that had to be discovered. Unity gives an array of Color32 structures that describe image data and expects a similar array when setting multiple pixels at once.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes...

Sunday, July 26, 2020 - 01:11

@withthelove

I was using functions like Distinct() and ToList() without realizing what they did in the background. Also tried tuning it until I did unit tests and realized how much memory and cpu they cost.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concept...

My default thing is to make stuff into classes too but Unity uses structs to describe color (both UnityEngine.Color and UnityEngine.Color32). I didn't need to copy that convention but kinda did without thinking much. I assumed structures didn't have the same overhead as objects and just went with it. It would seem in C# that's a dangerous assumption.

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choos...

Friday, July 24, 2020 - 15:40

@withthelove

Certainly! Things I ran into that caused serious performance issues:

- Default object comparison functions Equals() and GetHashCode()
- Default behavior of HashSet and Dictionary data types and their underlying need for IEquatable and/or IComparable interfaces to behave nicely with user defined data types
- Lack of (or incorrect) Unity issues with == and != operators
- LINQ performs terrible with large datasets without significant effort

I'll try to explain each point in plain programmer language so please don't be upset if you're not a programmer.

Point 1: Default object comparison functions Equals() and GetHashCode()

C# behaves differently with objects (reference type) than with structs (value type). If C# compares two objects (reference type) it checks to see if they refer to the same object (very fast). Simple reference check, nothing more.

Value types (structs) are different. C# uses reflection to find member variables and uses all of them to compute a hash based (think structInstance.GetHashCode()) to compare equality. If your struct stores 1 or 1000 member values they are all computed to get the GetHashcode() before they are compared (each member has struct.member.GetHashCode() called on it). Reflection is not super expensive but it is used every time it compares two structs to determine all the member variables. If you have (in my case) tens of thousands of structs to compare that gets very expensive very quick. If your struct uses an IEquatable interface then it implements the proper functions needed to compare two of the same structs. Example:

var a = new Color32(32, 64, 128, 255);
var b = new Color32(32, 64, 128, 254);
if(a == b)
{
// do something...
}

The Color32 struct in Unity is defined in UnityEngine namespace (RGBA struct with some methods). Without the IEquatable interface implemented, C# doesn't natively know how to compare two Color32 structs easily. The C# runtime boxes each struct instance (makes them objects), uses reflection to figure out all member variables, and then computes the hash values of each struct member variable to compute the final overall hash for the struct instance. This can get pretty expensive if your struct stores other structs because it causes recursion.

By default, GetHashCode() does some significant/expensive stuff to generates a semi-unique integer. If you override/define your own GetHashCode() it can be very efficient. Do this. Also, override and define your own Equals() function for every class/struct; implement the IEquatable interface so it plays nice with things like HashSet and Dictionary.

Point 2: Behavior of HashSet and Dictionary

HashSet only allows unique objects/structs; it uses GetHashCode() to figure out what's unique. That said, it (really desperately) needs the above things in Point 1 to run efficiently. A dictionary datatype needs the IComparable interface implemented because it uses those things to produce the highly optimized (nearly) O(1) search behavior. Hash sets and dictionaries are highly optimized in nearly every language so that's why I'm using them in C#. To get the best performance out of a dictionary it needs to store things that implement the IComparable interface because it internally sorts keys based on <, ==, and > operators to get the highest yield performance. HashSets use the GetHashCode() function on everything they store to ensure it gets unique items.

Point 3: Unity issues with == and != operators

Unity is notorious for lack of (correct) support when it comes to comparison of structs and objects (below is just one example, there are many).

https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/

Unity is designed to be fast for small collections of game objects, not for making tools. It's not designed for created enterprise applications or robust tools that deal with large amounts of data. It does a lot of things that are very safe but also very inefficient to ensure nothing breaks. I had to learn about many of these features (like the onGUI() function) and learn how to work around them. It's been a learning curve for sure. These are Unity specific problems.

Point 4: Microsoft .Net LINQ

Oh where to begin. We could start here:

https://stackoverflow.com/questions/1576679/reason-not-to-use-linq
https://softwareengineering.stackexchange.com/questions/160368/why-is-th...
https://medium.com/@raphaelyoshiga/linq-performance-dangers-6e9757607884
https://www.reddit.com/r/csharp/comments/6h2mbj/what_is_the_ugliest_linq...
https://dataflowe.wordpress.com/2017/01/24/the-disappointment-of-queryin...

Or we can talk about it briefly in relation to what I learned during this project. Microsoft LINQ is a fantastic tool for small datasets and it gives you so much freedom at the expense of memory and CPU cycles. First I designed with a lot of LINQ functions because hey, it's fast, it's easy, and it's already there. Then, I realized it created a lot of weird bottlenecks I didn't need so I got rid of it everywhere. It took a lot of work to remove it but my stuff runs much faster and uses much less memory now. Originally I was barely able to load a 512x512 PNG image without hitting performance and memory issues, now I'm trying to optimise a 10 megapixel image translation without issue (without LINQ). In my brief experience with LINQ it's great for things you know are small and won't grow. I will never use LINQ for anything larger than say a peanut or a baseball (figuratively speaking of course). If I do it'll be because there's no other option (there always is) or because it's the best tool for the job (it never is).

Friday, July 24, 2020 - 04:32

@chasersgaming

Added BMP reader support (does not allow saving as BMP but will load correctly). Also found some tools for GIF, may try to implement those (they support animated GIF too!).

Tuesday, July 21, 2020 - 13:50

After significant testing and refactoring with Bjorn (author of Tiled, www.mapeditor.org) we determined C# does a lot of boxing of variables and crazy nonsense. You can now load PNG and nearly any variant of JPEG and do color palette translations from PNG, JPEG, GPL, or text based HEX mapping files.

@chasergaming

Loading a BMP is an easy idea but somehow the BMP File Format

https://en.wikipedia.org/wiki/BMP_file_format

is not well supported outside Windows so Unity doesn't support it well either. I'll keep looking but for now it's still not supported.

Saturday, July 18, 2020 - 15:50

I'll offer my comments with the caveat that I've been tinkering with gaming and making games for a little while longer than I'd like to admit. My first foray into game making was with Java, then I went through an HTML5 phase, then Flash, then Haxe using flixel (HaxeFlixel), all the while looking at new/different ideas including lua, Love2D, and python to name a few. I've never been a fan of Microsoft languages (still not) but I settled on Unity3D because it compiles to different platforms, relies on a consistent API regardless of the platform, and offers some interesting/powerful tools like parallel thread processing and game development tools readily available. I'm not trying to advocate for or against it but Unity seems pretty easy (and free) and it meets my needs.

Saturday, July 18, 2020 - 10:52

@all

While testing with Bjorn (author of Tiled, www.mapeditor.org), he presented me with some crazy test cases that bent my brain and forced me to learn parallel thread processing in C#. What a learning experience! My tool now utilizes all available processors and threads! I also had to refactor a large portion of code to reduce memory heap size because it was running out of memory with large images. Should see improved loading and performance.

@withthelove

Got the two preview images to sync position. If you drag one the other will follow. I'll look at the mouse wheel zoom because I had the same thought but didn't act on it.

@chasergaming

I looked at BMP import/export briefly, that may be easy enough to implement but I'll have to rework the buttons again to make everything fit.

Wednesday, July 15, 2020 - 13:07

@withthelove

You have good ideas and advice so I did some more of those features. It now has the capability to zoom/pan and the zoom buttons are visible when doing color swapping. This tool is becoming a lot more interesting every day!

Tuesday, July 14, 2020 - 11:12

I'm also quite fond of sRGB and HEX because they're easy to understand and communicate. My concept of color and how machines represent it has drastically changed after making a tool that's heavily focused on color palettes and color definitions though. Most of my color palettes are stored as PNG's with square color swatches too.

I still use Microsoft Paint for the majority of my needs (I know, how draconian) but I've learned to use other things like Paint.net and Gimp. I have CS6 master suite because my wife is a graphic designer but I've only just opened photo shop or illustrator out of curiosity, never done anything. I recently learned of the existence of GrafX and Deluxe Paint separately from this discussion and they both seem pretty good, though I don't have much experience with pixel art (or art in general) so hard to judge tools you don't know how to use properly.

Pages