The issue is that the owner is able to access the public non-synced vars of another UdonBehavior within an UdonBehavior, but no other player’s instance is able to read (or write) these non-synced variables, almost as if they are not actually public.
There is an array of UdonBehaviors (SyncedSystem) because this controller needs to be able to select one of many to use at a time.
The UdonBehavior(SyncedSystem) contains a name which is set in the main script from another script on a button. The owner of the Controller prefab runs this and syncs the byte index of the SyncedSystem in the array (RequestSerialization() is called at the end of the encompassing loop not seen)
Once the state for applying a selection is reached, the indexed of the UdonBehavior(SyncedSystem) is read from the array.
It’s almost as if the non-owner players cannot interact with the public non-synced variables in the array member’s UdonBehavior(SyncedSystem) array… because ownership applies even to instances of scripts without synced variables and thus only a locally-relevant scope? (Surely it can’t be that, because that would be strange and cruel)
Let me explain why I’m trying to do this pattern. In previous attempts, I put everything within a single script and it was hideously unreadable despite mostly working. Because I want to be able to reuse this code for multiple things, the amount of “hard coded” specificity in the original script was inappropriate. I’m rewriting it to be generalized, operating under the assumption that you can read variables in other UdonBehaviors and that they are kind-of Classes in the C# (Not C++ or C) sense, appropriate for storing a set of variables that should be scoped together.
Is there a decorator or something beyond “public” that I’m missing?
I did attempt to add a method which ran on every loop that would round-robin the ownership to a different player on each run (I was angry), and it’s of note that it was not possible to determine if this actually resolved anything, because the abnormally large amount of SetOwner() and related events getting called easily clogged the network and prevented the state machine from advancing. I had previously tested the ownership access thing by changing ownership between players with a button and it is indeed ALWAYS the owner that’s the only one getting outputs that indicate they can access vars in other UdonBehaviors.
It’s not very clear what your issue is. You’ve come to this conclusion that you can’t access variables, but what exactly leads you to that conclusion? Have you tried logging these variables? If you can’t get them, what do you get? The default value? An old value? A null?
I have two GameObjects with two different Udon scripts in them.
GameObject A has an Udon script (Script A) that needs to read a variable inside the Udon script in GameObject B (Script B).
Both scripts are in the same namespace.
Script A is set to Manual Syncing Mode and contains 2 synced bytes.
Script B has no synced variables.
The scripts are the only things on the GameObjects they occupy.
When I test it, Script A is able to read public variables in Script B for the Owner of GameObject A, but returns null for those same public variables for all other non-owner players.
I have found the cause and a solution to the issue:
The public variables (including arrays) in other scripts can be accessed by direct reference ( foo.bar[SyncedIndex] ) but don’t appear to be able to be copied locally to a script by a player that doesn’t own the script into which they are being copied.
I solved the problem by removing all situations where I was copying variables from remote scripts and replaced them with direct access.
This is what didn’t work:
CopyOfBar = ScriptB.Foo[SyncedIndex].Bar;
Result = CopyOfBar * 2f;
This is what worked:
Result = ScriptB.Foo[SyncedIndex].Bar * 2f;