Is there a way to reference value-type variables without using pointers or wrapper classes?
Like I don’t want to use:
//not this (especially considering unsafe code)
int* stuff;
//and probably not this
public class Things
{
int stuff;
}
I’m working on an editor so I can adjust the value of variables in-game (e.g. tuning jump height or walk speed), but the current way I’m doing it is overly cumbersome and inflexible.
It has crossed my mind to do something like this, but I’d like to keep my editor system within my main code, and not rely on forms. I also don’t know how to integrate a Monogame game into a WPF. It doesn’t mean I’ve ruled it out though.
Im a little confused by this. If your making an editor you must built some kind of ui system. Make a textbox where its value is whatever object you want (in this case an int) selecting something in your game changes tbis value to whatever properties you want it to, and changing this value updates whatever value is on your selected object.
There is no data binding on monogames ui controls, because there’s no inbuilt monogame ui controls. You can either use someone else’s library or make your own.
This looks like a use case for dependency injection also known as inversion of control.
This is basically passing a class that handles the parameters you want to change into the classes that use them.
Something like this:
// Interface class defining the parameters that are configurable
public interface IParametersHandler
{
float JumpHeight { get; set; }
}
// IParameters implementation that you can change from your editor
public class MyParameters : IParametersHandler
{
public float JumpHeight { get; set; }
}
// your UI class that gets 'injected' with the parameters when created
class MyJumper
{
private IParametersHandler _parameters;
class MyJumper(IParametersHandler parameters)
{
_parameters = parameters;
}
// using the 'injected' value
public void DoSomething()
{
float jumpMax = _parameters.JumpHeight;
}
}
...
Now the 'control has been inverted' i.e. the UI class no longer has control of the jump height etc
This is a c# question the simple answer here directly to the question is No.
Value types are pass by value.
Di and other tricks are standardized patterns and ways to do as you alluded to in the second option, Wrap the value type in a class type and then link those references to get at the wrapped value.
For example.
Directly without the interface that uses the di pattern.
public class MyGuy2
{
public string Name { get; set; }
}
public class MyUi2
{
MyGuy2 guy2objref;
public MyUi2(MyGuy2 objref)
{
guy2objref = objref;
}
public string GetParameter()
{
return guy2objref.Name;
}
public void SetParameter(string name)
{
guy2objref.Name = name;
}
}
public class TestClass
{
public void TestRegularRefenceLinking()
{
Console.WriteLine("We set up the guy and name him.");
MyGuy2 guy2 = new MyGuy2();
guy2.Name = "Bob";
Console.WriteLine(guy2.Name);
Console.WriteLine("We set up the ui inject the guy.");
MyUi2 ui = new MyUi2(guy2);
Console.WriteLine(ui.GetParameter());
Console.WriteLine("We rename the parameter in the ui.");
ui.SetParameter("Fred");
Console.WriteLine(ui.GetParameter());
Console.WriteLine("How about the change in guy.");
Console.WriteLine(guy2.Name);
Console.WriteLine("How about renaming guy bill and then looking to the ui value.");
guy2.Name = "Bill";
Console.WriteLine(ui.GetParameter());
}
}
The output and result is the same as di without being as generic.
This test result is the same for a int instead of a string.
This breaks down to this basically.
public class MyGuy
{
public string Name { get; set; }
}
public class MyGuy2
{
public MyGuy myguyobjref;
public MyGuy2(MyGuy objref)
{
myguyobjref = objref;
}
}
I know you don’t want to box your variables but you can have them only boxed in the editor like so. The editor calls a function to ask what properties the class has and it returns:
new Properties.Integer(delegate { return Price; }, x => Price = x)
and which calls
public Integer(Func<int> getter, Action<int> setter)
{
store the getter and setter here for use by the editor
}
I ended up going with delegate ref return calls to do this.
// Class variables
public delegate ref int D_int();
D_int linked_value;
int editor_value;
MyReferencedClass myReferencedClass; // class ref that I wish to view in editor
// Method
ref return int ID() { return ref myReferencedClass.id; }
// Constructor
linked_value = method; // method is a parameter, and is ID in this example
// Update
ref int newValue = ref linked_value();
if (editor_value != newValue)
{
editor_value = newValue;
Update_stringBuilder;
}
I also used reflection to generate the variable name for my string label, so I didn’t have to type it twice when I create the object.
string var_label = linked_value.Method.Name;
These work pretty well, and easy to keep separate from my gameplay code.
I also liked the interface idea from jonathanmcc. I could think of some uses for that elsewhere in my code.