I wanted to toss out an idea. It might be solved in Udon2 but until then I wondered if there was a “hack” that might work. While we can have static classes and methods we (apparently) cannot access non-static properties of such a class. If we get this with Udon2 then the problem is (eventually) solved.
What would be nice is a single public static object defined in a world that could be set as the world is being instantiated. Without such a thing we are stuck with 2 alternatives. GameObject.Find or assigning a reference to the global object in every other object. One can pass a reference in a method as well but that is about the same as assigning it in the inspector.
.Find isn’t out of the question and if the object is at the top of the hierarchy might not take too long to run 100s of times. Assigning a reference is what I’m doing but it is a hassle and it is easy to miss one.
I’m thinking of writing an editor method to automate this but it is still a hassle.
Imagine an “App” game object that has an App script. It can include common settings, often-used methods, config settings, etc. Lots of other code needs access to it but there is no simple way to get it. As mentioned above a static property (if it was supported) would work, even a static method could work but such a method cannot return an instance variable so in reality it won’t work.
Do I have other alternatives?
Yesss, they need this!
Theres a silly workaround that I have made, feels kinna janky, but it works for now! Heres a sample code. You can add any variables and methods you want in the STATIC
class
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using VRC.SDK3.Components;
#if UNITY_EDITOR
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(STATIC))]
public class STATICEditor : Editor {
public override void OnInspectorGUI() {
base.OnInspectorGUI();
if (GUILayout.Button("Set all STATIC instances"))
SetAllStaticInstances();
}
private void SetAllStaticInstances() {
STATIC staticInstance = (STATIC)target;
Component[] allComponents = Object.FindObjectsOfType<Component>();
int foundCount = 0;
foreach (Component component in allComponents) {
if (component == null || component == staticInstance)
continue;
//PropertyInfo[] properties = component.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance);
FieldInfo[] properties = component.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
bool found = false;
foreach (FieldInfo property in properties) {
if (property.FieldType != typeof(STATIC))
continue;
property.SetValue(component, staticInstance);
found = true;
foundCount ++;
}
if (found)
EditorUtility.SetDirty(component);
}
}
}
#endif
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class STATIC : UdonSharpBehaviour {
public int commonVariable;
[HideInInspector]
public VRCPlayerApi specialPlayer;
void Start() {
//Stuff idk
}
public string ATestStaticMethod() {
return "Very special and important string that every script needs :3";
}
}
Add this to a GameObject somewhere in your scene, I usually add it with the same one my VRCSceneDescriptor
is on. Make sure to press the Set all STATIC instances
button, this makes sure that all scripts that reference static has a reference to the STATIC
class. (If there is anyone who knows how to run this method automatically upon editor run/vrc compile, let me know :o)
And it can be used something like this:
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class SuperNotStinkyClass : UdonSharpBehaviour {
public STATIC Static;
public void Update() {
Debug.Log(Static.ATestStaticMethod() + Static.commonVariable);
Static.commonVariable++;
}
}
Wow, thanks. It is a bit “janky” as you say. I don’t think I’m willing to edit all the code if I can avoid it. I moved all the game objects under a single root named App. That makes finding the class a piece of cake.
I have a lot of custom processing on start up now and it is working like a charm and it takes only a fraction of a second to process it all so I’m happy.
Thanks for posting your code.