When it comes to game development, you end up changing constants a lot. Make an enemy hit harder, make a character move just a tiny bit faster, etc. They’re still constant as far as the player’s concerned, but the compiler will get a little annoyed if you try and change them without recompiling. While my compile times are still reasonable (only a few seconds), it takes a few moments to exit my game, edit some source files, and load it up again. Even after the game’s started up, I still need to load a saved game to get back to where I was. All said, a hassle if I’m looking to fine-tune things.
I spent some time today adjusting various physics parameters to compensate for the fact that I’m getting ready to drop in the actual sprites for my player characters. The actual sprites are much, much larger than the placeholders I’ve been using, so various parameters – run speed, jump velocity, etc – all needed adjustment. Tuning these by hand was a pain.
The solution is a simple one, but it requires a little magic: Replace game-related constants with something more malleable that can still be used like a constant.
The first step is to find all the constants I care about. Hopefully, they’re all marked const… so, they’ll look something like this:
public const float StandingSearchDistance = 4.0f;
I change them to this:
public static Constant<float> StandingSearchDistance = 4.0f;
Easy to do with a regular expression, or a simple search/replace. Once I’ve defined the Constant<T> class appropriately, everything compiles and runs just like it used to.
public class Constant<T> {
public readonly T DefaultValue;
public Constant (T defaultValue) {
DefaultValue = defaultValue;
}
public static implicit operator T (Constant<T> constant) {
return constant.DefaultValue;
}
public static implicit operator Constant<T> (T constant) {
return new Constant<T>(constant);
}
}
This class doesn’t do much yet, but it’s not a bad start! It meets our most pressing need: Keeping the code working correctly, and setting the foundation for us to do more interesting things.
So, the next step is to make the Constant type a little less constant. Let’s give it a way to take on a new value at runtime:
public class Constant<T> where T : struct {
public readonly T DefaultValue;
private T? _CurrentValue;
public Constant (T defaultValue) {
DefaultValue = defaultValue;
_CurrentValue = null;
}
public T Value {
get {
return _CurrentValue.GetValueOrDefault(DefaultValue);
}
set {
_CurrentValue = value;
}
}
public static implicit operator T (Constant<T> constant) {
return constant.Value;
}
public static implicit operator Constant<T> (T constant) {
return new Constant<T>(constant);
}
}
Not a difficult change, really, and we’ve already got something useful to play with! If we wanted to, we could rig some code up to let us change these constants already, and if the game code is structured right, it’ll work just fine. It’s done! Ship it!
Well, okay. There’s more work to do. Two major things missing:
- There’s no easy way to get a list of constants to modify. Seems silly to leave that responsibility up to the game code, so let’s handle it in this bit of utility code instead.
- We need a way to save out constants once they’re modified, so that the changes you’ve painstakingly tested don’t get lost.
The first one is easier, and happens to be a prerequisite for the second one. So let’s start there.
The solution to this is pretty easy, really: We can use reflection! We know that every constant is going to be in a static field, and it’s going to be an instance of a generic type: Constant<>. This lets us write a simple bit of reflection code to find all the constants defined in the current assembly:
public static class ConstantManager {
public static Dictionary<string, object> Constants = new Dictionary<string, object>();
public static void Initialize () {
var genericConstant = typeof(Constant<>);
foreach (var type in Assembly.GetCallingAssembly().GetTypes()) {
var typeName = type.Name;
foreach (var field in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) {
var fieldName = field.Name;
var fieldType = field.FieldType;
if (!fieldType.IsGenericType || fieldType.GetGenericTypeDefinition() != genericConstant)
continue;
var constant = field.GetValue(null);
if (constant != null) {
var constantName = String.Format("{0}.{1}", typeName, fieldName);
Constants.Add(constantName, constant);
}
}
}
}
}
Well, okay. I might have been exaggerating a little – 20 lines isn’t ’simple’. But it’s not bad! There’s a few things going on in here: We scan over all the types in the assembly for static fields, check to see if they’re instances of Constant<>, and then pull them out, figure out their full name, and store them in a dictionary. Once we’ve done this, we now have a list of constants we can iterate over, so we can populate a UI to let the user fiddle with values.
So, as long as we call ConstantManager.Initialize at some point, the first problem is solved. Now for the second one!
As you may have noticed, we don’t actually have a clean way to interact with constants yet, because they don’t all share an underlying type – you can’t cast from object to Constant<> and fiddle with an untyped value, unfortunately. But the solution to this is simple – define an interface, and implement it:
public interface IConstant {
object Value { get; set; }
object DefaultValue { get; }
Type Type { get; }
void Save ();
}
Simple enough, right? Toss a little magic into the class to wire things up:
public class Constant<T> : IConstant, where T : struct {
...
object IConstant.DefaultValue {
get {
return this.DefaultValue;
}
}
object IConstant.Value {
get {
return this.Value;
}
set {
this.Value = (T)value;
}
}
public Type Type {
get {
return typeof(T);
}
}
...
Now we can use this interface to interact with constants – get their current/default values, and change their values. Combine this with the names stored in the ConstantManager and we have everything we need to populate a UI. Coincidentally, this gets us closer to being able to save constants out at runtime, too!
We’ve got a way to get a list of all the constants at runtime, and now we’ve got a way to get their values. All we need is a way to save them out to disk. We could try something elaborate based on digging through our source code, or save constants out to XML or something silly like that. But instead, why not let the compiler help us out?
The compiler already knows where our constants live, and it so happens there’s a way for us to get that information – in debug mode: The StackFrame class. Every StackFrame comes with a file name, line number, and even a column number. As it happens, it’s possible for us to get a StackFrame for the static member that contains a Constant! All we need to do is walk a couple steps up the stack:
public class Constant<T> : INamedConstant where T : struct {
...
public readonly string SourceFile;
public readonly int SourceLine;
public Constant (T defaultValue) {
var sf = new StackFrame(2, true);
SourceFile = sf.GetFileName();
SourceLine = sf.GetFileLineNumber();
...
We pass 2 to the StackFrame constructor because: 0 is Constant’s constructor, 1 is Constant’s implicit conversion operator (invoked because we didn’t change our constants to use the constructor directly), and 2 is the static constructor for the type that holds the constants.
Now, one would assume that the line number we get would point to the start of the class, or out into the middle of nowhere. But it turns out that somebody on the compiler team was feeling generous, because we actually get the exact line and column where the constant was declared. Awesome!
Given the file name, line number, name of the constant, and value, we have everything we need to save a constant back out to disk – right into the source file it came from, so it’s ready to be compiled or checked into version control.
I’ll admit – mucking with text files is annoying. So here’s the cheap hack I wrote to get the job done:
public void Save () {
var lines = File.ReadAllLines(SourceFile);
var line = lines[SourceLine - 1];
var typeSuffix = "";
if (Type == typeof(float))
typeSuffix = "f";
lines[SourceLine - 1] = Regex.Replace(
line, @"=(\w*)([^;]*);",
String.Format(@"= {0}{1};", Value, typeSuffix)
);
File.WriteAllLines(SourceFile, lines, Encoding.UTF8);
}
You’ll notice I had to hack in a fix for floats – if you write them out raw without an ‘f’ on the end, the compiler will treat them as doubles, and yell at you. I’m willing to bet there’s a better way to solve this problem, but I don’t know what it is.
After this, the rest is pretty simple – pop a button into the UI where you show your constants, and in the click handler, walk over all the constants and save them. You probably want to only save constants that’ve been changed from their default value, and that’s easy since we store the default value separately from the current value.
Now that you know how it works, here’s what my take on it looks like. It’s pretty simple – I wrote a couple dozen lines of code to hook it up to a DataGrid and some extra code to highlight constants that’ve been changed from their default values.



#1 by Overkill on March 30, 2009 - 3:07 pm
Quote
This is massive hotness. Though my game is written in Lua, I might be able use this general idea to redefine “constants” and save them in my code. The use of the debug module along with metatables, should allow me these freedoms.
Pingback: XNA Team Blog : Creators Club Communiqué 27
#2 by Pete on May 6, 2009 - 11:18 am
Quote
This is nice!
I’m not completely convinced of wrapping a single struct value with a class and also with the boxing/unboxing resulting from the getter/setter methods of the IConstant interface, though.
One suggestion: you won’t avoid garbage with this but as you’re restricting T for structs you may change “Object” by “ValueType” in the interface.
#3 by Kael on May 6, 2009 - 3:52 pm
Quote
@Pete
In retrospect, this was unclear:
The reason why the IConstant interface uses boxing is to enable building a simple ‘tweaker’ UI like the one I demonstrate – ideally, it should be so simple that you have no excuse for not adding it and using it wherever it makes sense. The tweaker UI is only used during debugging and development on desktops, not in production code, so the cost of the boxing/unboxing doesn’t really matter, unless you’re reading/writing thousands of tweakable values every frame – and I find that unlikely. Likewise, garbage generation should only occur when you’re interacting with the tweaking UI – if you’re just playing the game, this system shouldn’t generate any garbage.
The reason the Constant type is generic and restricted to value types is so that the common, important case – reading the value of a constant – is as fast as possible. I didn’t want to see my framerate drop by 20% because I changed the player sprite’s size from a ‘const float’ to a ‘Constant‘. Using generics and restricting it to value types gets you pretty close to the performance equivalent of a static variable (it’s impossible to hit constant-level performance, unfortunately).
Good tip about ValueType – I’ll check that out.
#4 by Pete on May 6, 2009 - 6:27 pm
Quote
I see. My approach: I use the content pipeline plus read-only fields (and in special situations reflection to tweak them). No need to recompile the whole game, just a content file.
#5 by kreppa on May 11, 2009 - 11:48 pm
Quote
I want to try this out – but I’m confused about one thing in particular: where do I put the datagrid and user interface? In a form in the game itself (I didn’t know you could do that), or in its own process?
#6 by Kael on May 12, 2009 - 1:08 am
Quote
@kreppa
If you’re using XNA on Windows, you can simply reference the Windows Forms library, create a form, and Show it (either as a floating window or a dialog) while the game is running and everything will work.
In other environments, you might need to roll your own UI. A command line tool or something in an external process are feasible options too, though.
#7 by kreppa on May 12, 2009 - 2:04 am
Quote
Cool, I had no idea XNA could run alongside event-driven forms so easily. That will be useful for all kinds of other development menus and things.
And maybe tweaking the constants will actually be fun from now on.
#8 by Nick Gravelyn on May 12, 2009 - 7:01 am
Quote
This is really cool. I’m getting ready to implement this into my framework. Two notes, though:
1) StackFrame doesn’t appear to be available on the Xbox 360 according to MSDN, so for people targeting the console, they’ll have to use some preprocessor directives to remove those parts from the Xbox build.
2) Your constructor assumes you never call the constructor directly which, while potentially safe, does open you up to trouble if you were to accidentally call the constructor directly because your StackFrame relies on the constructor being called from the implicit operator. One easy fix is to mark the constructor itself as private so that the way to create a Constant is through the implicit operator. Then you can know for sure that is how your object has been constructed and know that your 2 value for StackFrame is correct.
#9 by Kael on May 12, 2009 - 8:39 am
Quote
@Nick Gravelyn
#1 Yeah, that’s true. My assumption is that realtime tweaking on the 360 isn’t as useful as it is on the PC, since you don’t have a suitable input device. If you wanted to do constant editing on the 360, you could feasibly generate a list of constants and filenames/line numbers offline once you’ve built the PC version of your executable, using reflection, and bundle the list with the game instead of generating it using StackFrame.
#2 Good catch. Making the constructor private is a simple way to solve the problem.
#10 by Nick Gravelyn on May 12, 2009 - 10:51 am
Quote
@Kael
Oh I didn’t mean to imply that runtime editing on Xbox 360 was necessary, just simply that one would need to put #if WINDOWS around any of the code that handles the editing so that the project can compile for the Xbox 360. If they wanted to add in some complex code to allow changing on the fly on Xbox, they could, but bare minimum is just making sure the code that uses StackFrame has the #if WINDOWS/#endif around it.
Pingback: Constant Binding « luminance
#11 by Niklas Rother on September 11, 2009 - 7:48 am
Quote
Really Cool, this stuff…
I don´t get it managed to save all Constants in a Method in ConstantManager. I have this code:
public static void SaveAll()
{
foreach (KeyValuePair kvPair in Constants)
{
IConstant iConst = (IConstant)kvPair.Value;
((Constant)iConst.Value).Save();
}
}
but it doesn´t work. Can you give me a Hint…?
Niklas
#12 by Kael on September 11, 2009 - 7:15 pm
Quote
You’ll need to tell me more than ‘it doesn’t work’ if you want any help.
#13 by Niklas Rother on September 13, 2009 - 4:07 am
Quote
I’m sorry, i wanted to say it doesnt compile! But i’m really Bad in using reflection, so i think this Code is the wring Way to Save all Constants…
Maybe you should add a notice About this in the article!
Niklas Rother
#14 by Niklas Rother on September 15, 2009 - 8:45 am
Quote
I solved the problem by adding void Save(); to the Interface!
#15 by Kael on September 15, 2009 - 3:11 pm
Quote
Good catch. I don’t think I use the interface to do the saving in my game, but Save should definitely be part of the interface.
#16 by Mike on September 29, 2009 - 3:42 am
Quote
Hi,
It’s neat but i think you completely over complicated something, and in the process, mangled symantics.
What you have there are certainly not constants. I don’t mean to nitpick, but in C# constant is a real word that has a very specific meaning.
What you have are regular read only properties. What is the performance benefit to using this approach? None. You aim to create a solution to globally find all ‘constants’ so you can edit them in your UI. In most cases, while you are tweaking things, you don’t need access to ALL constants in the assembly at once, and if your game has quite a lot, then you end up with a bloated UI and have to scroll forever to find your one property (in alphebeical order i assume).
Your solution has no way to group these constants.
.NET made something for you that is much better than your approach. They are called attributes. Decorate your VARIABLES with custom attributes,
[CustomGameConstantAttribute("BigBadEnemyBoss")]
private READONLY float BossPunchDamageAmount { get; set; }
Now, using a little reflection, you find ALL properties that have the ‘CustomGameConstantAttribute’. Better yet, you group them by the argument value and your UI can only load the ‘constants’ for the ‘bigBadEnemyBoss’. You’re UI could have a cool drop down list at the top so you can choose what group of ‘constants’ you want to edit.
So now, you have an easy way to get to your constants.
Even better, when it’s time to ship your game, you simply remove the code that does the actual reflection, and what you have left are properties with attributes that are ignored….. no performance cost what so ever.
Your approach leaves artifacts of your ‘development process’ in your game code.
In the actual running game, is there any reason to have those properties be your ‘Constant’ type? Of course not. It’s only needed to make it easy to edit while developing. So why make it part of the running game’s architecture?
Also, your approach to writing your values back to the actual source code is dangerous. Code generation is cool, but this is not a good case study of it. Since these are NOT constants, write to XML, and populate the values at runtime. Your approach already throws the benefit of constants out the window. You can populate a static variable at runtime, no big deal. They can still be READ ONLY if you populate them inside the constructor.
Those are my two cents. Of course, i’m a college drop out, and maybe i missed your point, but i just layed out how i would solve your problem in less time, with less code, and no impact on the production code i ship to my customers while using preexisting mechanisms of .net.
Of course, i will assume you would not be doing this on XBOX, so this solution would only work on windows.
I don’t mean this to sound like a scathing attack. If i didn’t care, i wouldn’t write anything. Any maybe you can tear me a new one and i’ll learn something.
Happy Coding
#17 by Mike on September 29, 2009 - 3:47 am
Quote
And to clarify, the UI would only work on Windows, the actual game would have no issues with XBOX.
#18 by Mike on September 29, 2009 - 4:30 am
Quote
Also, in response to #kreppa# the UI question….
yeah, i personally like using WinForms (just like #kael# said) and loading the game inside a form.
Another option in the xWinForms library. It’s almost ALL the controls from real WinForms, re-coded from scratch to work in XNA.
Because it’s re-coded from scratch, It’s buggy as hell, but i have personally implemented it and works cool. Luckily, the source code is provided, as i needed to change several things in their code. Still an awesome effort that deserves a look.
http://www.gameprojects.com/project/?id=e68f3464c4
#19 by Kael on September 29, 2009 - 6:48 am
Quote
Most of your points are accurate, but it’s not remotely any less code. The custom attribute and need to initialize in specific places, along with the need for XML parsing, makes it considerably larger. The use of an attribute for categorizing constants is a cool idea, but I haven’t needed to do that yet since constants are always members of a given class anyway.
There’s no real performance benefit; I’m not sure I ever suggested there was one. The point of this approach is to avoid having to repeat yourself and only need to make minimal changes to your code (essentially, you replace ‘const x y’ with ‘Constant y’, which you can trivially do with a regex) in order to enable tweaking values. And when you’re done tweaking, you can trivially pull them back out.
Ultimately it all comes down to taste, though. Using attributes to tag things and saving/loading from a file was an approach I considered initially; I ended up going with this approach after reading about a similar one implemented in C using macros, just to see how it worked out.
#20 by Mike on September 29, 2009 - 2:26 pm
Quote
“Considerably larger” is completely untrue. My approach is less code and i’ll show you how……
You initialize you classes just like I would initialize my attributes. You do them with an operator overload, which, most veteran programmers would say is very bad practice. Implicit conversion operators are sloppy at best and bad OOP practice as it blurs the lines of ‘Strongly Typed Language’. Non the less, we both are instantiating something with ONE line of code. So far, we are equal.
My attribute class is smaller than your constant class:
[AttributeUsage(AttributeTargets.Property)]
public class EditableUiProperty : Attribute
{
public EditableUiProperty (string name) { this.name = name; }
string name;
}
Mine is 4 lines of code and has less members. So, now at this point, i’m using less code than you’re “ICONSTANT” or “CONSTANT” implementation. Also, if another developer looked at this, they wouldn’t even need to ask me what’s going on, it just makes sense and is clearly readable when it’s used……
[EditableUiProperty("Boss")]
public float BossPunchDamage = 8;
Now, i have no need for “IConstant” or the “ConstantManager “. So i don’t even code those.
So now, at this point, i’m using way less code.
We both use reflection, but since mine is based on attributes, my reflection actually performs faster, instead of looking for instances of objects and finding them by type, like you do.
In both approaches, we could choose to pull out this implementation so there is no sign of it in our production code.
Just like you said “when you’re done tweaking, you can trivially pull them back out”
You are not actually ‘pulling anything out’. You are changing the TYPE of these members to a value type when it was previously a reference type. If you do performance tests before you pull out all YOUR implementation, the results will be different after you go back, and change all those ‘constants’ to value types.
In mine, i can do this…..
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#endif
float BossPunchDamage
Wow! Now i don’t need to touch my code. No going back and changing a ton of stuff. I just put my project into ‘Release Build’ mode and those attributes no longer exist. It’s impossible to do that with your approach.
In mine, all the ‘constants’ stay the same type. It’s less obtrusive. My performance tests would be practically the same before and after.
Remember, every time your code reads one of these values for the game logic, YOUR code does the implicit type conversion. This spits in the face of OOP and strongly typed programming and is a performance drop when you multiply it by 1000.
On to XML parsing. If you don’t know how to pull values from XML in a few short lines, and wrap that into a reusable utility function, there are plenty of resources online. That’s hardly as complicated as using StackFrame to actually change source code.
Another benefit of my approach, is, you can write your ‘variable editor application’ separate from your game, and actually perform these edits using only the assembly of your game, instead of all the source code. I know that defeats the purpose of this article, but i think it’s a cleaner approach.
In all, you say it’s a taste thing, but i don’t think it’s that subjective. When you are coding in by yourself, then sure, nothing matters, but in pro world, this kind of stuff doesn’t fly.
I know you are sharing a cool thing you did, and i don’t want to shoot you down for that. Any time a programmer takes the time to share thoughts online, it’s a privilege for all of us. However, i think of the junior developers that might come across this and think this is totally great solution. So this is why i provide contrary evidence. And hey, who’s to say anyone will read this far down anyway (ha!).
That’s my rant. I like some of the other articles on your site, and you’re not a bad programmer. Keep up the good work.
#21 by Kael on October 2, 2009 - 8:32 am
Quote
Again, I think I agree with you in principle but I can’t agree with some of your conclusions here:
Constant<float> having implicit conversions to/from float is not inherently bad in any particular way. There are always ways in which implicit conversions can trip you up, but they’re not guaranteed to cause issues. In this case, it is highly unlikely that an implicit conversion to/from Constant<float> is going to do anything bad: There will be no silent loss of data, and no silent execution of code. Furthermore, an accidental implicit conversion in this case is extremely unlikely.
I also don’t understand your assertion that this use of implicit conversions violates the strong typing of the language. There’s nothing soft or fuzzy going on here; the only remotely unclear thing is what happens when you assign a value like ‘9.3′ to a field of type Constant<float>. I would hope that even a junior programmer could quickly understand the meaning of such a statement.
The decision basically comes down to this: Do you want to manually write out ‘new Constant<float>(x)’ or just write ‘x’? If you choose the latter, you’re paying a cost by introducing some ‘magic’ (the implicit conversion) in order to reduce the amount of duplication within your codebase.
The suggestion that it could be a performance problem is a strange one. Of course everything has an implicit cost, but I find it highly unlikely that an implicit conversion from Constant<float> to float would ever show up on profiles. It’s definitely never shown up on mine.
The only real significant performance impact I can think of is that it eliminates the opportunity for the compiler/JIT to perform constant folding, which could be a real problem in high performance math loops. Even then, though, I’d have to see a significant overhead in profiles before I’d believe it.
At worst, you’re paying the cost of a method call and a read from memory to fetch the value – that’s it. And theoretically, the .NET JIT can inline the implicit conversion (They don’t ever guarantee that it *will*, but the documentation says it can.)
The attributes still don’t seem any smaller than my approach to me. C# attribute syntax is too noisy for it to be a win on size. The fact that the attributes are decoupled from the rest of the declaration is potentially a win, I suppose, but I’ve never needed that.
Being able to use #if to make a constant not a constant anymore doesn’t seem particularly useful for me. I can’t think of a possible use case for this where it wouldn’t result in tremendous duplication. Of course, you can do this with my approach too – just #if/#else out the type part of the declaration – but I can’t imagine a good reason to do that either.
Saying you don’t need IConstant or ConstantManager suggests that you missed the purpose of those classes: Those are there specifically to enable simple, type-safe manipulation of your constants. There’s no way to magically get that functionality for free; it has to come from somewhere.
I also find your assertion that attribute reflection is faster to be dubious. Do you have any data to support this? Finding fields by attribute isn’t any faster than finding them by type as I understand it, since in both cases you have to enumerate defined types and then enumerate their fields in order to check each field for its attributes. Is there a helper ’search’ method somewhere in the Framework that performs this search for you more efficiently when aimed at custom attributes?
The suggestion that this approach ’spits in the face of OOP’ confuses me. I don’t understand. I wanted to be able to modify constants, so I created an object to represent a modifiable constant. I don’t see how this is inherently less pure OO than using an attribute.
I’m also not sure what ‘pro world’ you refer to in which techniques like this don’t fly. I’ve seen far worse techniques ship in commercial codebases. In the end, the determination is up to the people working on the app, and hopefully they make their choices based on what actually works, not based on fear or rhetoric. If this solution didn’t solve my problems, I wouldn’t be using it.
Pingback: The Week in Code « Sgt. Conker
#22 by Tom on June 21, 2010 - 10:11 am
Quote
I’ll be sticking with attributes. It’s a cleaner, faster solution, period. Yours is very clever but not practical for commercial, high-performance, team-driven applications.
#23 by Kael on June 21, 2010 - 10:17 am
Quote
I think you missed some buzzwords there like ‘enterprise’.
Anyway, while I still don’t see how attributes are any faster (I’d like to see someone actually prove it with a benchmark), cleanliness is always a matter of personal taste, so more power to you. Maybe you should share the source code for a good attribute based alternative so people have an easy choice between both approaches? I’ll gladly link to it in the post.
#24 by Barnaby Smith on June 23, 2010 - 2:35 am
Quote
This is a very interesting post and series of comments. I’ve implemented several tweakable systems in the past, but I’m looking to write a better one. I’ll be sure to link to this article when I post about it.