- Home /
Is it bad to use static on [practically] everything?
I don't mean everything, but I actually mean most things.
I'm the creator of a mod, RustEssentials, for a Unity game called Rust. RustEssentials is a C# assembly compiled into a .DLL using Visual Studio. I then load the .DLL at a certain point in server initialization and call a static method in RustEssentialsBootstrap.cs to start up the mod. Outside of RustEssentialsBootstrap, I use static for nearly everything: fields, properties, methods, classes, etc. For the past few months, I've been trying to figure out what I need to do to clean up a crashing issue that only occurs when using my mod. My assumption is that I have some sort of memory leak in my mod. Admittedly, I was an amateur when I first started the mod so the code is disorderly and practically an eye sore. Despite this, I feel like it's never too late to fix what I did wrong.
Essentially, I need help figuring out what is wrong with what I have and what I need to do to fix the crashing issue I've been having.
Should I not use foreach? Should I manually do GC.Collect? If so, how often? What is the significance of GC.Collect() vs GC.Collect(0) (I saw this somewhere but didn't really understand the objective.)? Is it bad to use StartCoroutine an abundant amount of times? Should StartCoroutines have short lifespans or is it okay to keep them running over a long period of time? Should I swap out all StartCoroutines with the creation of new [worker/background] threads? Should I consider using StringBuilder instead of all the string concatenation I do? If I've made a horrible mistake with using static everything, what is the best way to fix my problem? How should I reformat things? What should I do to properly dispose of UnityEngine.MonoBehaviour objects that I create? Is the sky blue?
You can view the source of my mod at GitHub. I've been running into a brick wall for quite some time now. Thanks for helping, I greatly appreciate any helpful feedback and advice.
Answer by kacyesp · Sep 01, 2014 at 08:53 AM
You should really separate all your questions into separate posts ( and probably google most of them ).
I'll answer you first question though. You should use static if you know you only need 1 "version" of that variable for all objects of the class to access. If the variable's value may need to differ per object, then you should not use static.
Answer by Baste · Sep 01, 2014 at 11:25 AM
Answers to some questions:
you should probably never, ever do manual garbage collector invoking, unless you really know what you're doing. A lot of engineers has worked to make sure that it runs automatically when needed.
foreach is fine
starting coroutines is generally good, but make sure you know when you're doing it. If you're say starting a coroutine in an Update()-loop, you'll start running slow really fast.
String concatenation is fine, generally. Are you doing it a lot? As in are you concatenating strings in update loops and sending them between objects as a way of sending messages? If you've got a bunch of methods like SendMessage(String message), you're doing something very, very wrong, and should do some major reworking of your code, BUT that won't lead to crashes necessarily, just to horrendously hard to work with code.
Static everything depends completely on what you're trying to do. If all your scripts are doing is editing the game world by modifying parameters and doing GUI stuff, you're probably good. If you're generating objects and instantiating multiple instances of the classes you've defined, you're doing something bad.
To sum it up, your code sounds like it's got a lot of problems, but none of the things you list are guaranteed to cause crashes. Does the game spit out any error messages? If so, which ones? Why do you assume a memory leak?
Thanks for clarifying, Baste. It seems like I'm a-okay on everything but the garbage collection. Is it bad to manually invoke GC.Collect? I've seen a lot of different articles stating conflicting advice. The game does spit out errors before it crashes. It always spits out NullReferenceExceptions with the source being an [RPC] attributed method (GetClient$$anonymous$$ove), with the deeper sources being the obfuscated methods of uLink - Rust's network library. I always assumed there was a memory leak because a lot of the time I would see the memory climbing gradually until it hit an approximate point. Once it got too high, it would crash.