The short, mostly-accurate answer is “you can’t”. You should probably eliminate the argument on the function and just write the script to directly reference the variable you actually want to set.
To elaborate:
Usually, when a function takes a parameter, the value goes into the function, but any changes to the variable don’t come back out of the function. The input might not even be a variable at all; you could call that function with a line like changeVar("hello") where you use a string literal and there’s no variable involved. Even if you use a variable, the function gets a copy of that variable; it can’t modify the original.
But if you want the function to modify the original variable, there’s a special syntax that lets you do that. You can add the keyword ref or out to the parameter to change how it works and convert it into either a by-reference parameter (in which case the value comes in and goes out) or an out-parameter (in which case the value only goes out; no value comes in).
But if you do that, then the function also has to be called in a special way, and it can’t be used as a listener for events (because listeners can’t return any output to the caller). So that won’t help you do anything through the Unity inspector (at least, not with regular Unity events).
In order to make this work without “ref” or “out” (and therefore make it able to work with events) you’d want to add a layer of indirection. Instead of passing in the variable you want to modify, pass in a class that contains the variable you want to modify. Since classes are a reference type, that means your function receives a handle to the same class instance as the caller has, and any change to the contents of that class will be visible to the caller (even though modifications to the variable referencing the class will not).
And if you want to assign it through the Unity inspector, that class has to derive from MonoBehaviour, because the only parameter types supported in the Unity inspector are int, float, string, and MonoBehaviour.
(You would still hard-code which member variable inside the class the function is to modify.)
There are even more complicated things you could potentially do to work around some of the remaining limitations, but that’s probably the most complicated option you should attempt unless you are experienced enough to come up with the other options on your own.
My first hunch was using reflection. It is in fact, very easy to make a reflection setup for this, but I am not at all convinced that he/she wants to do this. So in the end, I’ve decided to instead ask this user what he wants, but in fact, I can’t tell how knowledgeable they are, so that’s what I ended up asking.
Yours is a good answer but I’m not sure how useful it is.
okay, so it would be something like a “StringClass”, it would have a single string variable in it, then I’d make an instance of the class, and pass that into a function that goes StringClass.s=text?
But I don’t see how I’d use the inspector to pass in an instance, since the instance wont exist until my code runs.
But anyway the only reason I wanted this, was so I have a cleaner way of setting variables from inputfields.
“directly reference the variable you actually want to set.”
this is what i did last time, with a different function for every different variable that i needed to set, and it ended up getting messy. But is this the only practical way to do this?
The class would need to be a MonoBehaviour (or perhaps a ScriptableObject?) and it would need to exist as buildtime as part of your Unity project.
If you want to be able to specify the function argument from the Unity inspector, you need to use one of the argument types that the Unity inspector supports for unity events, which are int, float, string, or MonoBehaviour.
If you are willing to set up the events from code, rather than in the inspector, then you have some more options, although I’m not sure they’d do much more than hide the mess.
You could use a script to set up the buttons to call a bunch of lambda functions that operate on different variables. e.g.
If your data structures are somehow conducive to setting these events in a loop, rather than one-at-a-time, then this might turn out to be very compact. If you want to specify each variable by hand, then this would still prevent you from having a huge list of slightly-different named functions in your class definition, but would still involve encoding an equivalent amount of information.
I suppose you could also use reflection to convert a string argument into a reference to a variable. I don’t recommend this. It’s inefficient and unsafe (if you spell the variable name wrong, or if the variable you were referencing is changed in a code edit, you won’t find out until you get a runtime error).
Instead of using regular string variables, you could store your strings in a Dictionary<string, string>, and the argument to the function could be a string that you use as a key to find the appropriate entry in the Dictionary. This has essentially the same problems as using reflection.
You could try to come up with an alternative approach to whatever larger problem you are trying to solve (one that doesn’t require every button to modify a different variable).
Exactly it must be an Object, the base type of base type of MonoBehaviour base type.
Anyway it’s probably if you need to pass as reference a no Component child into your UnityEvent, you might been wrong in the concept. If you share some code, we could help you about why you don’t need to pass a string as reference to your UnityEvent (or your Button, it’s an UnityEvent at end) instead of how you could do it.
Be sure to check out Action and Func system delegates, because you can just as well pass around delegates instead of references to primitives, and these delegates methods adhering to delegates might have access to a common object, thus sharing the values. This lets you do tons of polymorphic stuff instead of messy/spaghetti ui code in some cases. There is an overhead involved, but may unburden your primary logic of boilerplate.
I actually wrote a package I call Datasacks to more smoothly interoperate between data in your program and the contents of your UI. This is an overview of how it works: