#udon-networking
1 messages · Page 3 of 1
I hate dyno
I spent so long writing that
Can a mod bring the message back? I am not writing it all again...
"No spamming" what a trigger happy bot. It was literally one message
Maybe try to call some active mod to get the message back?
@misty temple Hey, sorry to ping you. I wrote a long explanation on mobile about polymorphism and dyno nuked my message for no reason. Do you have a copy of the message contents somewhere in the bot logs? And if so, could you please send it to me?
Thanks in advance!
Ahhh, into the void
:(
return polymorphismExplanation;
The string was too long to be synced :p
I sent some explanations in DM
When inheriting from a class if the class has virtual or abstract methods you can override them. This means that if the method is called your implementation is called instead.
Let's say you have a lot of enemies that you all want to take damage.
You could then create a class Enemy and implement your
protected virtual void TakeDamage(float damageToTake)
{
}
protected is an access modifier just like private and public. It means any inheriting class has access to it but not external classes. So it's pretty similar to private.
Then you could create a class for each enemy and inherit from the Enemy class like so:
public class Slime : Enemy
{
protected override void TakeDamage(float damageToTake)
{
//stuff specific to slimes
base.TakeDamage() // you can also call the base implementation of the method if you want to. But this is optional.
}
}
here's your question:
so by reading a bit about the VRC networking I noticed that post requests are not allowed which is hell, as it makes overcomplex a simple problem of syncronization. so, I have a question. I'm trying to have 3 things synchronized
- a random number that's generated each 30 seconds
- a value that is added each 30 minutes (for a map changing system)
- the timer to keep all players game running under the same conditions
so, provided that VRC disallows GET request from a website.
I read that the way of addind synchronized objects is by doing a pool so my idea is to make
Obj_manager >> has component pool and indexes:
- Obj_timer -> for variables - has started, has ended
- Obj_random_event ->> for variable random event (just the random number)
and - Obj_map_changer ->> to synchronize the map ID (with a switchcase it will change ambience wo it only needs to sync a single value)
how can I tell the object pool which variables inside the objects are being synchronized in order to keep those three for the game
thanks
hm, I think an object pool is way overcomplicating what you need. It sounds like you literally just need one object with a synced variable
for what it's worth - you can effectively get strings and images from the web. https://docs.vrchat.com/docs/string-loading
sending arbitrary data to the web is restricted to prevent mass amounts of personal data being exfiltrated, such as precise tracking data over a period of time which can be used to de-anonymize someone and track their IP address.
but regardless, none of that is relevant because sending to/from the web is absolutely not the right tool for simply syncing with other players in the instance. That's what realtime networking is for, with synced variables and network events
oh ok, im actually trying to use an API, so users can control the game from a browser, or give more flexibility and reduce download size, I noticed there are some worlds of 500mb which is kind of exagerated, and for a poor 256gb SSD it's painful to have such worlds, also PHP gives me more control, and will allow me to have just 1 object managing all the game events
when you join a vrchat world, you have to download and unpack the whole thing. If your goal is to save download size then you need to make separate vrchat worlds
you're going waaaay off into the weeds here trying to come up with a solution that won't work when there are already solutions that do work. It would help if you more clearly stated what your actual goal is
the actual goal, it's synchronize events, the api returns a JSON with 3 vars that's the only use
now
for the variable synchronization on Udon
how could I determine which are the specific synchronized variables (without graphs)
right but udon already has ways to sync
in udonsharp, you add [UdonSynced] Attribute before the variable
this only applies to primitives like float, bool, int, string, and arrays of those
ok, perfect im just using Int
so, in case of a random event selector
I would do:
[UdonSynced] randomval = math_random_idk_func();
right?
the basic method for syncing is to:
- Take ownership
- Set the variable
- (if udonbehaviour is manual sync) RequestSerialization
Then other players receive OnDeserialization, which is the event that says "I have received synced data" and you can use the variable
No, you're mixing up the variable declaration and setting it. You need to declare the variable in one place outside of a method, with [UdonSynced], then in another place inside a method you need to set the variable using the random function
????
just post pictures
can you post a picture of it?
a few things:
-
You definitely don't want to be deciding on a new random variable on update, that would make it change every frame, roughly 90 times per second. You probably want to store a float of the last time that a map was chosen, and check if enough time has elapsed before choosing a new random variable
-
IsInstanceOwner indicates the person who created the instance, which may be someone who isn't even in the instance anymore. It has no bearing on networking. You need networking.IsOwner(gameObject), which indicates the person who has ownership (and the person who can send synced variables) of the object this script is running on.
-
In OnDeserialization, randomvar will simply be the new value set by the owner
-
For a random function, you'll probably want Random.Range
-
As this is a variable that only needs to be updated very infrequently, it would be best to set this to manual sync. To do that, you can put [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] before the public class.
-
If you set it to manual sync, you need to do RequestSerialization after setting the variable, which will send it to other players
wait, update happens per frame and is synced with the drawing?
if by drawing you mean rendering, then yes
(just ignore this)
Why is my code being deleted?
Our Moderation Bot Dyno can be quite mad about you posting code in here due to the many spaces you usually end up with.
In cases like this it’s best to just post a screenshot of your code or only a small part of it.
oki
then using it with a timer is a terrible option
thanks for the advice
but then how can I make a timer?
I saw a tutorial where someone added a counter in there
if you just need to make an event happen some time in the future, you use SendCustomEventDelayed. However, as this timer is over a long time period and the previous owner may have left in that time, that's not necessarily the best way to do it.
You need a synced timer, so one way to do that is to have a synced float representing how much time is left. Then a local float representing the last time that it was checked. Occasionally, you check the time by taking the difference between previous time it was checked and the current time, and subtracting that from the time left. If it's negative, then that means time is up.
This doesn't cover how to sync it, but at least that's a timer system that would be capable of being synced when you're ready for it
but, i mean, it's a delayed event repeated, I read from unity and people use the update from monobehaviour, as a while(1) is a terrible option to do
while loops aren't inherently bad, they're just unsuited for this application because udon code runs on the main thread, and there is no way to Wait(1) while on the main thread. So if a while loop gets stuck looping in the main thread, it will freeze the entire application
as it happens with any game
that's where my question comes in
how could i use the timer on other thread?
like
to avoid update
udon only runs on the main thread
if you want a wait function to only check once a minute, then you can use SendCustomEventDelayed that calls itself
recursivity?
kinda, but not technically because it's not being called immediately
just queueing it up to be called later
ohhh so delayed event makes a stack of events and once a determined time happens, it calls the last event from stack right?
nothing to do with stacks, but yes
it's just a list of events and times to call them
sorry im used to c++ xd on c++ queues are called stacks sjsjsj
okok thank you for the support!
Is it for example possible to tune back the trigger happy-ness on the "stop spamming" by requiring more than one message to trigger it?
A queue is not a stack though.
A queue is LILO/FIFO while a stack is LIFO/FILO. They are different data structures for different purposes.
Though a Queue can be implemented via a Stack, but it usually isnt.
are managed pretty much the same the changes are 1. the order of "attendance", 2 on the stack you can't remove an element from the center, but are pretty much the same stuff
how are they the same??
already explained the similarities, yes I admit i made a mistake mixing them up, but they are still pretty similar, and as described before it looked as a stack
On the website
https://udonsharp.docs.vrchat.com/udonsharp/#udonsynced
under "UdonSynced", the link for "Synced Variables" (https://udonsharp.docs.vrchat.com/udonsharp/vrchat-api#synced-variables) does not work
Edit: Just realized what it said at the top of the page 🤦
All supported attributes in UdonSharp
Open canny post to report
Where? How?
When you make multiple calls to RequestSerialization() from different classes, will the calls be made (and processed by others) in the same order?
no
RequestSerialization(); Just marks the gameobject as having new data that you want to be synced. If you change the data again and call RequestSerialization(); again before VRC has actually gone around and synced stuff, your previous RequestSerialization(); wouldn't do anything.
If you have a sequence of events that you need to be synced you need to store that sequence and sync it in it's entirety.
You can do this in OnPreSerialization() as it gets called right before vrc is about to sync data.
So it would go like:
Action happens => add it to the sequence of actions that have happened since the last sync and RequestSerialization();
Action happens => add it to the sequence of actions that have happened since the last sync and RequestSerialization();
etc.
(The above can happen many times before VRC comes to sync the gameObject.)
OnPreSerialization() You transfer the sequence of actions to your synced field. And clear the stored sequence of actions since the last sync. (since we just synced it)
Synced field gets read and sent.
Synced field gets set for remote players.
OnDeserialization() runs for remote players.
what about multiple objects?
I have say, a parent object, tells a child object to change its values, that child object RequestsSerialization
Then the parent does some more work, makes its own value changes and calls RequestSerialization on its self.
I feel like the most 'safe' thing to do would be to move my state data in the parent object and have a single source of truth and data sync. Child objects would then keep functions, set themselves to no-sync and just get and set state on the parent.
The local player NEEDS to be the owner of the GameObject that is calling RequestSerialization(); otherwise it will be ignored.
Definitely much easier with a single source of truth.
I finally figured out the issue I was having and it was this.
So when a person hits the next button they become an owner.
It does the IntractableCards() inside this script but then has to call another script: PlaysTurnsTopic to do the Rotate Turn()
If that script is on another gameObject, correct me if I'm wrong, but if you want all the UdonSynced data to be synced, you need to call
Networking.SetOwner again, but on that SEPARATE script on that SEPARATE gameObject.
If that script is on another gameObject.
doesn't this have a infinite loop which freeze the game?
The while loop?
Yea
Yeah, I'm pretty afraid of that thing. But it's connected to some other stuff. Hang on a second.
Ah no my bad
This function always fires first.
But you're right, if that while loop for whatever reason goes first, I'm screwed.
I should probably add hard count-out to prevent it.
Something like this:
Not sure what the best practice is for while loops, I'm open to any suggestions cuz they terrify me.
But that's outside the scope of networking I think.
Feel free to DM me!
Currently I try to figure out the use case of Datalists because for now they are kinda useless to me. It doesn't help with real problems like sync a list of GameObjects for all players such as adding new.
Oh, this is interesting.
Yeah it's maybe good for list of strings, ints, floats and bools but you also can just use arrays as before for it.
Everything is an array in U# it seems. Anyways, I'll check out datalists later, you have a good one.
Yea I don't understand why they don't just implement existing Lists and Dictionaries and Newtonsoft. I mean it's there already and you don't have to install something for it XD
String and Int on same Udon, if i manual sync the Integer, will the already existing string cause any problems, like try to serialize itself depsite its value being unchanged?
Yes. The entire data of an UdonBehavior is serialized together.
Hi,
I'm trying to spawn an object for my admins but they appear on people randomly...
what am I doing wrong?
You shouldn't be doing this for all users, you should be doing it locally only
You could have all users do it locally, but if you did then you wouldn't want to use a vrc object pool because that's synced
there shouldn't be any need for networking here tbh
oh, so the syncing of the pool is messing it up
I'm not sure, but it's extra complexity for little reason.
Hi, so I'm trying to come up with a simple room counter. An example would be we'd have 10 rooms the doors to each room shows how many people are inside.
My idea for it is to have a trigger surrounding the room and on PlayerTrigger Enter and Exit, set the ownership of the script to said player and increase / decrease the counter and sync it with everyone else.
The issue with this is that if the player exits the room before the ownership is set and the variable is synced, the counter gets messed up.
Does anyone have a better idea to pull this off?
Don't need to sync any of this. OnPlayerTriggerEnter() gets called locally even if a remote player is entering the trigger.
oh! that makes things a lot easier >w< thank you!
np :)
also back to thise one with the object pool, I made it so that only the instance owner controls the pool. but there is one main issue that makes it useless and I couldnt figure out why.
If you join an instance that already has an instance owner other than you, you'll see the objects and everything works perfectly fine. but as soon as someone else joins which would result in the instance owner redistributing the pool objects, everything will be gone for you, but the new player will see them fine. just like you did before. so it always works for the last player who joins and breaks if someone else joins. I keep looking at the code but the logic seems fine... not sure what I'm doing wrong >w< this is hard lol
You should just do it all locally there too
Networking should be avoided where possible
on Start() you can just check the names of all the players in the instance and for the ones that match you just assign them one of the follower object things and assign it the player to follow.
with public override void OnPlayerJoined(VRCPlayerApi player) you can just check player.displayName against your whitelisted names.
You can use an object pool without sync to avoid instantiating and destroying so many objects
OnPlayerLeft you check if they have a follower thing and return the object to the local pool.
yes I'll try that ^w^ thank you ❤️
The problem is that when a user disconnects within a triger it doesnt trigger a player leave event, so if anyone disconnects within the region the counter will get thrown out.
VRC should just fix it
We shouldn't be making workarounds
Yea its pretty inconvenient
wrote my own door counter and found that out pretty soon, had to make a workaround for it
Got a bit of a tough issue. This morning I had a strange error when I started up my project. Forgot to screen shot it but I rebuilt the SDK Reloaded Usharp assets and recompiled all program sources. The error cleared but for some reason ownership transfers are messed up and not updating properly. I'm using Phasedragon's simple object pool and it still works on the current uploaded version, but not in the untouched unity project. So now until I can get it to function like it supposed to I can't even upload any updates or it will break. I don't get it it's literally unedited from yesterday.
You need to make another custom event where you perform this action, and on interact you just sendcustomnetworkevent to trigger that on all clients
that's SendCustomEvent, you need SendCustomNetworkEvent
that should do it
set the audio source to play on wake false
@cold laurel I guess we should continue this here. So this is the code and my understanding of it is there is a synced boolean variable and a game object variable. On start the boolean is set to be true if the object is initially enabled and false if it is not. When the button is interacted with, if the person interacting with the object is not the object's owner, they are then set as the owner of the object before the value of the boolean is flipped and serialization is requested.
On deserialization, if the person receiving the serialization is not the owner of the object, the object is set to the value of the boolean. Does that sound about right? I feel like my confusion is about when serialization is supposed to be requested, is it like this, just after the value of the boolean is set? What if I want to do this to multiple objects? Does it require multiple booleans? Can an array be used or does it require an array of booleans? Do I need another unique boolean for every instance of this script or is "IsEnabled" something that can be synced and remains local to every instance of its usage?
You can see I don't use a lot of Visual Studio. Up until recently I would just edit stuff in notepad.
I recommend declaring the sync mode in the script like this above the class:
[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
The not owner check inside OnDeserialization() is not necessary as OnDeserialization() is only called for remote players.
This script is from VRChat so that's on them, I'm just trying to redo it in graph because I have some stuff already in graph and I don't want to have to completely trash it to set up syncing if I can avoid it.
At least I think this is an official script, it's inside of the UdonSharp project files
So I'm just trying to recreate what they're doing in graph
It's the GlobalToggleObject script if you want to have a look at it yourself
You'd only want to set the isEnabled bool in Start() if the local player is the owner. Late joiners get OnDeserialization() called.
The sharp script should work fine tbh
Assuming the sync mode is manual
Yeah, it's just that I already have a bunch of stuff I'm doing in graph and it's used on dozens of objects that already have their references nicely set up so I'd like to be able to use this as a piece of graph I can plug into those programs without destroying all of those references.
I'd hope the Sharp script works or else they probably shouldn't have released it with the SDK.
I also need to do this with multiple objects in one program so I guess I either need to have mulitple booleans or do this with an array but I'm still hazy on how one would go about syncing multiple objects in an array and whether than could be done with one boolean or would require multiple. I'm setting all of the objects to either off or on but I need it to work on multiple objects.
Ideally, it would just set one boolean and apply that to an arbitrary number of objects since their values will all be the same.
You want to sync the active state of many toggles in one script?
Ah
For the sharp version I would iterate over the array of objects you wish to change the state of like this:
public override void OnDeserialization()
{
foreach (GameObject toggleObject in objects)
{
toggleObject.SetActive(isEnabled);
}
}
I guess that makes sense, what's being synced is the boolean so it's just a matter of making sure all the objects get that value. I still need to do this in graph if I want to avoid a bunch of extra work but I'll keep working away at it and see what I can come up with, thanks.
Good luck :D
Is this anything? What I'm trying to do is do through all the elements of the array, checking for ownership and setting owners of each of them if the local player is not the owner and setting all of the elements of the array to the flipped value of the boolean to work as a toggle. What I'm concerned about is first does this make any sense but also will this keep flipping the value of the boolean? It shouldn't because the boolean isn't being set by the loop, or at least it doesn't seem like it.
The Set IsEnabled node is there as I think I actually need to change the value for OnDeserialization but I wasn't sure if there was a way to plug that directly into the SetActive node
Though I guess what could happen is it uses the flipped value of the boolean once and then after it sets the value of the boolean it negates the negation which wouldn't be what I would want. Not sure what to do there.
wait, do you have a bunch of toggles that you want to all change the same setting?
I want to set 3 objects all to be off or on and sync them
All 3 objects will always either be off or on
why are you negating the isEnabled bool
it should be 1 to 1 with the active state
I'm not sure, but shouldn't there be a node entry for OnDeserialization()?
God graph is such a mess
😆
It's a toggle so at some point it needs to be switched to set the active state to be flipped, right? Otherwise we're just setting the object to be active if it is and not if it isn't. I revised things a bit since I realized I wasn't ever executing the loop which seems like an important thing to do. There is an OnDeserialization node but I'm just focusing on the requesting for now
Yeah, but you would only want to do that for the owner right
The code version of that being
It needs to change the value for everyone or else how is it toggling them?
Yes
(you don't need the IsOwner check there)
Entry point? You mean Start? I can show you all that I have but I'm just trying to recreate the steps in the code
I was just trying to do that since it's part of the included code but I can delete it
you're doing the oposite
So then this?
It is, should it not be? It's all in one script in the U# version.
It should be
I do wonder if there's an edge case reason for checking for ownership on deserialization as I'm not sure why they would include it otherwise but if it works, it works
There isn't
I'm just not sure if my order of operations is properly set up or if I'm flipping the boolean a bunch of times when I just want to negate it once every interaction
Just flip it for the person interacting. Make sure they are the owner, and mark the object for Serialization. (just listing the required steps)
Is that not what it's doing? I'm not sure how what this code is doing is different from that. It's not flipping it OnDeserialization, just before requesting it
Is it not working?
I'm still not 100% sure how it knows what it's serializing. I'm flipping the boolean then requesting serialization but I'm not requesting serialization of that boolean specifically. Does requesting serialization request serialization for all synced variables in the program and set them to the values for the owner?
It syncs the entire object and all it's synced variables at once
You can't choose which synced field to serialize
I haven't tested it, just figured I'd post it for review before doing that. The first version certainly wouldn't have worked but this one might.
Should synchronization be manual or none?
I'll try manual, seems right
manual
Yeah, doesn't seem to work. Unless there's something obvious, maybe there's a place where I could put a helpful debug log? 🤷
Could it be due to this error? Comes up whenever I compile and the references in the inspector don't seem to be updating when I remove variables so maybe it's not compiling properly even though I can enter play mode with client sim and it doesn't crash when I interact with the button, it just doesn't do anything.
Just copied the nodes over to another program and it doesn't compile so yeah, it's probably whatever that is
Seems like maybe I'm trying to access an array element that doesn't exist? But I'm either ending at the length of the array or I'm just using the 1st element of the array (at position 0) and my array had 3 elements so I'm not sure what would cause that.
try logging a bunch
Well, now that I recreated it, I can't even compile it to set up my references so I don't think a log will tell me much. I guess I just need to recreate it from scratch, maybe I just need to make sure I'm setting the size of the array before doing anything with it. Thought I did that the first time but maybe not. Luckily, I thought this might happen so I made a screenshot of the program.
@cold laurel Okay, so I started recreating it and the error comes up right when I try to connect the Gameobject[] Get node to the for loop int index even though that's exactly how PlayerBush001 does it as far as I can tell.
I tried using an addition node to add 1 in case there was an indexing issue but that doesn't seem to be possible to hook up to the int index and starting at 1 rather than 0 doesn't do anything either.
I'm sorry, I'm not familiar with the specific quirks of graph
I think I got it, thanks. It seems to not have any issues if I use a separate instance of the variable than I'm using for the "IsOwner" check even though it's pointing to the same Array.
So I have this new version that runs without errors but still doesn't do anything. I'm thinking it may be because when I enter the instance, I'm automatically the owner of all of the objects and since it only runs for someone who isn't the owner, it won't run for me? Or am I confused about how that works?
It's also only checking for ownership of first object in the array which should have the same ownership as all of the other objects but I'm thinking if I'm not setting ownership of those objects, I'm not going to be able to request serialization on those objects which isn't ideal but I figure it should at least set the first object to be active but it does not.
aren't you using Start()?
That's just an image of interact since that's what I changed, the Start stuff is all the same but I'm not setting ownership on Start, just setting the boolean equal to the 1st element of the array's active state.
check ownership on start
How should I go about that? Check IsOwner and then what? Should I do anything with it?
That's not in the original script but I can add it
you're checking master currently
How do I hook it up? GetOwner doesn't have a boolean ouput. Should I have a loop that sets IsEnabled 3 times? I was thinking just use the 1st element as all of the objects will have the same initial value. In fact, all of the objects will be disabled by default so I'm not sure if this is even necessary.
isOwner
not get
Ah, okay
I think you need to check the "send change" box
Okay, should I also do that when I set IsChanged on interact?
Still no luck. Am I wrong that it's a problem that the interact only runs if you aren't the owner of the objects in the array or is ownership not granted to anyone until it's set manually? In which case that Start code won't run, will it? Since I wouldn't be the owner of anything?
it should run for anyone that clicks it
Does this part of the code not tell it to execute everything after the branch only if they aren't the owner of the objects in the array?
you need to be checking ownership of this object, not the ones you are toggling
if you are the owner, just continue
if false
Owner of the button?
yes
set ownership of the button
Okay, well that's different. I'll try that
So this? I'm still a little unsure as to why I'm checking whether someone isn't the owner of the button to activate the rest of the code.
if the person clicking the button isn't the owner then we need to make them the owner.
if they're already the owner then we just run the rest
in both cases we run the rest
Okay, right now the rest isn't being run at all if they are the owner so I'll need to fix that.
we just need to do this first before continuing
So like this?
yep
That did it! I still need to make sure it's actually syncing, not sure if that's possible to test on my own but it works for me and I can get some people in to test it. Appreciate the help, I'm not looking forward to having to remember how all of this works for more advanced cases but at least I can sync an array toggle by just copying this code 🙏
you can build and test with multiple clients
I guess that's true. I was thinking it wouldn't test for late joiners but I guess if there's no network events, it's either synced or it isn't.
you can rejoin the instance
Alright, so I tested with multiple clients and it's not encouraging. The first instance that loads up needs to press the button once to turn the object on whereas the second person needs to press it twice and neither of them seem to be synced with the other. Also neither person can turn the object off regardless of the number of times they press the button.
you should do the negation separately from the loop
just do it on interact directly.
Now that you mention it, the Set IsEnabled node wasn't even hooked up to flow at all so that would cause some issues. Thanks, I'll test in a bit and report back.
Hooking up flow to the Set IsEnabled node allowed for the object to be toggled locally but still no syncing so I tried setting up Start this way. It didn't make sense so me why I was getting the ownership of an element of the array if what matters is ownership of the button but this didn't seem to fix anything. The first person to interact with the button can immediately toggle the object locally but once it's been toggled once, for the other player to toggle it, they need to press it twice which seems to me suggests that they're having to interact with it once to get ownership and again to execute the rest of the code even though it should all be connected.
no
you are not supposed to set owner in start...
Okay, but am I supposed to be getting the owner of the elements of the array or the button?
no
why would you
I'm not really sure why I'm bothering with the owner at all in Start but I thought you said I was supposed to.
because we need the owner to make sure everyone else knows what the state of the button is
Isn't that what setting it on Interact does?
This is what it was before I changed it but that also didn't seem to be working so I tried to fiddle with it.
Just remove all of start
Okay, I'll try that. All the original script uses start for is to set the value of IsEnabled and all of the objects should be disabled to begin with anyway so as far as that goes it shouldn't be necessary.
Removing start didn't seem to change anything for better or worse. It still takes 2 interactions to start toggling the object and there's still no sync. Here's the full program as it stands now.
Alright, so I found one tiny issue, that code was never actually requesting serialization (must've gotten missed when I initially recreated the graph). 😅 Alas, adding it after Set IsEnabled gets flipped didn't seem to fix anything, it's still not synced but progress maybe?
I'm just requesting serialization after the boolean is flipped since that is ultimately what is being used to set everything on deserialization.
I'd chain the setting of the bool and requesting serialization right before the for loop. And right after the ownership has been confirmed.
Like this? Still no luck, no syncing and it still seems to require cone interaction to gain ownership and another to toggle the object.
I still haven't tried it with other people but I imagine if it doesn't work with multiple local clients, it won't work with remote players either.
I think you might need to plug the button into instance for the RequestSerialization node
Doesn't seem like you can plug a GameObject in there, when I hover over it, it says it's an UdonEventreceiver
I honestly don't know, this looks like it should work fine.
I'm sorry that I can't help that much with graph.
I just don't see any value in learning it for myself
No worries, appreciate the assistance. I should probably just take this to #udon-general since no one looks at this channel even though it seems more relevant here.
I could use the Udon Sharp toggle script even though it would be more work but I'd still have to rewrite it to handle arrays which I would need to get asistance with but I guess that's plan B.
If you just did this in sharp it would be so much simpler imho
Yeah, it's just a matter of having to swap out all of my existing references which would be annoying since there are dozens of instances of the existing non-synced script being used whereas if I can do it in graph, I can just plug the new nodes into the existing program.
But if I can't get it working in graph, I guess I gotta do what I gotta do
I’m looking for a good freelance site to hire someone to code. Looks like people with udon experience is actually a little bit more difficult to find. Anyone have any advice on where to look?
Vrc traders? That’s for avatars
Do you have any other leads for people specifically who focus on Udon? I’m looking now, just hard to find through the Google’s. I’ve had bad experiences with people from Vrctraders.
there isn't really a dedicated community for people that do commissions with udon aside from vrctraders as far as I'm aware, but you could always ask people individually
That’s what it’s looking like due to how specific Udon is, the only thing im seeing online is the ability to hire for company projects where you post projects on hiring pages, but that’s an entirely different level. Due to needed a company/website. I’m just going to have to dig a bit deeper on the people I deal with I suppose and do some manual networking. Thanks for your time though, I’m hoping someone else here might have some insight.
What you even need done? Its either gonna be something you could learn yourself or just cost you a lot of money. You wont find much outside of asking people for commissions, udons just a niche limited c#.
My conclusion so far is that it will cost a lot of money 😆
Yea, as dev by trade I go by the hour and at least $40 an hour
For the low low cost of $28000 USD you can have your very own VRC vehicle system :D
HAHA. Fr fr. Makes me feel bad when I work on my own passion projects instead of all the commissions I get asked to do XD
Like Ccmon self, you could be making money!
This is low balling it pretty hard too tbh 💀
anyone knows why the data can be just not sent even tho it called the RequestSerialization()?
*might've figured it out
nop, didn't
Is the requester an owner of the object?
yeah, it sends the request onDrop of VRC_Pickup and transfers ownership to the dude hoding the item on pickup
I'm not sure if that works because it might conflict with pickup object trying to set ownership to a player holding the object.
it will just ignore it if it tries to transfer ownership to owner
update, seems to be the problem if sent not from the instance master
master doesn't receive the value for some reason
or more like it doesn't receive only the "" string
left is non-master trying to send stuff
right is what master received
also OnPostSerialization*, forgot to change text in debug log
ok this one is more readable, i need to make a better debug log UI
second SEND log tells that empty string was sent, but instance master on the right didn't receive it at all
is there something obvious that i am missing?
yes i do
i forgot to actually set the variable to have this value
yep, works perfectly now
that was a long 2hrs of troubleshooting because of this one line
and late joiner sync works now, that is enough coding for today
RequestSerialization() just marks that the object has data you want to sync.
If you instantly transfer ownership VRC might not have synced anything yet. Manual sync is only about every 0.2s iirc
is there any reason why it would ignore me setting local position/rotation to 0 when it definitely was called?
same happens with the rotation
is it too early to start moving object before "OnPlayerJoined" appeared on joining player's side?:
10s delay before sending data doesn't help
and it doesn't look like it waits 20s at all
Change your event to be public rather than private
how does it affect things?:
it clearly fires the function that zeroes to position/rotation locally for joining player since debug output is here
SendCustomEvent isn't able to call private events, if it is working properly that would be odd.
it doesn't send custom events, it uses the FieldChangeCallback's
even tho i almost feel like swapping them for custom events
Due to Udon not being real C# the way the functions get called isn't typical and is in most cases emulating C# in roundabout ways.
i mean
function gets called
it does
game just ignores the values it sets
it outputs the log message exactly where it should be fired, but later check in FixedUpdate if the same variables shows them not set to Quaternion.identity and Vector3.zero
Yes that should be working assuming you aren't applying different values somewhere else, I was just assuming you may have had your other custom events set as private as well whilst trying to use SendCustomEvent
does one object firing RequestSerialization cause all the other objects to serialize the data too?:
No, only for the object you called it on
but on all the scripts attached to this object, is it?
i feel like the serialization of sync script also causes serialization in the main one
both on the same object
Yeah calling RequestSerialization on one component will serialize for all Udon Behavior components on that object
might've got an idea then
i guess i will have to abandon and idea to use FieldChangeCallback's in this case
or make them not apply the values directly
that might work
nah, will have to use custom network events, i guess, thats annoying
The issue was actually because Udon seems to sync the variables on join, not only when I requested the serialization, even for manually synced objects , so values the objects were getting were contradicting and the one that was sent last stayed there
Hello quick question!
2 years ago, I made a Brick Breaker games in VRC and the ball was pretty laggy in multiplayer 😦
Does the physics synchronisation got improved since this point?
Else I'll try to dig some new ideas and even participate on the jam 😄
You can make your own physics sync implementation now with Udon, however there are already some you could download and try yourself for example: https://github.com/MMMaellon/SmartObjectSync
Ohhh nice! thanks a lot!
That setup is quite good but you would have to test if it works well for your usage
I will only have one ball at a single time and bricks
Other players will have to help or disrupt the gameplay of main player
I guess it should not be that heavy for the bandwith
That is true. You can't mark a single script for serialization. Only the whole gameobject.
I highly doubt that you need to use custom network events together with synced fields.
It's a terrible idea as it's not late joiner compatible, and you're causing a race condition.
You can sync the time the data was sent to treat stale data differently.
There are also many ways you can ensure you're only processing the synced data once.
the whole trying to networking in vrc turned out to be a race condition management game lol
or more like hide-and-seek
starting to understand where to search for them
I get the impression that if you're running into this problem, you might be using networking incorrectly, or expecting it to behave differently from how it actually does.
Start with the basics. If you want to send data to other users on a manual sync object, you do
-Take ownership
-Set variables
-RequestSerialization
And then when you want to create the logic for receiving that data, you simply implement OnDeserialization. In that event, all the variables will be up to date.
There are several pitfalls that you may run into when you diverge from this basic implementation, here's a couple:
If you use FieldChangeCallback to respond to synced data, the changed events will arrive immediately as each individual variable is changed, meaning that if the callback for one variable depends on a different variable, it may or may not be updated yet.
If you send variables through manual sync and then events with network events, those two things take a different route and usually the variables will arrive first, but this is not guaranteed if there is heavy traffic. It is not recommended to mix and match so that the resulting event is dependent on synced variables.
yeah, thanks, trying to get into it for the first time lately
that actually helps a lot
i simplified the code so 1 scripts takes care of everything and in more controlled manner, now it works, at least i didn't manage to break it in 10min of trying to do so
@rich wharf https://www.youtube.com/watch?v=mNYt11OPXhI
In this TLX Spring 2021 session, FairlySadPanda explains how to use the UNU update to make networked games and content that doesn't suck or break.
Check out other talks from the TLX Spring 2021 event at https://www.youtube.com/playlist?list=PLTgqlzYxsEMxiUvVaqBcD5OL9MpdmkiSH
Learn more about Prefabs TLX at https://tlx.dev
Follow TLX on Twitte...
Awesome!! Thank you @cold laurel
oh, that is nice, thank you
Know how to do what
I should probably have asked this in #udon-general XD
Probably :p
I'll switch it over then lol :p
Wow there is game dev conference in VRC 🤣 That's so cool ! Thanks for sharing!
Ok I want to hit a button and and have an object is set active for everyone, even late joiners. will this work?
no
Sigh...
You need to have a synced bool
[UdonSynced] private bool isOn;
you need a method for the toggle to call
in that method you set the local player to be the owner, set the value of your isOn bool to be the same as the toggle value, and then RequestSerialization()
I'd suggest having a different method for actually applying this change with the for loop.
Then just call that event in OnDeserialization()
You'll also have to update the toggle with the new value but without triggering the OnValueChanged
Well that complicates things for me lol I'll have to see if I can logic that out.
Do this in OnDeserialization() eventStart.SetIsOnWithoutNotify(isOn);
Thanks. It still amazes me how many different things they have created libraries for.
Like so....?
well minus the Request inside the for loop
You need to set the local player as the owner before trying to sync the isOn bool.
Also, please move the for loop into it's own method and call it from OnDeserialization() as well.
I could just do the ownership request at the start right?
Or set owner in this case.
can you show the whole thing again
make a new method that only contains this:
And don't call EventToggle(); from OnDeserialization()
You will create a massive feedback loop
and everyone will die
Oh my
You only want to do this specific part
this doesn't do what I think you think it does
You need to call ColliderArray() in OnDeserialization()
I don't think so.
I'm just too new to it I suppose lol.
You'll get the hang of it.
I just need a random int value that is consistent for every player in this world's instance and different in another. I dont need to change it, I dont need to give any player any control over it, it just exists. Like idk, today you join - walls are red, next time they're blue.
Let's break the problem down,
- For the first player that joins the instance, generate a random number.
- Make sure it never changes.
- Make sure everyone knows what that number is.
pic 2 - first two steps, pic 3 - third. But i guess if i wrote it in pseudo code it would make more sense
i have no idea what im doing since udon networking docs is a... thing
- On
Startcheck if the local player is the owner of this object. - If so, check if a random number has already been generated.
- If it hasn't, generate a random number.
you will need a synced int, and a synced bool
Step 4- how do I actually access it from everywhere
(there's probably a way to do this that doesn't require the bool but whatever)
i ignore bool since uninitialized int is 0, and initialized is greater than
With the OnDeserialization event you can change all the things the synced value is needed for.
2nd pic
Add a second branch that only proceeds if the local player is the owner of this gameObject
Is the first player is always owner of all objects by default?
yes
from the true part of this branch you need to apply the things the random number impacts.
Then in OnDeserialization you just apply the the things the random number impacts.
ColliderArray is not firing do I need to add it to the OnValueChange list.
show me your whole script
yeah, it's not being called because you stopped calling it
you need to have it here at the bottom
LOL ok
OnDeserialization() is only called for remote players
Oh got it.
How do I access it later? Part with animator is disabled by default
OnDeserialization get's called when a player receives the synced data. For example when they join.
Ok, how do I access this data in 3rd pic. I.e. send this into animator. Is having the same name for int is enough? Somehow i doubt it
what do you mean
Are you sure you only want to do those things on interact?
I thought you wanted the world to automatically look different
this part of the world is disabled and i already have script that enables it on interact
And I dont get OnDeserialization part as well, ok it deserialized, what do i grab and where do i store it
you don't need to
aa
Sorry
Please watch this @tulip sphinx
maybe next time
Also, isOwner checks if the user is the owner and returns a bool, it doesnt set the owner which is what I assume they're trying to do
That is a fantastic point
I totally overlooked it
lmao
Bit tired
is if the non owner clicks it it just wont update, lol
or it will only do it locally? idk, its weird in that case
You need to SET the owner.
Networking.SetOwner(Networking.LocalPlayer, gameObject);
Oh thanks fo the heads up.
Is there any sort of queue for network events, or is it possible for them to get skipped under some circumstances?
EG: Say i have a list and when a user pressed a button it adds that users username to the list.
If two users press the button at the same time, could they interfere with each other or will they both happen in succession and they both get added?
Adding them to the list just being
Take ownership of object
Add name to list
request sync
Or is there a way to detect that there's a pending change and to wait to apply your local change until after that's been synced
to answer your very specific question, network events do have a queue, so the more you send at once, the longer that queue will get. If a network event sits in that queue longer than 120 seconds, they'll be dropped. You can process hundreds, even thousands of network events in that time so it's fairly reliable for counting the raw number of events
that being said, this process you have described has nothing to do with network events
you are describing synced variables. And the limitation there is that only one person can have ownership of a specific object at a time. So if two people click it at the same time, one will likely stomp on top of the other. Synced variables are only "eventually consistent", meaning that eventually everyone will agree on the state. It does not guarantee that every individual intermediate state is synced on all clients
if you expect multiple people to need to send data through synced variables at once, then you should have multiple objects where each player can send their data through independently
True sorry, wrong words. I just meant any data occurring over the network, not udon-networked events specifically. I should've been more specific,
I dont expect everyone to be trying to press the button at the same time, but I want to make sure to handle any possible edge cases just in case.
if this is something where the users are manually pressing the button, then one way to handle it is to immediately detect and provide feedback that you have been stomped on. For example, if you press the button and add yourself to the list, something lights up. If you get removed from the list, it turns off. So if you click it and it immediately turns on then back off, you can just click it again and you'll be good
Yea, that seems like the simplest solution. 🤔
alternatively, if this is something like a lobby system, pressing a button is not the only way to do it. You could also have a square/circle on the ground where people step into
In could as you say, have a whole bunch of data objects and assign one to each user to store each users data, but i feel like one data object would be a little more efficient than one per user.
well if this is a complicated game world, then it's possible you'd need player objects for other reasons anyway
once you have them, then adding one small thing to them is not a huge deal
That is true.
I was thinking of just a small prefab that allows users to signup for something and display their name on a list with a number next to it from whatever number they input. To make it a little more portable I was thinking of trying to keep it all self contained, but if I decide to intergrate it with other things that would definitly be the way to go.
Ok so I suck at Networking. I can't for the life of me figure out why this isn't working.
I'm literally just trying to toggle 3 objects on Oh...Never mind I just realized....
I think
The objects were not synced.
I can't sync the array. GameObject. Hummm
Anyone have any idea's? I'm sure it's just something simple I'm overlooking.
You are getting the local state of the UI toggle.
Use your synced isOn bool instad.
Oh so just SetActive(isOn)
yea
Thanks again.
General Networking question. Can I have a locally toggled parent object with a Networked toggled child object?
Yes.
Ok thanks
is there a better way to do what im doing here? this feels wrong.
i dont think the networked event should be firing locally but im not sure how to stop it from doing that.
or rather in a way that doesn't send the net event locally and only receives remotely.
If it works like intended, keep it that way.
ok cool.
If you instead had a synced isHeld bool you could do this entirely without network events, which would make it easy to sync for late-joiners. Though I suspect this isn't strictly necessary for your application.
probably not but i'll keep that in mind if it ends up causing problems, thanks.
Ok, I watched this and it was a complete waste of my time except verifying that network events are indeed trash. It did not clarify to me in the slightest how to reuse my variable nor it contained any proper full examples, let alone that I never mentioned using U#.
So ok I butchered some default examples and got this, no idea if it works/syncs for now
`using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class World1 : UdonSharpBehaviour
{
[UdonSynced]
int SyncedInt;
public override void OnDeserialization()
{
Debug.Log(SyncedInt);
}
public void Start()
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
SyncedInt=123;
RequestSerialization();
Debug.Log(SyncedInt);
}
}`
but at least I get log output
but then i try to reuse it and get 0
Does Client Simulator even works with networking properly? If it does then I have problems. If it doesnt, how do I even debug
Should output 1 on start, 3 on second player joined, 6 on third etc since its fired for every player. But it just goes 1 2 3
ah I have no game object
Yeah because all the clients are trying to take ownership of the same object at the same time????
If you just want to count how many players have been in your instance you can infer that from the ID assigned to the player
Im just trying to make sure this runs for every player
shouldnt this be queued then?
That's not what happens.
Ok, anyway. How do I access variables
What do you mean?
I am so confused
Look a bit higher
like here
Expected: "local1" "remote2", "local2" "remote3" etc on each Spawn Remote Player. Actual: "local1", "local1" etc. Deserialization does not fire.
ignore sssss
First "Thats me" fires, no deserialization at it as well but i guesss i dont need one as an owner
Ownership does not transfers if I to believe script's preview in inspector
And, nope. This one transfers ownership allright, OnPreSerialization fires never, var is 0
If you are doing this testing in ClientSim that isn't going to work
For network testing you will need to do it in client
And how do I log in client
From the VRChat builder window you can launch multiple clients at once
*And how do I Debug.Log("asdf") in client
https://docs.vrchat.com/docs/world-debug-views Right Shift > tilde > 3
These are the tools you can use to debug your worlds in-game.In order to access debug views you need two things: Launch VRChat with the launch parameter --enable-debug-guiPress Rshift + Tilde + 1-9. If you have a keyboard layout where tilde is not directly to the left of the 1 key, try using whichev...
To open the output log in client
Ok, can you also tell me how do I get access to the same variable, synced or not, in different scripts, other than player tags
You would need to use one Udon behavior to store the variable, and then in any other Udon behavior you can reference the script that has that variable and use: UdonBehaviour.GetProgramVariable("VariableName")
There is also SetProgramVariable that you can use to modify variables in one UB component from another UB component
Is there a benefit to using GetProgramVariable over just directly doing YourBehaviour.YourVariable?
I'm not sure, I assume YourBehaviour.YourVariable compiles to use GetProgramVariable in uasm
I have never checked though
It actually does compile differently, meaning that YourBehaviour.YourVariable is likely better as it doesn't have an Extern My initial test was bad as I assumed doing this.MyVariable would be the same as MyBehaviour.MyVariable but it does compile to use GetProgramVariable.
Don't use UdonBehavior[] it is not supported
Weren't you using U# just earlier?
thats the only thing Instance point offers
Is it illegal?
I want to recieve variable in nodes
You can store the reference as a GameObject as you are here and then use GetComponent typeof UdonBehaviour
Probably the easiest way in Graph
Should use (type) input instead
?
Whats the difference?
So you don't make typos
Thats irrelevant
You had typos: it's UdonBehavio__u__r.
Yes I said so and i fixed it
Where does it say it's null?
in log output
Post its detail too
Ah whatever, I give up till next time. I originally asked what I consider to be trivial thing and've been sent to watch 1hr video, then had to read god knows how much on u/u# and I still have no idea. I just spawn invisible synced prop and modify/read its coords. Works like a charm
I am stuck here. I know I am doing something fundamentally wrong but I cant find a good solution. I have a control panel where I have buttons with IDs and I am sending the IDs to this udon script. In this script I want to check if the user is instance owner and if not instance owner I want to check if he is on the whitelist to change the variable. I am setting the variable and trigger the onchange event for everyone but it seems it doesnt work, probably because only the owner can change the synced variable? But how would I send the ID from a user to the owner then? I think my system here is overcomplicated but I have no idea how to do it better. Actually I just want to send an integer to a function and sync it between everyone.
SendCustomNetwork - Owner
Changing a variable without changing the owner.
I dont get it. When i send a custom network event, how do i get the variable from one user? There is no parameter in send custom network event. On what position do i send it?
What
Don't use custom network events, use synced variables.
SetOwner to be localPlayer, Update the value of the variable, RequestSerialization
Then OnDeserialization runs for everyone else.
How do i set owner to local player?
The main issue that I see here is that you are branching conditions and then recombining them. Udon Graph usually doesn't compile properly when you do this.
Yeah when something is 100% broken it usually gives an error or warning 😅
didnt get any warning here
So I would do this instead. But will it actually sync the ID for everyone?
Adding Debug log nodes to different areas of your script will help you find what part isn't working properly
Also are you testing in client or in editor?
how do i get the debug log in vrc? Could never find it and I cant run two clients from test modes because I get an error because of anticheat...
If you hold: Right Shift, ~, 3 it will bring up the output log in client
As for the AntiCheat warning if you go to the settings panel in the VRCSDK you can go and find your game install and target it to launch VRChat.exe and that should allow you to launch multiple clients
What, what? See examples, learn udon.
It is not necessary to constantly change the owner, you can change the variable on his behalf.
Lmao "learn udon" 😆
How exactly do you suggest to "change the variable on his behalf"
This is not what I propose, it is indicated in the documentation, as well as in a hundred video lessons on YouTube.
Send by sendcast to owner.
Grnerally you make the player that needs to change a synced variable the owner of that object with Networking.SetOwner
Keep in mind that this is not the best solution if your world requires multiple players to click the buttons & change those variables at exactly the same time
However if it's not a button that'll be spammed by lots of players at once it's fine
If you have specific methods being called by each button you could use SendCustomNetworkEvent and set the target of the event to Owner.
This doesn't solve everything of course because it's not guaranteed that the owner of this object is the instance owner or Master.
If you aren't setting the ownership manually then the owner of the object should be the current Master
Can you provide an example, instead of being condescending?
This is not what I propose
It's exactly what you proposed. You said "you can change the variable on his behalf."
Please explain how you suggest doing this.
Lol
Learn udon.
I know how to use Udon :)))))
Obviously you don't
Since you can't provide a basic example.
It shows in your idiotic questions and answers.
you go to the block.
What a clown
This scene is ready to Build & Test or Publish, and it demonstrates many common interactive items.PrefabsThese objects show off some of the Prefabs included with the SDK which demonstrate default interactions with the VRChat components for Avatar Pedestals, Stations and Mirrors. AvatarPedestalTh...
I literally told the person to use this exact node in this message
You are blind
Also, sending a network event doesn't show how to "change the variable on his behalf" 😆
Your claim of changing a networked variable on an object you are not the owner of is still unfounded
There are plenty of ways to do it without changing ownership, but this is not the way lol.
I write that you are an idiot.
Learn udon.
Sit in the block, there is no time for you.
What a respectful, helpful and charming little fellow.
If I just add this and select synchronization method, should it just work? Its probably not the most optimal way for me to update it every frame but would be nice to know for testing
What are you actually trying to do? It's hard to help without further context.
Basically trying to synchronise UI output
UI for?
BTW is that notepad++?
VSCode, yes light theme 💀
Why
Uhh not sure if I want to go into details at this point, basically a canvas that has a UI.Text component
I can add text to it using an input field and a button, after which I want that text to be synchronised between clients
I don't know, just got tired looking at the dark theme for the past few years
I prob will switch back to dark theme at some point though
Is this like, a chat? A messaging thing?
Are you overwriting the whole text on the UI?
I guess you could call it that
You should be using
if (!string.IsNullOrWhitespace(previousMessagesArray[i])) continue;
I might've messed up some capitalization I don't have my IDE open rn
The way you currently have it set up makes it so if two people send a message at a similar time one of them will be overridden by the other
Race condition my beloved
Well I thought of that and I have another bool for that
what
Though I'm not sure if it will work right because its supposed to be synchronised
What you should be using is a player object pool
Then each player can have their own networked object
You can send data through these
Essentially you'd create an event buffer
And let the owner of the UI.text handle appending the messages
This way you have no race condition
Like I have a bool that is set to true whenever someone sends a message, it is then "processed", and then outputted, after that the bool is set to false again.
When the bool is set to true it makes it return in the "processing" function.
Though tbh right now I am less worried about that and just want to get synchronisation working at all for a test
I have other things to solve before I would be worried about race condition
Alright so with the way I have it right now it does not synchronise the textbox it seems, weirdly enough though it synchronises the input field even though I did nothing with that, must be default behaviour
Use manual sync and public override void OnDeserialization()
Also IsNullOrWhitespace did not work for me for some reason just marked all text as such or whatever but probably my faul, not relevant for now
Any examples on how can i manualy sync?
Use this class attribute:
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
will that synchronise only the variables with [UdonSynced] ?
as i dont want every variable to be synchronised
And I assume i select manual here too
What would the purpose be of having the [UdonSynced] attribute if all fields were synced regardless
Fair
Yeah but you really should be using the class attribute instead to avoid user error.
So should i select none and only have it as [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
yeah but i still have to select something in the U# component?
What if, you put in the thing, and observed what happens in the inspector
Mb, forgot to Ctrl+S
[SerializeField] private Text myUiText;
[SerializeField] private InputField YourInputField;
[UdonSynced] private string UiText_SYNCED;
private VRCPlayerApi _localPlayer;
private void Start()
{
_localPlayer = Networking.LocalPlayer;
}
public void _onValueChanged()
{
Networking.SetOwner(_localPlayer, gameObject);
UiText_SYNCED = YourInputField.text;
RequestSerialization();
ApplyTextToUI();
}
public override void OnDeserialization()
{
ApplyTextToUI();
}
private void ApplyTextToUI()
{
// Do the thing
myUiText.text = UiText_SYNCED;
}
probably a lot of wrong capitalization etc.
since I wrote it in discord
and not an IDE
but it should get the point accross
Coming back to my question from yesterday. I got confused by all the discussion here so I dont really know what to do here. So this whole script works fine for owner but it still wont work for the admin user in the upper branch. I still guess its because only the owner can change the variable. So the only way for me to do it to give temporary owner to the player? How exactly would I do it if thats the correct way to get this variable synced?
just do networking setowner to the localplayer before changing any synced variables
like this?
yes
This seems to work fine but I still have syncing issues on quest. Is there any reason why this wouldnt work on quest. Especially when a quest user is admin. Then it doesnt do anything even for me as admin getting the owner. Its like quest cant change the integer.
Why are the OnPlayerJoined and OnPlayerLeft events not working? Nothing is happening
They should be working. Can you provide examples of how you're trying to use them?
I have this setup in my script: public override void OnPlayerJoined(VRCPlayerApi player), nothing was happening so I'm trying to debug it with a log and even the log isn't showing up
more details? Again that should work
I have also updated my SDK
is this object disabled maybe?
no it's active
and where/how are you testing? Editor? Clientsim? local test? published?
local test and published
the only case where this shouldn't work is editor without clientsim
can you just take a picture of the whole event?
users is not null and contains more than 1 string
can you share a picture of the udonbehaviour component where this script is placed?
I'm not sure what to tell you. I mean I could keep asking for pictures of various things for a while but there's gotta be something somewhere that is not set up correctly. Do you have anything weird or uncommon about how this is set up?
This looks like a prefab, does that prefab actually exist in the scene?
nope, I have a StringDownloader on this object if that's an issue?
nope
oh, are you sure this script isn't crashing from something else before it even has a chance to get onplayerjoined?
or rather, are you sure this script is even running in the first place?
yeah, everything I have set up in Start() is working correctly
Hello, I'm using OnDeserialization to keep players updated with the current synced variables on my scripts but I have never used OnPreSerialization before so I'm confused on how to use it properly and what it would look like setting it up.
I see it is defined as "This event triggers just before serialized data will be sent out, it's a good place to set synced variables that you want to be updated for other players."
I kind of get it but what would be a good example of when or why to use this event?
I'm confused on how to use it properly. for most of my scripts they are set to Manual and I call RequestSerialization from the gameObject owner when I need synced variables to be sent to everyone else
if all you're doing is setting a synced variable and then doing requestserialization, then that's all you need to do. OnPreserialization doesn't need to change that workflow, and you can keep it simple.
What OnPreserialization is good for is when you want to apply some sort of final step right before the data is sent off.
A good example of this would be if you want to sync a datalist/datadictionary. These can't sync on their own, but you can sync them through json. So OnPreserialization, you could convert it to a json string and then ondeserialization, you convert it back to datalist/datadictionary.
Another example may be a case where the precise timing matters a lot. Say you want to adjust a specific timestamp right at the moment in time it gets sent, OnPreserialization is the time to do that.
Another example may be a case where you are creating a sort of event buffer. Throughout your program, you may send a dozen events within a second, before it gets to serialize. In OnPreserialization, you could bundle up all those events into a format that can sync.
Oh I see, thanks that helps me understand it better 👍
Hi, in not sure i quite understand how the data rate limits of networking apply. If theres a doc that explains it id love a link to it, otherwise hoping someone can help me understand. From what ive been told the rate limit is about 10kb/s, of which about half (conservatively) is used for players/avatars.
Lets say that in my world i have two spheres. Players can only ever be in one of them. If they are in sphere A, they only need to sync the objects in sphere A. Likewise with sphere B. If i have 5 kb of objects i need to sync in each sphere, and assuming i am already using 5kbps of the limit for avatars and players, what happens when two players enter sphere a and b, one each, at the same time?
Does the world interpret this as trying to pull 10 kb overall, or can it do this just fine since each player is only syncing the 5 kb from avatars and then the 5 kb for their spheres?
Or am i just completely misunderstanding how syncing works
Try not to sync everything; consider what you can determine from the minimal amount of information shared. For example: if an object will move on a fixed or predictable path, then its position may not need to be synchronized and instead its initial location and velocity may be sufficient.
Tyty 🙏
all of the limits of vrchat networking are referring to the outbound per user
there is pretty much no limit to how much you can receive
so two users sending 5kbps each only counts as 5kbps
Awesome, thanks! I think that is best case scenario for me!
Much appreciated, once again!
🙏
Is it possible that setting variables is not possible even for owners in public instances? Do I have to set owner manually every time?
the fact that it's public has nothing to do with it. The owner is the one who can set synced variables
I just dont know why i people cant change this variable then in public instances. It seems to be good in private ones. I can do it as admin because I am setting the owner to me when doing something. But all other players cant change it, even when I am not there.
you're gonna have to provide more details of what you're doing and what you're expecting to happen. Sounds like you have some custom system that is preventing you from doing things
I basically just want to change the int variable for everyone. but its not reaching other people in public instances.
I'd like to do manual sync, but also sync position of grabbable object, why won't work?
Do I just need to use ObjectSync ?
You can't put manual on the same object as objectsync
Thanks for the reply! That much is clear, I scoured the channel before posting. My thing is trying to manually update and replicate the coordinates for when I would want to manually sync a movey object!
I'm not quite sure what you're asking, then, do you have a question? Is there something about your code that is not working as expected?
Yes and yes, the position/rotation of the grabbable gameObject does not get replicated to other clients after manually setting it like above!
Shouldn't the position update on all the clients?
Is RequestSerialization and everything being used correctly?
Are the variables marked as synced?
yes!
And what event is the first picture in?
Update()!
Is this instantiated at all?
not instantiated, a placed object!
Oh, I don't see anywhere where it sets POS and ROT
Oh nvm that's the last image
I don't see anything wrong with this code, could you show me more?
Well what exactly, this is most of it
It's just a grabbable object and the position is trying to be set like that
What happens in update before/after the first image
Can you show me the synced variables and also the inspector for his object?
found a workaround but it would be a handy thing to move a manual sync object around
???
(compile errors are bcs I completely changed the script and mashed undo to get the screenshots)
It should work. But I will say if the whole reason you're doing this is because you want manual sync on the same object as position sync, you're doing it wrong
It's a lot of work to make a good looking manual sync script, with interpolation and everything
As in I've found how to implement the thing just fine without manual sync but having position sync+manual sync would be king
yeee.
I mean it would work but with all this undoing and compile errors I don't know what to think
The only problem is that it wouldn't interpolate, it'd be choppy. And it takes a lot of work to smooth that out. So you'd be better off just using objectsync and putting manual sync on a different object
Interpolation/prediction was the plan but it doesn't update at all
I can get the code and everything back in it's entirety and send it but it's just some other logic that doesn't touch the movement sync!
was just curious why setting coords and manually synching resulted in the object still
not syncing pos
Like if the grabbable component messes it up or there's a function I'm not aware of or smthn
I don't see any problems with what you've posted except for how it was on continuous and you had compile errors. I can only assume there's something you're not showing me or telling me that would cause the problem, or you're not testing it correctly
Alright, thank you!
If there was nothing wrong with the snippet then uh must be something else
Or, again, it's the continuous or compile errors
compile errors werent there when I was running the code in full, and the object was set to Manual hold up I'll get a fixed screenshot.
Are you certain that you have tested it while it was set to manual sync
If it was continuous, the int array would likely cause the whole thing to not work
oh yes!
I'm certain!
I only set it to continuous just now while doing a continuous+ObjectSync solution.
Found ObjectPool which can seemingly hold and sync a whole bunch of objects
That doesn't really fix this specific problem
Doesn't no
Object pool only syncs the active state, not position
If you want to diagnose your manual sync script, try adding onpostserialization and debug log the serializationresult
I was making a dice cup, the object pool holds the dice which are synced just fine with their own components
before I was doing int array stuff and trying to instantiate them
I'll try that when I try to do this again, but it was very helpful to know that the code was seemingly correct
I've been informed that CinemachineVirtualCamera "is not supported by Udon sync". Unfortunately, how I've designed the camera system in my world uses them extensively, and I did want them to be network synced.
I had a version of this post with a code snippet but the bot unilaterally claimed it was spam and deleted it.
I'm not personally familiar with cinemachine, but I assume that the reason why it's not compatible would be either referring to objectsync being overridden by it, or certain functions not being exposed to udon.
Either way, it should be possible to do what you want and if what you want is to simply set a certain priority, and those functions are exposed to udon, then there should be nothing stopping you from plugging values from udon sync into the cinemachine priority
Ohhhhhhh that's why my particle system are not positionnate properly!
If a networked object is out side of the render distance will it stop functioning?
Being far away from objectsync or a player will reduce the rate at which you receive synced data about that object or player's position. But this does not affect the rate you send, and does not affect continuous or manual sync
and it has nothing to do with render distance
Just checking
Let's say there was a spam of SendCustomNetworkEvent, would these arrive in order?
I'm actually not sure if the order is guaranteed. But I do know they're guaranteed to arrive as long as they aren't in the queue longer than 120 seconds. The speed of the network event queue is dependent on network conditions and ping to the region server, and 120 seconds means roughly 5k-10k events
How can I spawn a new prefab on runtime using udonsharp on a global instance (meaning on all instances)? So I can sync data to the new object.
Object instantiated on runtime can't sync data. You have to use object pool.
Which means they have to be already existing in the scene correct?
yes.
okay thanks
Hmmm it seems that even the object from my pool were not syncing variables.
Or i did something wrong...
Anyway, i did a different setup where my manager sync the initial data of my pooled objects and it works
I dont know why on my Brick gameObject
I had udon sync variables with manual network synchronisation
And calling RequestSerialization was not calling OnDeserialization
OnDeserialization does not run for the owner of the object calling RequestSerialization
Are you sure the player calling RequestSerialization is the owner of the object?
Yeah that what I said
I was calling Request on the owner
And OnDeserialization was not called on others
Interesting to know, i wont have to check if I already did a client logic (on the owner)
I was, i put a different skin for my brick on the owner
Hi, I am trying to have an object follow the object owner, and have this be seen for everyone. I don't want to use VRCObjectSync, since it is too slow to update for the game I'm working on. I basically am trying to get each player's position (via a GameObject for each player), and it Updates the position for everyone.
Here's what I have:
VRCPlayerApi ownerPlayer;
Vector3 playerPosition;
public void AssignThisPlayerPosition()
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
ownerPlayer = Networking.GetOwner(gameObject);
}
private void Update()
{
playerPosition = ownerPlayer.GetPosition()
}
It seems to work in ClientSim, but when in the VRC Client it says the API is Null.
Any assistance would be appreciated.
If there's a prefab I can get something like this from, that works too.
you should use utilities.IsValid to check if ownerPlayer is valid, and don't attempt to get their position if they are not.
@frozen igloo OK, this prevents errors with an if statement (I logged it as a warning instead, so the udon script isn't stopped). But why would the PlayerAPI return it as invalid?
because update would run before the ownerplayer gets set
@frozen igloo I have an if statement (in the update loop) that checks if the object has been assigned, which is not shown in this code. If you want I can send the full code.
well you do now
@frozen igloo Hmm, I don't know how to go about this then. I got it to work with Networking.LocalPlayer, but it doesn't work with Owner. Do you have any advice?
oh that's a different issue then. Is this object instantiated?
@frozen igloo No, it's a predefined object that is always active in the scene.
(Not sure if you want me sending mentions or not lol.)
is it none sync?
Manual sync
are you trying to getowner very early, like onenable or start?
Yes, on Start, but also when the player interacts with a button to become a player of the game
Start would be too early to know what the owner is, and interact only happens for the person who clicked it. If this is supposed to just always follow the owner whoever that is, you should probably use the onownershiptransferred event
I tried using OnOwnershipTransferred as an override method, visual studio was saying it was obsolete, and I cannot find another syntax of how to use it anywhere.
The version with no arguments is obsolete, there's another that I think adds the new owner
Check how graph does it
I'm still getting that it's not valid even after calling it with OnOwnershipTransferred.
public override void OnOwnershipTransferred(VRCPlayerApi player)
{
ownerPlayer = Networking.GetOwner(gameObject);
}
Do I even need to use the argument here?
You could also just get owner in update
Well... I have no idea. When I do build and test the log still says 'Could not Execute! Connected - api is NULL!' even when it's trying to get owner every frame.
What what that has nothing to do with vrcplayerapi
That's like invite notifications, which don't matter in a local test
Is that the whole reason you thought this didn't work? Are you actually testing the thing itself?
Yes. Although I think I was too focused on the logs, I don't usually see that error so I thought it was related. When I observe it looks like this worked. The object seems to follow each player on both clients now.
Yeah, it's working flawlessly now. This really did help, thank you very much @frozen igloo 🙂
Incidentally, it would be awesome to have a toggle to only show my own logs, not all VRC client logs.
You can change the mode to only listen for prefixed logs.
heyoo i have a question, what will happen if lets say we have a owner of an object and all of the stuff is synced to every user, but then the owner of the object crashes and a new person joins
would they get blank data or would it automatically assign some1 else as a owner and retain the data
data will be kept
so ownership gets transfered to the oldest person which could be the master right ?
yes, the master gets ownership of objects when a player leaves. And all synced variables will stay as they left it
YESS
doing a double manager syncing system since i need one script to stay owned by the master and another for updating a list of players by users
Need help with UDON! When a person enters the zone, VoiceFar becomes much smaller than the default. At the same time, it must be local. And it applies to all players. Any ideas how to do this?
it's not very clear what you're asking, as it sounds like you're partly describing something that already exists, and I'm not sure if you mean that's what you want to create, or something you've already created that's not working as you want
I think he's looking for ways to make the voice distance smaller when inside an area but just for the players inside said area ?
Unsure, words 
Is there a way to only sync a variable to certain players?
Alternatively, will new players get the latest state of a manually synced var, while older players will only get updates when serialize is called?
you can't sync a variable to a specific player, but you could add synced variables that indicate it is intended to only be received by a specific person, and then you can write code that ignores the message if you're not that person
and I'm not entirely sure wha the second part of your question is, but anybody joining late will receive the latest serialization from each object, which is the same thing that other players may have received minutes ago
Damn, that's what i wanted to setup - newer players get a full sync of the vars current state, while older players get one inital sync and then recieve events for small modifications of the var
Alr, thx
I think i got an idea-
I'll have one big synced var that holds all the data, and then a smaller synced var that stores recorded modifications of that data
so you sync the big var once, and then sync the small var for each change
(maybe the small one only syncs when a new player joins, since modifications are driven by rpcs to everyone)
then when the small var gets big, you internalize those changes to the big var & sync that
and then loop
That way you can sync a bunch of changes to a massive var over time, without constantly resyncing the massive var
yeah, having "big data" and a separate "fast data" is a valid technique. Just be aware that this is not separated per-variable, but rather it's separated per-object. You'd need two different scripts on two different objects to do that
and there is no reason you need everything to be in one variable. You can have many variables on one object and they'll all sync together
Ah, but i'm trying to create a minecraft-esque 16x256x16 grid of "blocks", and i dont want to have a massive pool of block objects that could run out
i'm already doing optimizations for storing rectangular groups of the same type of block
ah, a minecraft system makes a lot more sense
indeed, separating between big data and fast data is a good idea. I'd recommend having just the master control the big data and then every player has their own fast data
Oh definitely, fast data should only be synced when a new player needs it
no, that's not what I'm saying fast data is
I'm saying fast data should be used for every time a player makes a change. They dig a block, they place a block, etc. And don't forget to queue up multiple block changes in case they place/dig faster than it can sync
and then the master receives that and applies changes to the big data, and resyncs it occasionally to make sure everyone is on the same page
Yes
Basically, I have a glass box. So I want this: when a player is inside the box, he barely can hear anyone including people near him and far from him
- Do you want other people to be able to hear the person in the box
- Do you want the person in the box to be able to hear other people who are also in the box
that wasn't a multiple choice, it was two separate questions
I mean, I want only option 3
I understand you don't want the people in the box to hear the outside, I'm asking about the other edge cases that you're not describing
Alright, 1 sec, I'll show
you don't need a diagram, it's a simple question
Basicaly, it is a box. When player enters it, he can't hear other players outside and inside the box
When he leaves it, he can hear anyone
okay so the person in the box just can't hear anything
and people outside the box can't hear the person inside the box
this is kinda complex then. What's your familiarity with udon?
Uuuh, I actually made it

But the problem I have - it is not reverting back when player leaves the area
that was what I was trying to ask in the first place omg
:omega
okay so just onplayertriggerexit just undo everything
Yep
set back to defaults
It has everything the same but reverted
For example, "when players enters trigger, volumeFar is 1.3" <- this works
But "when players leaves the trigger area, volumeFar is 5" <- doesn't work
Both have the same code, just different numbers and event
the default VoiceDistanceFar is 25
if you want to return to default you should set that
that's really low
can you show the code/nodes?
Yep, opening the project
@frozen igloo
And for when player exit trigger area
The first part works very good, but the second just not
Currently, I use "hack" with 2 scripts with "area trigger enter"
1 for inside of the box which is decreasing voice range
and the second script - on the door to the box so when they leave the box, it runs "triggerEnter" event with "reverting" back to 5
It works but I am 100% sure it is not the best solution since it requires more areas (4 in my case) in scene instead of 1
So it looks like this. Area on right side is for people that came from spawn just in case they click "respawn" while in "1,3m" cube. All "VoiceInBox" and "VoiceOutBox" scripts are in continuous sync
Will Serialization happen if there's only one player in a room?
yes
the serialization will be saved on the relay server so that when a late joiner comes in, they can receive that directly rather than the people in the instance having to re-send it
Alright, sick - was that changed recently? I havent developed stuff in vrchat in a while, i remember having to setup flags and resync when the first non-host player joined.
it did change about 8 months ago, but not in a way that matters. Previously, the relay server was incapable of storing anything so when a new player joins, the other players would have to resend everything. But that was handled automatically, so if you ever did requestserialization at any point while solo, it would automatically serialize when someone joined. I would bet that the flags and resync you did manually was either unnecessary or only necessary because you were doing unconventional things, like late join sync by network event
Ohhh so an instance can keep running a long time before resetting all the data? Or is there always 1 public instance that keep running indefinitely?
A world instance would be destroyed right after when there's no player left in an instance. There's no permanent instance either.
Ok thanks
Hi, can anyone help me with making my slider sync when you enter a specific area?
Is there a way to create an area and boost microphone volume to be heard throughout the whole world? And rather make the microphone audio be 2D rather than 3D?
@spring sapphire https://creators.vrchat.com/worlds/udon/players/player-audio/
Players have two sources of audio
Looking for someone who is proficient in udon graphing to help me with a potentially major project
I've omitted something important. I have a ship in my world and I have made it so it sail using a path & dolly. The first issue is that when multiple players jump onto the ship they end up in various places in space but everyone sees themselves as on the boat. So I see 2 people standing in the air 10 and 20 feet away and each of them sees the same thing. This is before the ship starts to move so I'm wondering if it has something to do with the Cinemachine dolly and the path attached to it. Any idea?
Did you sync via Object Sync or via variable ship coordinates?
If not, then everyone has it locally.
Thanks for the reply. I'm only syncing a button that starts it sailing along the path. I've just added a VRC Object Sync to the ship but I have yet to test it. I hope that's it.
The reason this happens is because even if everybody sees the ship at the exact same place at the exact same time, there is an additional latency between the players as they send their position to each other. As a result, it is impossible to use normal, global position sync and have multiple players all in sync on a moving platform. The solution to this is that the players should be in stations, which will ignore their synced position and instead all players will see each other forced into the stations.
Bummer... I had it working with stations but that required enough seats, people to sit in them and not get out and of course they couldn't walk around the deck. Now they can walk around the deck but then there is this issue. Seems a bit limiting unless... can I make big stations that are the size of the deck somehow?
I guess that wouldn't work as they are essentially sitting regardless.
ultimately, if you want the players to move on the deck, you'd need a fully custom player controller. This is a really complicated topic and it has a lot of caveats, but you may have some success with this prefab: https://booth.pm/ja/items/4690338
So am I correct in saying each player would need to have their own ship much like the car examples have?
no, that's not the issue
I have a prefab that is handling the movement on the deck. Someone was nice enough to give it to me.
Each player was on their ship in this case and could walk around.
I mean that would be one way around it, but that has it's own complications like needing to build a custom sync script that locks onto that player's simulationtime
So if I have one ship. One person could get on it and sail? Would everyone agree where the ship was?
yes, everyone would agree where the ship was but the problem is latency
another solution would be to move the world around the ship instead of the ship within the world. But that would put a strict limit on how much you can do with the world, because the world couldn't be static
That's not possible in this case and would preclude having multiple things to travel on.
Bummer.
How would the latency manifest itself? What would everyone see?
player A would sync the ship and themselves to everyone else. Player B would then sync themselves at the location that they see. Then player C would see the ship where player A says, but then they'd see player B further behind because of the added latency of traveling from B to C
umm... you mean if multiple players were on the ship right? I'm considering one person at a time at this point. I just need the other players to see the ship in roughly the same location in the world along with the player that is riding along.
yeah, if everybody has their own ship then you're just facing an implementation problem, not a physics problem. In that case, you'd need to build a custom sync that matches the player's simulationtime
Thanks for trying to explain it. I'll try a few other things. I was however, thinking of a single ship and just telling people to ride it one at a time. Pity there isn't some "universal" solution in VRChat for multiple players and moveable platforms. I have to think many people would like such an effect.
oh, I guess that's also an option. The same solution would apply
I have a question about how to deal with disabled objects and receiving data.
From what I've noticed, OnDeserialization is not being called on disabled objects in general. Thing is, those objects are enabled shortly after, but it seems like their opportunity to call OnDeserialization is already gone.
I am encountering this with Cyan's object pool and was wondering if there is a way to quickly receive the data again? So let the network manager call OnDeserialization for me again.
My solution has been something like this so far:
After joining, send a networked event to everyone else and tell them to call RequestSerialization. This way, we still receive a OnDeserialization with the updated data.
But that doesn't seem that optimal. Is this more of a feature request or even bug?
Only the owner of the object should RequestSerialization()
Then OnDeserialization() should run for everyone else right after they receive the data.
From my testing, OnDeserialization() does in fact not run while the object is disabled.
Allthough, it runs every OnDeserialization() event that was "missed" while the object was disabled when it gets enabled.
I am aware, that's what I'm doing.
If the object is disabled for the Owner while calling RequestSerialization(), then OnDeserialization() will not be called for everyone else before the object is enabled again for the owner.
I think I might've solved the issue with something very simple: Just toggle off "Disable Unassigned Objects" on the pool...
I'll test it out later.
Alright 👍
You just worded this very weirdly:
send a networked event to everyone else and tell them to call RequestSerialization.
Yeah, it's a overcomplicated solution. I sent the event for everyone else to RequestSerialize their own object which was previously disabled on my side.
That isn't shouldn't be necessary to do.
It was for my case. Although I just can use the checkbox for the pool and it should fix all my issues. Just saw that and feel kinda dumb for never using it.
So I've set up my networking so when the local player hits a note it sends a CustomNetworkEvent so the flame on the networked side will trigger. Is this a bad idea due to the number of networked events? It's purely a visual thing, I could just make the fire happen for every note locally and not sync it but I think it would be cool
^ for the strikeline emission and drum emission/size I'm using continuously synced variables instead. I'm not sure what is better: continuously syncing like I'm doing or even just send network event every time a drum is struck? I went with continuous for the drums because I assumed sending lots of CustomNetworkEvent is bad compared to continuous syncing?
The more I think it might actually be better using CustomNetworkEvents for drum hits instead of syncing as it's only one event instead of lots overtime
Yeah sorry I think I've answered my own question, did some testing with VRC Quick Launcher and using CustomNetworkEvents is better than continuously syncing and it just looks nicer because it's not interpolating size/emissions
What are you using continous sync for?
i was being an idiot, i was using continous sync on:
float emission;
Vector3 drumSize;
Whne you hit the drum, FixedUpdate lerps the drum back to normal so originally I continous synced these two values
Why don't you just animate it and trigger that when hitting the drum?
Yeah that's what I'm doing now, so when you hit the drum locally it sends off a custom network event
I'm just kinda worried about the impact if I scale this up to like 8 players all with synced highways
does anyone know what to change to make this a public or world toggle, and not local?
hook the interact to a sendcustomevent note
and then get a custon note, name it whatev and hook it to the SetActive
*SendCustomNetworkedEvent
If I remember correctly
right
I've got some size changing systems synced between all players: when a player interacts with a cube, all the players in the world start getting bigger, and it's reset when it's interacted with again. The problem is that the networking part works when doing build and test, but doesn't seem to work with other actual players if I publish the world to vrc. What could be the issue?
can you show what you're attempting to do?
you mean the udonsharp code?
yes
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class syncedscalingall : UdonSharpBehaviour
{
private VRCPlayerApi player;
public GameObject thisObject;
private float baseHeight; //currently unused
private float currentHeight;
public float multiplier;
[UdonSynced] private bool active = false;
void Start()
{
player = Networking.LocalPlayer;
}
private void Update()
{
if (!active) return;
currentHeight = player.GetAvatarEyeHeightAsMeters();
float updateMultiplier = 1 - ((1 - multiplier) * Time.deltaTime);
player.SetAvatarEyeHeightByMeters(currentHeight * updateMultiplier);
}
public void Interact()
{
Networking.SetOwner(player, thisObject);
active = !active;
RequestSerialization();
if (active)
{
baseHeight = player.GetAvatarEyeHeightAsMeters();
currentHeight = baseHeight;
}
else
{
player.SetAvatarEyeHeightByMultiplier(1);
}
//SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "SwitchScaling");
}
public void SwitchScaling()
{
if (active)
{
baseHeight = player.GetAvatarEyeHeightAsMeters();
currentHeight = baseHeight;
}
else
{
player.SetAvatarEyeHeightByMultiplier(1);
}
}
public override void OnDeserialization()
{
if (active)
{
baseHeight = player.GetAvatarEyeHeightAsMeters();
currentHeight = baseHeight;
}
else
{
player.SetAvatarEyeHeightByMultiplier(1);
}
}
}
I also get a problem where if I use this system to shrink, the shrinking stops way before the limit, probably because it rounds the multiplier float to 0 very quickly. what would be a way to obtain a smooth scaling effect bypassing this problem?
that looks like it would work. And there aren't many differences between local test and build these days. Are you sure all clients got the latest version of the world? If you updated but they didn't rejoin it might explain it
yes we're sure
there's a lot of weird behaviours, like the script working if they interact with another object that also changes their scale
I can't explain why it's happening
add some debug logs or print to a canvas text to figure out what's happening
how do i work with TMP text to display numbers and stuff there?
yes, make a variable called textmeshprougui
the class is TMP_Text?
no, it's TextMeshProUGUI
I don't think TMP_Text works or something
I must be missing something because I get a 'method is not exposed to udon' error
are there some examples with TMP and udon?
what method are you trying to use on what class?
on textmeshproUGUI with .SetText
use .text =
in udonsharp, can I reference in script A a variable from another script B on another object without having a variable in script A that includes script B?
so, if I wanted a script with some 'global' variables that need to be used across all my scripts, I'd need to reference this script in all my other scripts?
You want to create a game object that contains your "global" script (it will create the instance) and then reference that game object in any script that needs access.
Through a custom event, you can refer from anywhere. UI panel, triggers, other objects with udon.
Add the Udon Behavior variable, and specify it as Instans in the sendcast event.
hiii! so im trying to make this global instead of local
it is an event interaction that plays an animation when a button is pressed, what components should i add? ty!
Add a synced bool
Set the udonbehaviour component to manual sync
On Interact:
Add Networking.SetOwner to the local player
Set the synced bool to the opposite of itself, replacing the animator setbool. Also mark "send change"
RequestSerialization
Then hold alt and drag the bool into the graph to make an onvariablechanged node. When the bool changes, you use that to set the animator bool to match the synced bool
hi, so im new to udon and use this solution I saw on a video for syncing an object's state.
What im trying to do is have an object go invisible for everyone when it's held and vice versa, and when used a particle system container empty toggles (child of the main held object)
It works mostly, the states are fixed now. The problem is when I drop it the object seems to appear visible at the world origin, and same for when enabling the particles. The object is placed at the world origin so presumably it's syncing everything correctly except the location of the object in your hand
and synchronization is set to manual under udon behaviour
tysm!!!
Only thing I could think of is if the visibility object is the same as the object the vrcPickup and ObjectSync components are on.
the visibility object is an empty under the main parent object, which contains all the meshes for the visible part of the object
Does it have maybe to do with the fact I dont have an object sync component? VRC SDK told me I had to remove it because synchronization was on manual so I did
Ahhh
Yeah, you have nothing syncing the position of your object right now
Here's what you could do.
Make a separate udon behavior that is on the pickup. And the only thing this behavior does is listen for the OnPickup and OnDrop events.
Then you just forward those events to your actual script (which you have moved to a child gameobject)