- Home /
How to reset all static variables.
Hi,
I have hundreds of static variables across dozens of scripts. In fact 1 script has almost 200 in, and there are 71 scripts.
I am looking for a simple bug free way to reset all of these static variables to their initial values, when the player uses my log-out function to return to the game's front-page.
Application.loadlevel doesn't reset static, only local variables so doesn't help me.
What I want to avoid is a huge function on "log-out" that systematically goes through the dozens of scripts I have, resetting everything manually or doing it in the Awake.
I can replicate the desired effect of resetting everything by simply closing the web-player and re-opening it again, and would be happy with this if I could avoid the need to redownload the game content.
Any ideas at all would be great.
Thanks
Answer by nug700 · Oct 02, 2014 at 04:35 AM
A better way to manage these variables would be to make them all not static, and add a static Variable to your class called "Instance" that's the same type as your class, and set the variable to "this" in start. Then access all the variables through the Instance variable.
example
class myClass : monobehavior
{
public Static myClass Instance;
public int aVariable = 0;
void Start()
{
Instance = this;
}
}
You can now use "myClass.Instance.aVariable" in place of a static "myClass.aVariable" so that it gets reset after the component is destroyed and re-added.
Edit: Here's another way you could solve this without reprogramming every class. Keep in mind that this should be used for only this project, and for future projects you should use the above or any other answer. The idea is to make a static struct called "className_DefaultValues" for each class that you have static variables in and copy all the static variables into it. You then run "ResetStatics(typeof(className));" to set the static variables in that class to the values of the variable in the struct. Also please keep in mind that this may not be a fast way to accomplish this.
example:
using UnityEngine;
using System;
using System.Collections;
using System.Reflection;
public class Test : MonoBehaviour {
public static int exampleVar = 0;
// Use this for initialization
void Start () {
exampleVar = 5;
Debug.Log(exampleVar);
ResetStatics(typeof(Test));
Debug.Log(exampleVar);
}
public static void ResetStatics(Type type) {
MemberInfo[] members = type.GetMembers();
Type defaultValues = Type.GetType(type.Name + "_DefaultValues");
if (defaultValues != null) {
foreach (MemberInfo member in members) {
if (member.MemberType == MemberTypes.Field) {
FieldInfo field = (FieldInfo)member;
FieldInfo defaultValueField = defaultValues.GetField(field.Name);
if (field != null && defaultValueField != null && && field.IsPublic && field.IsStatic && defaultValueField.IsStatic) {
field.SetValue(null, defaultValueField.GetValue(null));
}
}
}
}
}
}
public struct Test_DefaultValues {
public static int exampleVar = 0;
}
Thanks for this. I don't use classes much, but I think I understand, so every script needs a local pointer to myClass, which contains all of the variables in the project in a huge list?
I've tried to avoid this just for the simplicity of being able to define the variables in the scripts that mostly use them for the ease of finding them and keeping them together. it also has the benefit of keeping the variable names short and apt, I think my lines would often go off the screen with a long prefix before each variable. I'm obviously doing something wrong anyway as no one else is coding this way or finding these problems.
This is probably the easiest solution. I still believe its wrong, and would only recommend doing this to fix your current project. Don't use this on a new project, except for variables that truly have a reason to be static.
Answer by Kiwasi · Aug 01, 2014 at 07:48 PM
You really should look at restructuring. Why do you have so many static variables?
By there very nature static variables keep their values. The only way to reset a static variable is as follows.
private static float myVariable = 0;
// Change myVariable
// Call this function to reset
void Reset () {
myVariable = 0;
}
This method is prone to errors, you must remember to add every static variable on every script to a reset function.
You really, really want to reconsider having so many static variables, and restructure accordingly.
Well they need to be defined as something, the idea was that static should be preferable over private or var on the cpu if there were no reason not to, in order to keep them in memory.
The need to initialise the variables twice this way is a bit messy and with a huge project like this could end up with obscure bugs.
Is there no way of simulating an application quit / reload without having to redownload the web player content?
Thanks for this Bored$$anonymous$$ormon. $$anonymous$$y understanding was that private variables get called into memory at the moment they are needed and then garbage collected when there are no longer references to them, while static variables stay in memory all the time from the moment the application starts and therefore have less cpu overheads. Can you then confirm that this is not true?
I haven't yet had a response from you but this is something I'd really like to understand better so I can program more efficiently going forwards.
As far memory allocation goes, if I declare a variable to be static on a script that is shared across multiple objects (say 10000 triggers), is memory given to that variable only once, as opposed to say 10000 independant times if it were private or just "var"?
Sorry I missed your last post. I'm no expert on memory management, but I can give you a few pointers.
First up public, protected, private and internal are all access modifiers. These control what can access your variable, and have nothing to do with static.
For most variables that are passed by reference the memory cost of having multiple instances is negligible. Object pointers take up almost no space. 10000 * almost nothing is still almost nothing.
The cost of GC is worth considering. But there are better ways to manage garbage collection then by making everything static.
By making things static you are basically removing all of the benefits of working in an OOP environment, and moving yourself back to the days of procedural program$$anonymous$$g. $$anonymous$$aking, testing, debugging and maintaining code will all be a lot harder. $$anonymous$$odern CPUs are capable of managing the overhead, so why not use them to the extent of their ability?
There may be some rare circumstances where this optimisation is justified, but in most cases its pre optimisation gone mad.
But are they actually passed by reference in my case of 10000 triggers which run a script, on which there is a private var as opposed to a static var? I don't see how they could be if in the private case you can have 10000 independant values for that variable local to each trigger, while in the static case they would all be referencing a single value. Surely in the private case it's creating new instances of that variable for each trigger?
Answer by cf · Aug 01, 2014 at 05:28 PM
There is no single command you can issue to reset static variables to their initial values.
A good option would be to assign all static variables their initial values in their corresponding Start() functions. Then their values would be reset when LoadLevel is called.
Answer by Tepei · Oct 02, 2014 at 06:32 PM
As your variable are static maybe you could store them in some static array in just one script. then in this script make array.length = 0 on start..
You cannot set array.length (you'd need to set the array to null or a new array). Also that may be quite confusing to use an array to access the variables. Image trying to code by doing StaticStuff.AllStaticVariables[x] = value
and trying to remember what each index maps to.
In Js Array.Length = 0 works for me ...
It's not so confusing:
in start all object make:
index = Game$$anonymous$$aster.Characters.length; //the index for all the array
Game$$anonymous$$aster.Characters.Add(TrueName);
Answer by friuns3 · Apr 27, 2020 at 11:33 AM
public static void Reset(Type type)
{
var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var a in fields)
a.SetValue(null, Activator.CreateInstance(a.FieldType));
type.TypeInitializer.Invoke(null, null);
}