I am programming some small apps with algorithmic/simulated computer generated content. These are not games, but more like small sandboxes to play around with. For an example of this you can check out this prototype: http://emerganz.com/LorentzTrails.html
Each scene will have a number of configurable parameters. These are easy to tweak in the editor (via the Inspector), but I would like for them to be tweakable in the final build as well. Since I’ll be doing a lot of scenes I’m wondering if its possible to automate (or semi-automate) this process.
To be specific: a GUI script that takes another script as a parameter and looks throgh that script for public variables which is then represented with appropriate GUI controls (sliders, drop-down, checkmarks etc.). Using the GUI controls then changes the parameters of the script.
Alternatively to looking through all public variables it could also require a certain data structure to be present (ala a struct) which is then parsed by the GUI script.
Preferably this would make the variables accessible both inside the game and from the editor’s inspector, however this is not an absolute requirement.
My question is what is the best way to implement this? I am fairly new to both javascript and C#, so I’m not familiar with their introspection features.
I recently posted a somewhat speculative reply to a thread, and then was embarrassed when someone else posted a much better answer. This answer is speculative as well, and maybe the same thing will happen here - I suppose we’ll see.
Anyway, I believe this can be done using reflection. I put together the following quick test code in C#:
InspectorTarget.cs:
using UnityEngine;
public class InspectorTarget : MonoBehaviour
{
public float field1;
public string field2;
}
Inspector.cs:
using System;
using System.Reflection;
using UnityEngine;
public class Inspector : MonoBehaviour
{
public InspectorTarget target;
void OnGUI()
{
Type type = typeof(InspectorTarget);
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields) {
if (field.FieldType == typeof(float)) {
field.SetValue(
target,
GUILayout.HorizontalSlider(
(float)field.GetValue(target),
0f,
1f,
GUILayout.Width(100f)
)
);
} else if (field.FieldType == typeof(string)) {
field.SetValue(
target,
GUILayout.TextField(
(string)field.GetValue(target),
GUILayout.Width(100f)
)
);
}
}
}
}
And this worked as expected. Note that when running in the editor, the values set while in ‘play mode’ will not be preserved once you’ve returned to edit mode (which is the same behavior you see when modifying values in the Unity inspector while in play mode). If you want the values to be saved (either to the scene, or between runs of a standalone app), you’d have to take some extra steps to make that happen.
Also, the above code is of course type-specific; I didn’t bother trying to figure it out for this brief example, but I imagine reflection could be used to make the inspector work with an arbitrary type instead.
Again, this is speculative, and there may be some problem, issue, or better solution that I’m overlooking. But, for what it’s worth, the above code does seem to produce the desired behavior in my test project.