#udon-networking
1 messages · Page 35 of 1
although, also limiting to that kinda restriction, i could proby also shrink input to 1 byte a frame
In the Drawing world (https://vrch.at/wrld_86f03319-38c5-4d8b-8935-b2a5ab58b22e) you can save your creation to the web. Would really appreciate any clues on how this might be accomplished.
I can't find any way to of moving variables/data from world instance to a file or REST call or anything
most of this often done using videoplayers
you can't really extract data from VRChat by uploading it to the internet. The only way to get data out of VRChat is by using Debug.Log() and then look at your log file in %userprofle%\AppData\LocalLow\VRChat\VRChat, or by making the user copy something from a text field and saving it manually. I've also once seen a world that does save data by changing your avatar to load data from the saved parameters. It's also technically possible to do something with video players to get like a ~12 byte/minute upload to a server but that's against the TOS and will get your account banned.
All are really hacky workarounds, and the devs said in a dev stream early 2021 that they will add save data to udon at some point, but so far they're pretty behind the schedule roadmap they showed in that stream
the best i can suggestto save a drawing is something i suggest in the past which was: create a screenspace canvas inside a trigger area, put your camera in the trigger area and take a photo of the drawing via that canvas overlay (not sure if this world does the same as ive not been there in 3ish months but this is how i would save my drawings)
"you can save your creation to the web."
I did not see anything that can do that there. Did I just miss it?
I think i misunderstood how controls work. there is a button to 'sync' but it seems to just sync the picture for all the users in the same world.
@jaunty sentinel I'm trying to reach you cause I got a question for you please reach out if you see this x.x
Hi, quick question: Is there a way to sync the appearance of UI Canvas elements between players?
I have a panel with toggle buttons (checkmark or no checkmark) and it seems to not sync between the players. (Using the VRC UI Shape. I tried using VRC Object Sync on the toggle buttons, on the checkmark UI Object, on the whole UI, but it seems to only sync position and rotation, not appearance.
Yes, object sync won't handle such a thing. It depends on what you want to do, but most likely you want to have manual sync for those, which means writing some udon code.
Heya, I'd like to have some sort of ping compensation for a synced animation in a world I'm working on. Is there a reliable way for me to determine how long it took for a manual synced item to get from the owner (instigator) to the local client?
I am using u#, by the way.
You can send the time the animation got executed on. Then you can just do current time minus instigator time to get the delay.
I think you can use Networking.GetServerTimeInMilliseconds for that.
Thank you, I'll look into that
Is this on quest
How would I preserve sync/late join sync with udon stuff? I've made a separate room for stuff that only activates if someone goes in there. But the issue is that this only gets synced to people already being in the room. Anyone new entering sees the default state.
I want the objects off to save performance for everyone not using them currently.
Also had the issue of some game not properly working due to game master not having the objects active
So this depends on what you want to sync
if its just the on/off state you could make a udon behavoir for it, that syncs some variables
basicly if sync mode on the behavior is set to manuel it will sync when you explicitly call the RequestSerialization, but also to any new player joining the world
if sync mode is set to auto it will sync 4 times a second to anyone
It's minigames like pool or pinball
games are rather hard to sync like that as it would require the game code itzelf to be implemented in such a way that it syncs. if the object the game is on is disabled it will also interupt re from receiving events and thus breaking syncing, not many objects can recover from that state
So basically I've to trade full sync in for performance
for most udon prefabs yes. unless you fix any sync issues by writing code for it manually if the source code is available
Mmh guess I'll keep the current world settings panel then
Concerning the syncing of physics:
When I have a soccer ball that is synced with Auto (4x/sec), everyone but the owner sees an oscillating motion rather than bouncing.
Can this be circumvented by adding a RequestSerialization to a UdonBehaviour for Collisions with the walls, despite the Ball already having a VRCObjectSync attached or will the UdonBehaviour be ignored if there is a VRCObjectSync attached already?
I mean, to get the most precise movement of the ball to all players, should I send my own sync requests on each and every collision with the environment or can I leave 80% of the work to an VRCObjectSync and only cover edge cases like collisions with players and walls in a separate UdonBehaviour on the same Object?
yes and no,
the same object cant have multiple sync modes on it, it just wont compile
so adding a manual sync behavior to a VrcObjectSync that is continues wont work
Hm, how should I go about it?
I need to hVe a very precise ball motion, since players can kill each other by smashing the ball and hitting other players.
what if you used player motion locally to do the physics, then sync position and inertia ondrop andor collision
so VrcObjectSync 4/sec sync isnt that great, you could create your own udon behavior for synching transaforms and rotations that is manual sync and you can then do it faster then 4 times per second
to get smooth motion
based on who ownership
but ofcourse this is major strain on the network so dont want to do this to much
Well, there is only one ball and max. 8 players
If we can't handle that in 2022, I lose my trust in the future of networking, haha
I think just 4x per sec is fine, if additionally collisions with the walls are also added. This oscillating motion is so immersion breaking otherwise
The ball cant really be picked up.
Players are sitting on a robot and driving it around. By left click, the robot does AddForce on the ball obiect, if its within a sphereCollider around the object.
This way I tried to keep it simple, but this jerky movement of the ball was driving me nuts.
These robots can also get destroyed if the ball smacks them too hard, disqualifying the player and teleporting him back to the lobby, similar to prop hunt.
Töthe robots use a VRCObjectSync
And UdonBehaviour script to controll them with WASD
If I ubderstood it correctly, the VRCObjSync only syncs position and rotation as well as velocity?
well for one, is the ball using extropolation right now or discrete?
Discrete
would switch for slightly better physics
i would look up rigid body manual and check out
exactly
I will, thanks for the hint!
Objectsync when it's not held as a pickup is extremely low-priority so you probably don't want that. As Jarno suggested, if you want the absolute highest quality syncing you can do it yourself with manual
im not 100% on the velocity part but phasedragon might be able to tell
I had no idea, thank you!
So I will go for manual UdonBehaviour with RequestSerialization of pos, vel and rot for both robots and ball in case of collisions and triggering shots.
i would sync position and totation on collision with robots along with inertia, that way itll look like the ball is moving smoothly and synced when needed. but since its one ball, jarnos method would probs work better
it's a pretty big task to make your own syncing code. It's not just a checkbox
Isn't it mostly just doing a RequestSerialization?
I mean yeah, that's how you send the data. But how do you interpret it?
Oh, i thought the server handles that
that's not what I mean
if you just set the position as soon as you receive it, it'll be jittery
because at most it'll be about 10 times per second
Ah right
so you need to interpolate
lerping position might add weird latency
Felt quite smooth but also a bit sluggish
Can I get the players oings somehow?
Then I could interpolate
Pings*
you can keep track of the time between receiving sync, that's one of the important variables
ping isn't super relevant
sure, if you need to account for collision then your approach will be different
this is an entire field of study 😅
Haha true that. Nonetheless it feels so fundamental for games in this time and age.
I was messing a bit with proton servers and Unity in the past. If I understand it right, VRChat also uses Proton?
Photon, not proton
Aah sry, autocorrection
proton is a compatibility layer you use to run windows games in linux
Meant to write that (im on my phone and my sausage fingers failing me)
but yes, vrchat uses photon networking
Yup I know, running Linix most of the time
which means that it is effectively peer-to-peer in that everybody can take ownership of whatever and send data to everybody else, except it all goes through a relay server so nobody is communicating with each other directly
the server does not care about the game, it just sends packets around
So I can't really let the server handle the trscking and informing the clients about current pos?
Maybe using UTC time to check the age of the information and interpoöate based on that
correct, you need one of the players to be the owner of the object
Hm, so I guess the last player exerting force on the ball is owner, until the ball collides with another player
yeah, you can certainly get better results that way but it will be a lot more challenging to make it look good
Hm, true. Also im using oarticle effects like fire n smoke that make the ball burn when its high velocity. Maybe it can help mask the jerky movement or it might make it worse
I have a question what difference of functional between RequestSerialization and SendCustomNetworkEvent?
SendCustomNetworkEvent will send a single event over the network. It does not contain variables, it does not require ownership.
Requestserialization will send synced variables over the network. It requires that the object is set to manual sync. It requires ownership and when other people receive it, they will get the OnDeserialization event
In SendCustomNetworkEvent, Could you explain what does it mean exactly not to contain variables?
In practice, there is some confusion in that synchronized variables can be accessed by both functions.
network events don't transmit variables, that's all there is to it really
it is just an event
if you wanted to sync variables and an event, you could requestserialization and then send a network event. That will work most of the time. But you can't guarantee that the variables will arrive before the event because they take different paths
ahhh
but in this case I don't think you need a network event at all since all you're doing is updating the state of an object with the value of the synced variable. You can do that in OnDeserialization with no side effects
Okay, now I understand what you mean. Thank you for explaining!
@frozen igloo trying to remember your explanation for ownership transfer events
As I understand it, When set owner is called, the ownership request event is called locally on all scripts tied to that object, correct?
If you return false (transfer not allowed) does it then request a result of the ownership request event on the active owner?
if you return false it cancels the transfer
So OnOwnershipRequest doesn't ever ask the owner of the object if it can be transferred? only the local player?
the ownershiprequest event happens for two people: the person requesting the transfer and the person who owned it. If the requester denies, then it doesn't send anything over the network and the owner will never receive any event
So yes it runs on owner
yes
if the requester returns true, then they will assume that the ownership is that way before they receive confirmation from the previous owner. Which means if they set it to themselves, they can set variables and requestserialization
if it goes out to the owner and the owner returns false, it will then send a message back to the requester and tell them to revert everything they just tried to do
Perfect. Will require some rework of my asset, but that might be what I need to implement. Thanks for the clarification!
Hello, I'm reading through this channel and saw another post about this drawing world.
In the description is says that it supports "synced textures".
They appear to be drawing to a render texture, then syncing that to other users in the world.
How is this possible? How can you even get data from a render texture to send to other players?
https://vrch.at/wrld_86f03319-38c5-4d8b-8935-b2a5ab58b22e
Might be worth tagging bd_
@woven pewter Hi, are you the creator of the "Drawing Retreat" world?
I'm wondering how you are syncing the "synced textures" for the canvases.
Are you syncing render textures somehow?
I actually wrote a whole post on this: https://ask.vrchat.com/t/need-some-help-with-shaders-and-rendertexture-for-a-painting-world/6883/8
I talked to jynbug directly, but I guess I should probably post some information here as well. Capturing a RenderTexture in Udon isn’t too hard - you need to attach an UdonBehaviour to the same GameObject as a Camera; in the OnPostRender event the render texture attached to the camera will be active, so you can do ReadPixels there. To have cont...
You can also see a debug version in shaderfes (I think it was in the green branch?)
yeah, shaderfes 2021 G07
Perfect, I'll take a look at this, thanks
tl;dr it's complicated
Yes it does seem complicated.
This post was very useful though. I am trying to sync a canvas for late-joiners, similar to what jynbug is trying to do there.
It seems like the 11 kilobytes/s bandwidth is the main issue.
I didn't realize VRC's networking was that strict
Why does this work locally but not for other players or late joiners?
Custom events do not resync for late joiners
A networked serialized variable is required
Hiya! Is there any way to send an event with parameters to the master client?
Let's say I want to invoke a method on the master client, a method with a parameter. Is that possible?
RPCs with parameters?
no, not possible, there are sort of workarounds, what's your use case?
I have created networked NPCs and I want to send an event specifying which NPC took damage and how much damage.
I have all NPCs in an array so I would need to send two params, both integers.
By replicating both integers before firing the networked event, i may run into issues as the integers might not have been replicated yet before the event is fired on the other client.
the integers might also be overwritten if two attacks happen at the same time.
Do you know about syncing variables? You'd want to use the manual sync to RequestSerialization and transmit the NPC id and damage to everyone. Then you receive those values via OnDeserialization and call the event you want locally. The transmitting of the event is already like an RPC in this case.
does anyone know how to spread out teleportation between multiple points for multiplayer?
not spawns, but teleports.
teleports are things you do programicly with udon, you teleport a player to a certain position
so you can either select the target position out of range of posiable positions or add a random +-x +-z to the coordinate to offset the position by a random amount
ok, how would you set the random x y z coordinates to a transform?
A transform.position is vector of x,y,z the y is the height so you leave that the same, but you can alter x and z simply by adding or subtracting a random number from them
How do I make this local
either make the event name start with "_"/underscore or set sync method to none on the udon behaviour
this event for player trigger enter/exit will fire on remotes too, identify whether it's the local player to proceed
I am using an animation on a pivot point that rotates multiple planets around it, as well as then having the planets spinning, with a moon also rotating around on of those planets.
I would like for these objects to be synced for late joiners to the lobby, so I assumed that putting the VRC Object Sync component on each object would allow this to work properly. But last night I was testing with some friends and some of them joined late and the planets would be flickering between the synced position, and the position of the planet as if the lobby had just begun (as if the animator reset to the start). What exactly should I do to make the planets and their rotations/positions sync up for late joiners?
I think I essentially just need to set up a variable that allows me to sync the animators on the objects up in the same way that the object sync is supposed to update position data, right?
I think so too.
In this case... I think it might work if you sync the animators' time. Maybe...
I could potentially bypass this by having all of the different orbiting and spinning animations all on one parent object right? Then I only need to make sure that the one animator is synced across the network?
Yes, probably. I've never tried it, so I can't guarantee that, but I think it's worth a try.
okay so I ended up making a script that allows me to grab each planet I want and be able to change the speed of each planet individually, as well as their rotation axis individually. What I'm wanting to do now is have this be synced up for everyone in the instance, and sync up for late joiners in the instance as well. What exactly would I need to add/change on the graph here to do that? Or would I end up setting up a different udon behaviour entirely to do this?
As you can see, I have an object sync script on the object that is the parent of all of the planets, but that has not helped with the situation.
Okay I actually figured out how to sync the planets main orbit, but I cannot do synced variables for the arrays. Is there a way I can set that up in the graph so that their rotation states in the arrays are also synced?
Basically I have my planets properly orbiting and it looked like their rotation states properly synced, but I have a moon orbiting one of the planets, and it was desynced in terms of how far around the planet it was supposed to be, but was still properly synced in terms of following the planet that was orbiting around the main orbit location.
I'm sorry, but I can't figure out the current situation... especially about the "but I cannot do synced variables for the arrays..." part.
I haven't checked, but could it be possible that the array sync doesn't work unless the array itself is recreated instead of rewriting its contents...? (I think I' m wrong.)
I apologize for my lack of skill.
No worries, I have a poor way of describing things due to my lack of knowledge on the topic at the moment. Still learning a lot.
I managed to get the variables synced up (rotation, location, etc.) but my last problem is that the planets and rotations are jittery for people syncing up to the instance owner, and I'm not sure what to do to resolve that issue.
Go to where you made it public & synced, and change the sync mode from none to something else (liner or the other one, see what's best). This will smooth out the float updates to make it seem more consistent. Will make it slightly further behind though
so i condensed the top part with the separate axis not using arrays down into the arrays (was testing what you just mentioned) and if you see in the variables, I cannot edit it to linear or smooth.
But from what I saw, linear and smooth didn't make a difference on how well the planets moved
Huh, wonder when that changed...
You could always create a private variable that is the local position, and lerp it with the networked position, but dunno how hard it would be to make that smooth...
so a private array of each variable for their local locations and then lerp (not sure what that is yet haha) that with the networked position?
How about this?
Change the synchronization mode from continuous to manual and run RequestSerialization at regular intervals.
To achieve a regular interval, you can use IsOwner to check if the LocalPlayer is an owner, and then execute RequestSerialization again after a certain time has passed since the last time you executed RequestSerialization.
In this way, the gimmick will basically run locally, but will be synchronized periodically, so it will be almost smooth. (It might be better to have RequestSerialization even in OnPlayerJoined)
^this
So I thought something like this might work, but I still don't quite know what I'm doing yet (i was surprised I got the planet stuff working as it is) and I haven't found any udon graphing guides that kind of explain these nodes and how they interact with one another. Do you have any recommendations on a guide I could go through that explains these things so I can understand what I'm doing as I put it together?
Yea... Guides be pretty rough. This one might cover it, but I haven't personally look through it https://youtu.be/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...
It's also like... an hour long.
xD I got 31 minutes through that and didn't get anything immediately useful out of it so it's paused in a different tab at the moment haha
i might just finish that up
and i'll check out the synced slider video the VRC team put out and see if I can get anything out of that
Um... actually, I don't know of many detailed explanations of Udon that are not UdonSharp...
That's why I'm writing an article in Japanese explaining UdonGraph, and will eventually touch on synchronization.
If you can ignore some differences in wording, it might be useful to look into synchronization in UdonSharp... but it's hard...
For the whole manual sync and Re-sterilisation, I did do that in my skybox changer tutorial. Perhaps have a look there, though it's more of a thing in passing
I would genuinely love a link to the article whenever you post it. Trying to learn as much as I can about these things so I can put them to use in world creation
And I can look into UdonSharp as well and see if I can make the connections between that and the graphs.
Well, does it means that you want a link of my articles...? (Sorry if you don't.)
If so, that's the Qiita link on my Discord profile.
It's mostly a "list of frequently used nodes" at the moment, with few examples (I'll add more in the future).
Instead, the Booth link on my profile provides free examples.
I apologize that they are all in Japanese at the moment, but I hope they will be useful.
I do! I'll check out your discord profile and read through the article. No worries that it is in Japanese I can get by on google translate for now haha! Thanks!
Also I just saw this. I watched through it and tried modifying things to what I think I would need to make it work, but I cannot get it to sync up properly.
I put an event "onplayerjoined" going into a "sendcustomnetworkevent" for syncing the rotation data for the planets and orbit, but it doesn't seem to work at all.
Is this generally what you meant for updating the location of the planets? Honestly it should work well if it just syncs when new players join to keep things relatively lined up. Doesn't necessarily have to be exact.
yea... this isn't really something that's easy to walk you through with just text...
so I did some playing, and this should be more or less what you need. I didn't have a scene to playtest this with, so beware there may be bugs.
What you want to do is update the rotation of the planets to be what the host sees, and then have it's position be updated locally. this ends up being done separate to your original code, and the new code does get a little large
holy crap that is quite large
I am genuinely interested in learning this graph inside and out so I can understand it/apply it to other things I may want to do. I totally understand that explaining things over text is less than ideal in this situation. If you're willing and it isn't a huge bother for you I would love to sit down and listen to an explanation of things and it would allow me to ask questions more directly about parts of it. Doesn't have to be right now or anything, but if you have free time at some point and it isn't a bother, I'd be more than willing to sit down and really understand what you're doing in the graph here and ask questions. I'll be taking some time now looking at the graph to understand what I can from it and give it a test.
yea, I wouldn't mind sitting down and answering some questions. Spend some time looking through it and figuring out what you can though, as that filler learning of me explaining it tends to consumes time
I will be spending quite a while disecting this and experimenting with it so I can understand it. Thanks a ton and thanks for putting time into the graph, I genuinely would not have even remotely come up with something this elaborate at this point. Maybe in the future after I have learned more, but I don't think I could have done this yet hah.
Yea, there's a reason udon networking is split out into it's own channel. There's a whole lot of small lessons that you learn over time that just kinda come together
Hopefully my notes will help with dissecting it ^^
Looking forward to learning more! And the notes have been helpful so far! I'm sure I'll stumble across questions on things as I tinker with it and try different things with it
Ironically it does seem to work fine for the non-local player now, but the rotation doesn't actually occur for the owner now. Going to look through and see if I can figure out what might be causing that.
Okay tried testing 4 different clients and rotating them through host migration of the world and when it swaps a player to being the owner/host the local script essentially freezes, which in turn makes the sync off for any late joiners as well.
What exactly would be causing the rotations/speeds/etc to not play for the owner of the instance?
I also am having a hard time understanding the use for currentCount in the graph
Oh it is for grabbing a planet and then allowing each x,y,z to be set, then move to the next and run through that again, i see.
Yeah it appears to be breaking for the local host because of something in the syncing when a player joins the instance. It looks like it plays the planet rotation for a second or two and then it freezes for the local client. When someone joins late, I (assume) it syncs up to the small bit that did occur for the local player and then continues to play out the rotation as if it were still playing for the instance owner as well.
so, it sounds like the script is crashing at some point... hence why the planets stop moving, as the script to sync them is also the one moving them. Perhaps change the int.greaterThan node for a int.greaterThanOrEquals node. I'm suspicious it's counting one to many higher than it should. Would also be good to see if the convert.IntToFloat and convert.FloatToInt are converting as expected
Would that cause it to crash just on the local side though? It seems to rotate fine in unity when in play mode and it also rotates fine for anyone who isn't the instance host.
if this is too large, the script will crash. I suspect this is where it's crashing.
also if they aren't the owner of the object, this whole section of the script doesn't play
ohhh i see, okay cool when i hop off of vrc i will do some more testing haha
no rush or anything
Changing the currentCount to be compared to the planetsToRotate length with a int.GreaterThanOrEqual fixed the issue thank you so much!
I'll probably just tweak the sync frequency to smooth things out now!
I have sat here and stared at it for quite some time and I think i have a decent general understanding of the graph, but once you indicated that the middle portion of the graph that syncs the vector4 values also affects what the owner of the world sees I understood that issues could crops up in more than just the onplayerjoined section or the original local part of the graph
If players are not loaded due to draw distance, do they not receive networking events?
players are always loaded even if not rendered
and they will always receive networking
objectsync and player sync quality is affected by distance but even at lowest quality it still does a little bit
Hmm, thats how I thought it would work. Curious
I am sending a networking event based on an OnTriggerExit, though it doesn't appear to be 100% reliable across all players. Any idea what could effect this?
Thanks for the response of course.
who is sending the network event?
For context, the local user detects the Trigger exit has occurred, and then that same user sends the event to all
what does the code or nodes look like?
Essentially its a component of a voice system, there is a collider on each hand (L and R) that send events when they hit they enter or leave the head object.
One hand sends a whisper, two hands a shout, none resets to normal params
that checks the owner of the trigger zone, not the owner of the lefthand. if you never transfer it, it will always be the master
the owner of the trigger zone is set elsewhere
is that person always nearby?
Yes. On spawn in they are assigned their own set of head and hands. This node graph is on the head object
The object updates its position based on the head bone of its owner, so we know that any event is being called by the owner of at least the head and one hand.
are you sure the triggerenter is even happening correctly?
Yeah so we play a haptic event in the controllers whilst the trigger is registered as entered, then we cancel the haptic event when the trigger is exited. So we know that the event is occurring.
In addition, players can re-scale the head object to customize where contact happens, but that doesn't appear to have resolved the issue.
ok then are you sure the network event is failing to go through or is it the result of the network event that doesn't work?
This is what I am struggling to diagnose. From simple observation, with 40 players in the lobby the system is working the overwhelming majority of the time. But then all of a sudden a player might get stuck in a certain vocal state until they try to "re-jig" their settings by calling the triggers again.
Thus my hypothesis that networking events might be being skipped based on proximity.
oh, if it's only unreliable sometimes then that's just because you shouldn't use network events for something this important. they are not guaranteed reliable. that's what manual sync is for
network events won't get dropped by distance but they can be dropped if there's too much traffic in general
Ahhh I see. That was the other idea. Sorry this project has been my first foray in to video game networking so there has been a lot of learning.
So in essence, switching to a manual sync solution is the key. That would explain why i couldn't replicate the issue with a smaller lobby. Cheers Phase.
what's the biggest array we can efficiently sync in udon today?
the size of the array isn't the limit, it's the total number of bytes on the object. That limit is about 60kb per serialization in manual sync
in this case I have a single bit per element 🙂
so I dunno, I'd probably pack it into longs
you can see how many bytes you use if you add onpostserialization and print the serializationresult.bytecount
what I'd really like is a way to sync a RenderTexture but aeh, looking at other options
I assume having a million world objects is out of the question
syncing a whole image should probably be done over multiple serializations
but it is possible
for everyone already present, it should be possible for most of them to just derive the next image frame from the previous frame, the issue I guess is if the owner changes a pixel manually at some point
they're going to send that update out, and if it gets sufficiently delayed, someone might generate the next frame incorrectly, and have to recalculate it
so I might have to keep some kind of history of the last N frames
having a million game objects would be nice in its own way too
if I were doing this in a 2d toolkit there would usually be some kind of lazy row, lazy column, or lazy table thing, where you only create the object when it's going to be needed... but Unity 🙄
I just watched this whole thing thank you for this
np ^^
I'm trying to do a set of drinks and everything is working for local users but I'm gonna try to make visible the amount of drink in the glasses to everyone looking at it
I dont know how hard it is to sync it but globally I did a onpickupdown event to "drink" that activates a gameobject and deactivates the two others (three game objects for three different layers of liquid). It's working fine for the one drinking but everyone else keeps seeing the first gameobject (glass full) activated even when one empty the glass from his perspective
I'm not sure yet how to do it but I'd like to manually synchronize the activeself of the different drinks game objects while keeping the pickup's moves synchronised with everyone
and why isn't object sync compatible with manual sync btw ?
manual sync:
just have a state, a byte or int, mark as synced, the integer represents the different stages
in the OnDeserialization event you then check which value is set and adjust accordingly
when a player drinks, ensure you set ownership to the drinker, decrement the value if the drink is not empty, and you request serialisation
So I can use the manual sync while keeping the vrc object sync ?
(to keep the drink's place synced with others players)
just keep the parent using object sync and offload the rest to a child object
I'm gonna try to do this again but last time I did the drink were not sync in place with the glass it had some delay
Maybe I did the opposite (placing the udon on the parent and sync on the others
Imma look into this thank you
the children move relative to the parent
Just out of curiosity can the custom network events work as well ?
Or something like this maybe
it can but the events are not buffered in sdk 3, late joiners would not see what you do
Okay thanks again xD
hiya
Question about UdonSynced variables and behaviours set to manual sync instead of continuous. I have door animators that should be global synced when a player interacts ( a bool isOpen set to ! isOpen in interact method ), but right now it only syncs when the instance 'host' opens / closes the door. When my second client tries, the animator works locally but it's not synced back to the host. I'm using RequestSerialization() as well as setting the animator to the synced variable OnDeserialization() so I'm not sure what is causing the non-hosts to be ignored.
I can send code snip if anyone thinks they might know
you need to take ownership of the object before setting synced variables
Wow I hope its that easy of a fix
so i should try using set owner at the very beginning of the interaction?
yes
the typical flow for manual sync is setowner > set variables > requestserialization
Thx so much it worked, I would have spent hours trying to figure it out and then realize it was so simple
is VRC_Pickup.pickupable synced?
no
Cool. Might just be my logic then. Other players being able to pickup something they shouldn't be able to
how are you setting it?
VRC_Pickup.pickupable = bool
Not literally the identifier bool, but supplementing a bool for it
I'm working on a game world, and I've added a local toggle that could be considered cheating in certain settings—there are legitimate reasons for players to turn it on, but I want the whole world to know that they've turned it on, so I'm trying to set up a wall panel that lists the players who are using that toggle. Is there a standardized or sane way of doing this?
Right now, all I can think of is implementing the list as a synced variable, having each player watch the list in Update, check for whether their name should be on it but isn't (or vice versa), and take ownership of the list behavior to correct the list if so. This seems both like a performance loss and really ugly—I figure I could limit the checks + ownership requests to specifically when the toggle changes, but I don't know what happens if two players toggle near the same time, or if the owner of the list behavior disconnects, or any number of other weird race conditions. Is there a more sane way of solving this?
(it is MADDENING that custom network events don't seem to include their sender)
Not sure if it's overkill for your use case, but using a player pool with player owned objects will ensure a lot of safety (and your sanity). Each object will have a manually synced variable that can be set by the specific player and everyone will know about it.
that actually seems like it might be a lot easier
at that point, i'd just need to handle objects with a stale owner, right?
I'd recommend using the following pool so you don't have to manage ownership yourself.
https://github.com/CyanLaser/CyanPlayerObjectPool
I would have suggested the same thing. Really is handy with storing user related properties and methods
hey, i followed the vrchat example for a synced video player 1:1 and the video wont be played for other people in the same room. for me the video starts playing though
i more or less copied the code
but its the same code and it doesnt work for me
anyone having experience with it?
or is there like a prefab you can buy for a working vrc video player? i feel like a lot of different worlds use the same framework, even graphics wise
look into udonsharp videoplayer by merlin
Tags question!
Is there a way for me to serialize tag information and update other players to local player tag information changes? Other clients don't seem to be getting the changes I'm making locally, despite requesting serialization, or maybe I'm doing it wrong if I want everyone to have all up-to-date tag information?
I'm doing this in udon graphs, should I look into u#?
player tags are not synced
if you want them to be, you must add auxiliary data that, upon syncing, updates the tags locally for everyone
which i don't recommend
instead you could use a pool where every player obtains 1 object but also synced
but for further usage, you should explain your problem
Oh hey, sorry for the late reply, I'll take a look at that tomorrow and let you know how that goes, thanks already!
Usage is I want players to be able to register for a game, and let anyone who is registered start the game, which selects one random player from everyone who's activated and teleports that one person to a different location
Do objects with an udon behaviour with no synced variables on it still have an 'owner'?
Aka, if I were to go get is owner on an object with a pickup component (and no object sync), will it still say if me or someone else were the last one to grab it, even if it didn't update its position?
pickups transfer ownership even if they don't have objectsync or any synced variables, so yes it would say whoever picked it up last
but if something has no syncing whatsoever, it should give you the master
Cool, thanks for the info ^^
What's the performance impact of having a syncing, grab able game object? And how that scales to amounts upwards of 3000
Just 3000 cubes
I suppose the number could be increased by updating them every second and then predicting positions in-between, right?
Here's a tutorial explaining how to call an event, a delayed event, a networked event and a delayed networked event on another script!
This tutorial is for udon graph, though I do have another tutorial covering this for udon# too. So if your after that, be sure to check that out
Hopefully this helps, and if you have any questions, feel free to ...
Is there a way using udon graph to read system time and trigger an event on a certain hour of the day ?
My goal is to organise events in a world that is sync to everyone. Example music concerts... if the sync is done based on DateTime instead of network events ?? just wondering ...
if you want to trigger something locally for everyone at specific date/time you can use datetime utc now
but, you need 1. check/compare (https://stackoverflow.com/a/5178603) datetime on Update, or 2. on Start run a DelayedEvent with length of Time until your date. i think 
Is it possibe to do this with udon graph ?
I think DateTime approach seems to be better if I want the music and animation to be sync throughout the world for everyone including late joiners .. I am wrong ?
I see my DateTime assumption will not work as vrchat is not a persistent world. The world will not continue to exist or run ... unlike some other metaverse out there which is one world by itself.
The metaverse or nexus, is nothing more than a concept. in reality, unless everything is done via cloud computing, with faster than lightspeed connections connecting us to a super super computer, it cant be one world. Instead, every client/computer will have to sync their local version of the world to be the same as the networked version of the world.
As for what your after, you essentially want events to sync up to a time. You can (with a bit of effort) do that in vrchat currently. The only thing that cant be done right now is something done in one instance effecting another, or doing something in an instance, leaving and coming back to it being the same.
Has anyone found that manual variable sync can be slow for late joiners when there is a lot of people in the instance?
I have a toggle for locking a door that syncs as it should for late joiners normally, in the OnDeserialization event.
But when there's 70+ people it doesnt seem to trigger than when you join and the state doesnt get synced until another manual seralization gets called
maybe i could add a RequestSerialization for the owner of the variable on the player join event to try and counteract it?
Interesting. Would checking if it's clogged and if it is requesting a serialization solve it?
If it is clogged maybe trying to get the data out again would just get stuck anyway.
Oh i also see there is a IsNetworkSettled , would i be right to guess that that will occur once its no longer clogged?
manual sync will slowly catch up, but if you get clogged networks, it often is you oversyncing data
Hmmm, i dont have many synced variables, but i do have 2 decks of synced cards so maybe that's contributing too it.
or is it just for when the world is initializing
Ill give that a try
Thanks !
Does this solved your problem?
I havent noticed the issue occurring yet, so it might have. But i havent had a full 80+ lobby for a few hours to be sure, only like 60 ppl.
Thanks for letting me know, I have similar problem on my world..
#user-support-old Not an udon question
Found the information on this very helpful, thanks for sharing it.
that's great!
I had similar issue with the sync, though there's only very little data needed to be synced, when there's a lot of players joined, all the variable syncing seems just totally suspended until very long time after. This can add up to mins.
But if there's no new player joined, all the variables sync in a very decent short amount of time.
Hey folks, I'm a long-time game dev with a lot of experience with Unity, but Udon & Udon#'s networking is giving me some serious trouble. I've got my UdonSharpBehaviour-derived class set to manually sync; I've set its owner to the interacting player; I've got the variables I need synced set with the UdonSynced attribute; I'm calling RequestSerialization after any changes from the owner player; And I'm pulling in the data to display in OnDeserialization. And yet, despite all of this, basic things like score integers aren't syncing. Does Udon have issues with prefabs, maybe? Several of my networked objects are prefab instances. I'm not instantiating or destroying anything at runtime, though. Any other common mistakes I may be forgetting? Thanks in advance.
sounds like you're doing everything right. The only thing I can think of is if there's something preventing the code from running like the object being disabled or it halted from an error
I'd also verify if its serializing with onPreSerialize or something
See where its breaking, on sending or recieving
Yea, put some debug outputs in there, check they're all calling when you expect they should be
If you haven't figured anything else out by now, I'd also recommend checking that the player attempting to sync has ownership of the item. I usually force an ownership request every time I change something locally and need that player to send network it Never mind, said you did that. In that case I'm only here for emotional support
Networking is always a pain
I know I've had OnDeserialization lead to RequestSerialization that feeds back in a loop and causes players to fight over ownership before. Likewise if a change on update does the same thing
I also dont trust networked events, so I usually try to work around them. I dont know if thats well founded but I just avoid them
Is there any function that can set a sync object not syncing when it's not needed? Simply set object inactive it doesn't seem working.
And it jam all variable syncing when there's many sync objects.
Yes there is a sync mode none
Question, what would be the most optimal way to sync a variable for something like a world-wide stats system?
I don't really understand all that much about network code so I thought I'd ask
I mean the object sync like this.
Ohh yeah, no.
Thanks, I'll try that!
I have a log of interactive weapons in my game world, and as a result I notice when there's new player joining, the more new player just joined, the longer the variable sync will be jammed for, this can add from 10 sec to up to mins...
Yeah, I've got a couple already. My next move is to build in-game debug state panels to expose everything.
Is it possible to dynamically spawn syncing objects?
I'm not sure how the Object Sync works in vrcsdk, but since there's the warning of gameobject using same path name error, I assume they take a parameter of the gameobject's name path to identify a syncing object?
But is this path being read once on instantiate, so changing the object name after it's spawn won't affect the object sync? Or will this read happen after a bit so changing the object name on spawn will affect?
Names don't matter, when you start the map all networked objects get assigned a network ID
It is never run again after this point
So any future networked objects won't get an ID
spawn a gun for player to pick up, and for other players to see this gun
I don't think dynamic sync object spawn is possible if they get network ID on start of the map though.
How you'd do it is by having an object for each player called "ItemManager" and that item manager would in arrays describe every object that player has last touched along with their ID. You manually create it this way
The downside of this system is that picking up objects another has last touched looks odd to 3rd party observers, and only allows objects to be on a fixed position on the ground, or in someones hands activelyt
No falling/throwing/ect
And if the objects themselves need sync'd info (Like a gun firing) it won't work
So basically manually coding a object sync function,
Ya I don't think it will work well,
Unless you truely need to support infinite items I think a pool of 40 reusable networked objects that can describe any gun is better
The project that did this networked item implementation did it because their developer is a madman @jaunty ice :P
I do have a "left-hand" pick up function for desktop user in my game, and it has a bit bad latency. It would be much easier if I can access to avi's transform and attach the object on it.
Something I'm very confused, is when the object is inactive, they still sync their positions as long as they have this VRC Object Sync component attached... that jam the network whenever a new player joined. An object pool system is supposed to optimize the performance, but it just doesn't work. And this Object Sync component cannot be disabled neither, it's fully locked.
I don't disagree
In theory you'd have a very limited amount of sync position objects
IMO its probably easier to do manual sync and just say whose hands the item is in, and teleport the item to their handbone each frame
Or just say where on the ground it got dropped and sync its position manually as it falls
This will be too much for the very restricted network we have, imagine 20 players holding 40 guns, that's 40 x 3 = 120 float variables being synced very frequently.
Well no
VRChat itself is already syncing the position of avatar's bone positions, I just need access to one of its transform so I can attach this object to it... that's also how the VRC Pick Up do, but they don't have these parameters exposed.
You'd only have to manually update the variable for the gun when they drop the gun or swap hands
You can access bone position/rotation
Just not transforms
Oh you mean manually "attach" the gun to the bone by position update
yeeep
So you have a gun defined as
- Who is holding me
- Which hand
- If neither, where am I on the ground
And on update() if its in someones hand, teleport the gun to their hand position
I think it will kill Quest CPU, but it's an interesting idea.
Nah
the SAO VRC project does it
IMO its not bad
Depends on the number of guns
Even so you could make it even more efficient
I built this system specifically for optimizing the quest user performance. Their CPU is impressively low performance. Just simply 200 bool check every frame can make it drop to 20-30 frames
I learned that when I was profiling my chess world.
If there are more guns than 2x Player cap, instead of teleporting guns to hands, have 2 orbs attached to the players hands (Via update teleport) and have the guns attach their transform to those hand orbs
So worst case there will be 2x player cap update() position teleports
oh wait, now that's a really good idea, instead of letting player hold guns... we let players hold orbs, we only need 48 sync object orbs and that's it. We can attach guns to these orbs and it should just work.
Yep
Do that if the Gun amount is arbitrarly large
You'll need to attach the gun to orb and fuck with local position/rotation but eh
Its at least feasible (I did it for my project)
I put murder bomb bracelets on kids ^-^
Oh position/rotation would be very easy to do. I will leave the guns with vrc pickup component, but build a customized pick up object sync system with only 48 sync objects.
No wait but this will make the connection for guns and pickup indirectly...therefore latency.
The only optimized way to do this is make the orb itself be the vrc pickup being bound to
Honestly just have the orb always attached to hand via some sort of player specific tracker object
I'm sure you'll need a player tracker object for something else (Health, ammo, whatnot)
Might as well re-use
could be very confusing if they try to pick up a gun among multiple guns though, caz the gun won't be highlighted, the orb will be
no I don't wanna use the position update attach, I need the VRC pickup attach.
That's the only way to smoothly syncing an object being picked up by player.
without having too many local position updates in update functions
you can force it smooth but it requires local position update.
Requires on which object?
I think the wristband itself had its local position updated yes
It went from being world position to local position with an adjustment when it got attached
I didn't have to do that calculation though its automatic
The calculation would only be on pickup/drop
but don't you have a position update function for that orb every frame to attach this "tracker" on the player's hand?
I know for the bracelet we can just set parent to that "tracker", there's no need for updating that.
but for this "tracker" to player's hand, we do need a position update, right?
Yep
It would be perfect for PC or local objects... but for guns in Quest build, it would be heavy on performance.
That's why I was thinking we could give this "tracker" a "VRC pickup" and "VRC Object Sync" components.
So when the player picked it up, VRChat will attach this "tracker" to player's hand for me. And then I attach the gun to this tracker.
playerApi.GetBonePosition and playerApi.GetBoneRotation?
That’s the position and rotation but I do not think the transform itself is exposed
ah, I think I get where your coming from. Yea... no parenting
👋
damn can't use emotes from other servers here lol
hmm stickers are allowed though
might want to patch that
will calling RequestSerialization() every 1 second clog up the network or should it be fine?
it's for syncing a countdown timer btw not for something that I could better use continues sync for I think
It should be fine (though I never tested it so no idea honestly).
Maybe you don't even have to send it each second though. Can you just send the start time of the timer and let the client figure out everything itself?
Okay, I discovered part of my problem. Some of my logic was relying on Networking.isInstanceOwner, which was, for whatever reason, returning true for all players simultaneously.
That is .. not meant to happen XD
I just switched it to check the owner of the master-state gameobject instead, so that should resolve the issue 🤷♂️
I remeber they where trying to depricate one of those master checks, but cant remeber which without checking the docs
That's Networking.isMaster. Just read up on that last week and changed all my isMaster checks to isInstanceOwner checks 🤦♂️
Hah, oof
were you doing a local test?
We were testing a non-public world, but it was two people in separate locations over the internet, so not local
Oh good point, was the check against the local player only or where you checking against other users than yourself?
It's not a function. It's a static boolean. Networking.isInstanceOwner
Oh right right
that's odd, last I heard it was working fine. But maybe nobody's using it so I never heard of it being broken
The things that i ahve that use it are functioning fine
hm, maybe Networking.isInstanceOwner is behaving differently from Networking.LocalPlayer.isInstanceOwner
I'm very much getting this sense as well. It's almost easier to send "events" by watching for a synced variable state change.
Yea, i genrally just write a little state machine that runs off a synced variable and base events off that
Do Pickups with UdonBehviours require continuous sync for their position to be updated continuously or will manual suffice
you cannot mix manual sync with objectsync
if an object is tracked with ObjectSync will its values never manually sync?
stuff will break, don't do that
child or parent, yeah
Thanks for the clarification
Trying to call a method on another udon behvaior but .SendMessage() is not allowed , is there an alternative?
Yea I just tried to do this with events but then realized that it only calls the event on itself and you can't really direct it to send an event to another object, unless im mistaken
.sendcustomevent
Does OnDeserialization work for continuous sync or is it just for manual use?
yes it does
it'll happen about 3-5 times per second as long as you're not the owner
Cool, thank you
How much money would it cost for someone to make me a komi avatar for vrc
Theres a discord server called VRCTraders for people who do commissions to make models. You'd have to talk to someone over there
Oo
Wait, so does OnDeserialization also fire 3-5 times a second for manual sync scripts too? I'm getting a lot of OnDeserialization calls in a log file even though none of my scripts ever log that they're requesting serialization
no, manual only syncs when you request and when someone joins
Okay thats not the behavior I'm getting
What kind of situations cause OnDeserialization for objects other than themselves? Referencing continuous synced variables from other scripts, calling methods from continuous sync variables, being a parent or child of a continuous sync script? Just being in a build and test environment with two clients? Anything like that?
are you mixing manual and continuous or manual and objectsync on the same object?
No, and they even dont share the same parent either
Wait, I may have found a stray reference from testing
Okay yeah I had a couple things going on that I just didnt catch at first. Looks like I had another copy of the script set to continuous in a different hierarchy that was firing my debug logs for receiving deserializations
i have an array of VRCpickups that i want to be able to reset to their original positions using a button. right now it works locally but doesn't reliably work when networked. what method do i need to use to get the reset working?
If you aren't already, just before you reset their positions use Networking.SetOwner to make sure that Networking.LocalPlayer is the owner of the pickups.gameObject, assuming you have an VRC Object Sync on them or are syncing the position with [UdonSynced] and continuous networking. Thats what I'd expect to work
thank you!
If you're using object sync, you can also just do an vrcobjectsync respawn
is there still an issue where if two people join a world at the same time, and the master sets a synced value on two different objects with requestseralization on a manual object, that someone could possibly never get an ondeseralize?
Im using this as a way to set an object's synced value to the player id of whom i want to take control of it, as such when ondeseralize happens they could try to grab ownership of the object. I need this so i can have the master also have an object they own. However, even tho everyone else can see what value they should have, they dont, so they never take control of the object
i would just send them ownership, and on ownership transfer let them take control, but even then i had the same issue pop up where they wouldnt set the value. Would it be better to just stagger the id set as people join?
also ill mention no udon behavior breaks at all, which is what has me the most confused
Can you have instantiated objects be synced?
You can instantiate objects but they will not have networking
Anyone know how you can access vrc object syncs from UdonSharp code? I'd like to temporarily disable interpolation when moving it, whether that be directly or with some kind of Teleport method
You can just have a public VRC.SDK3.Components.VRCObjectSync variable and then set it in the inspector.
Thank you, for some reason I was having trouble finding the namespace
what is the current up to date method for syncing something like a door's state to late joiners? the tutorials I'm finding are indicating that their method is outdated: using OnPlayerJoined to send a custom event to set the state of the variable. Is there a better way to handle this now, and if so, where can I get a primer on it?
Is there a way to guarantee something fires off before networking has a chance to do anything? I have stuff I want to set up my objects with on start but it seems it doesn't always go first
Thats what i do. I have the master when the door is not in its default state to call out to set it to that state on player join. This optimizes over just calling out its current state, because if the door is closed theres no need to close it
and specifically, to call out a networked custom event over a standard custom event
right. that's the method a tutorial video i found was mentioning, though the comments seemed to indicate that a synced variable is the "better" way to handle it after the UnU, though they don't explain the how or why.
id argue itd depend on how many doors you have. The event will cluster if and only if all of your doors are not in the default state, which the message will get through reguardless. Using a synced value means every door needs said synced value, which means they would all need to deseralize every time a player joins
also youd need a seperate handler for the master, because if someone interacts with the door, either they need to claim ownership of the door to set the value, or they need to tell the master with a custom event to open the door, which point you're doing the custom event anyways
handler is probly not the word for that, method might be a better term
overall, even though ownership trasnfer is better than before, it's still resource intensive to exchange hands. Its much better to just let one person to handle the sync using the same events everyone uses to open/close the doors
I'd just make an bool array for all your doors and just sync that. then on bool array change, open/close said doors.
@warm lodge
Don't think you can sync arrays though... Or was there a change?
you can
Neat
yes super neat
The three main concepts used for networking in Udon are Variables, Events and Ownership. Variables are containers for values - like a number, a set of colors or a 3D position.Events are things that happen at a moment in time.Ownership is the system that decides which user can update a variable, whic...
I need to gain a better understanding of quaternion rotations
VRCUrl is in the list twice, heh
There are a lot of typos
but yeah the point for the use case of a synced array is that all of the data will arrive at the same time
so it's very handy if you have a lot of the same data type that need to change at the same time
you still need for someone opening/closing a door to either take ownership or do a network call. Id still skip all that noise and just do a network call
yes thats the other half of the script
i mean it's really handy for syncing a large map with a ton of doors
i just have each door have on interact call out open/close based on its current state, and on player join the master if the door is in the none default state call out its current state like as if you interacted
most of the time you can just think of a quaternion as an axis and angle. thankfully with game engines you don't need to understand the math at all, because it is fucking crazy
multiply quaternions to accumulate rotations, or slerp to blend them, that's it
back to another problem: i asked a while ago about a "reset" button for an array of VRC_Pickups. this behavior seems to work sometimes, but the longer an instance is live, the less likely it is to work.
the behavior itself just triggers on a button press. i have an array of GameObjects. i loop over each one, get the VRC_Pickup component, then run the Respawn method on it. it generally seems to work at first, but over time becomes less and less reliable. i was under the impression that VRC_Pickups automatically sync. am i missing something?
What do you mean by "reliable"?
I think you need an ObjectSync component on the pickup for it to sync btw, but maybe that's not what you mean.
ah, i do have objectsync components
i mean that some of the pieces in the array will reset, but often will just stubbornly sit there
and the percentage of pieces that stick seems to grow over time
Maybe it's ownership related? If a bunch of people keep touching your pickups, then you might not be able to call the respawn method.
I haven't used that method in a while, so just an idea.
ah shit, i bet that's it.
Thats where object pool comes in
But maybe not for your use case because you're trying to address individual objects directly
And you'll have to call set owner on all of them
it makes sense. yeah, it's a bunch of chess pieces, they're all part of an array i'm cycling through. just need a way to reset them.
Ahh yeah. Since it's chess you'll need to use an array. Supposedly, manual sync is the best way to do that
I take it the players can pick up the pieces and move them
isn't Respawn plus VRC Object Sync supposed to handle that automatically?
then when they drop, it fires off the move
they're all effectively just physics objects, just default pickups
you actually call vrcobjectpool.return
I'd have to build it myself to test it, but I think you'll have to get gameobjects that you fire from vrcobjectpool.trytospawn
and assign those to the array.
So that you can control those individual pieces
Chess pieces doesn't sound like a use case for an object pool. You have a set amount of pieces, they just need to be returned to their place, you don't really cycle through the same type of object.
You could actually just send a networked event to everyone and make everyone respawn all chess pieces, someone ought to be the owner of it.
no they dont
they're also already spawned at the games beginning and always in a fixed location
so what's better? sending a networked event, or setting the ownership to the user who pressed the button and then calling Respawn?
I personally like to set owner then respawn on the player performing the action
rather than fire it for all players
since object sync handles the respawning for everybody, its a little less network event code
last question... is there any harm in just running set owner brute force, or is there a benefit in checking first to see if the user already owns the object?
I put in conditionals anyway just for safekeeping. But you can brute force it
I'm actually going to write my own pickup/sync script because the proximity slider on vrc pickup only works for desktoppers (its been broken since I started map dev in 2018)
that proximity thing is killing me
I'm going to do it with synced variables though since the motion is a lot smoother
I've never tried doing it to that many objects at once to be honest, but setting owner should be slower. But it might as well work anyway, it's only done once anyway.
But I use graph. I'm not familiar with udon# yet
once I learn the syntax of # which i wanna do cuz graph gets super slow when you have a big program, I'll write it and share it out
The way I'll do it aims to look a lot better as well
I did it with my "duel disc" that I made and everybody thinks its a prop on the avatar itself because its so smooth
This has probably been asked before; when calling Networking SetOwner in a situation where you have an empty root game object container, with other game objects and components inside, Do you set the gameobject target of SetOwner to the root game object container? Does it automatically change/transfer the ownership of all the gameobjects inside?
I'm asking because I'm getting mixed responses back from my debug logs. If I do a query (using networking GetOwner) on all the gameobjects inside the root game object container after doing a Networking SetOwner on the root object, I get back the the ownerships have changed. But the following script interactions with the object behave as if the ownerships have not changed. Additionally, I have another test script on a gameObject inside the root, that has a Event OnOwnershipTransfered check that is not getting triggered in the sub-gameObject when Networking SetOwner occurs, but does get triggered if the Master leaves the world.
setting ownership does not forward/relegate to child objects, you must set the (network) ownership per object of interest, you only need it for objects you want to sync
leaving a world will set ownership of objects owned by the master to the new master (the player who is the longest in the session now)
Does OnDeserialization() not fire for the localplayer if they initiate RequestSerialization()?
correct. OnDeserialization is the event that happens when you receive synced data
OnPreserialization happens when you send synced data
I searched the discord and I guess I need to fire a state event locally after requesting serialization
but neither events happen if you are the only one in the instance
oh really
Ahh ok. I'll make another method that does the same thing as ondeserialization
and call that after I call request serialization
or something like that just for the local player
if the only one in the instance
Personally I often have Ondeserialisation call a method that updates the values, and manually call that method for the local player right after the call to Ondeserialisation
Yeah I finally got it uploaded and none of the networking is functioning. I think I have the wrong concept. I was under the impression that if I changed a variable and requested serialization, said variable would sync ondeserialization. But, do I need to set those variables again in the deserialization method?
In OnDeserialization (so on remote players) the synced variable should already have the new value, but often you need todo something with that value, like update some text or move object or something
I have conditionals in many methods including the update() method for those variables if they're true. But, I think I found bug in my code. I need to sync one more variable.
So anyone know how to guarantee something like start happens before udon's network code takes place? I need to ensure it happens before OnPlayerJoin.
start should always happen before onplayerjoin
hmm...is it different then it used to be? coulda sworn I had issues where code broke because my player list script didnt get a chanced to load up the list before the onplayerjoined fired
does udon inject all scripts via script execution order to ensure their start happens first? or does it run a timer or somthing?
The way I understood your question (and was answered) is that we have Start vs OnPlayerJoined on the same script. OnPlayerJoined doesn't get fired if the object is disabled. So it has to be enabled, which automatically calls Start, and OnPlayerJoined has to be second.
I'm guessing your player list relies on OnPlayerJoined to manage itself as well, and I don't think it's possible to enforce an ordering on that (no idea though).
It is possible for onplayerjoined on one script to happen before the start of another script. That may account for what you're seeing
is VRC_ObjectSync between Quest and PC instances handled based on the object name, or some other identifier? i'm having a hell of a time getting some objects to sync between quest and PC players.
It's based on the network id, which is assigned based on the order of the hierarchy. You need to make sure that both versions have the same hierarchy, and you don't delete any gameobjscts on the quest version. You may delete components, though
got it. okay, so i'll need to resync my PC and android builds.
thanks! i have another networking question if you have a minute.
Yeah
i've been struggling with a script for a while. it's a "reset" button that cycles through an array of chess piece pickups and respawns them.
i can't get it to reliably sync in multiplayer and i'm not sure why.
Don't recombine flow back into one node like that, it'll break stuff
Just get rid of the branch, always take ownership
okay, understood. thanks!
wonder if calling SetOwner on so many pieces in one loop causes the network to chug slowly
a good deal of the pieces just never even seem to respond. the ownership check rarely seemed to work. if it was the way i'd wired two inputs into the Respawn function, i guess that would make sense
I think it's generally not a good idea to call SetOwner many times. Not sure if it might be causing your problem though.
It cancels if you're already owner
And even if you're not owner and you actually do take ownership... No, that's not a big deal
ah okay
Is it possible to clog the network by syncing variables on join? I'm gonna have a lot of data, but data that is infrequently updated, for reference.
Question : I have a script which is supposed to toggle a certain game object globally, This is what I have now, problem is the master can toggle it, but late joiners can't toggle it, how to fix it ?
Hi! I have some code to rotate objects (attached picture) The udon script synchronization method this is set to 'continuous'. I've also tried 'manual'. When I am alone in the world, it works as supposed, but when there are two, the object keeps spinning around, never stopping. I'm currently testing a Windows build. So in short, since it works with one player, but not two, I'm guessing some funny buisness is happening during the networking, any suggestions on how to solve this?
setting the sync mode doesn't magically make the code sync. The only thing it does is sync the variables, and then it's up to you to make code that uses those variables to make sure everyone sees the same thing
But why does it work when there is only one player, but not two?
or rather the question should be: which library am I going to for syncing up the variables across players?
how are you calling this function?
through a regular void Update(){}
oh, is stepcounter a synced variable?
well, I suppose it may not be, since it f's up with two players 🤣 , how do I make it synced?
well no, I mean I think setting it to synced would screw something up. Idk, in general this code is just not designed to be synced
you should be syncing the output of this code, not the input
easiest way to do that would be to throw objectsync on the thing you're rotating, then make sure that you only run this code if you are the owner of that objectsync
*testing that now
well, I suppose I need to do some workings on only have the owner running the code, then I hope it will work. ty for the help 🙂
Is it possible to make HTTPS get requests within vrchat worlds?
no, what are you trying to do?
auth system so only specific people can access
just seemed like a cool idea to work with
Can instantiated objects be synced
What happens if I instantiate a networked object for only some of the clients
From recent discussion, it seems instantiated objects cannot be networked sync. People usually recommend using an object pool if you have a fixed number of maximum objects you can spawn. You can pull some weird stuff otherwise but you'll always need to pre-generate whatever youre syncing
been 2 years and we still don't have custom events with parameters, let alone networked ones. i'm in pain.
employing some tricks to keep my bandwidth down, but it's still way higher than i'd like, and limiting my scale.
U# lets you get around the first one to some degree unless you mean SendCustomEvent*. As for networked, I don't think that would be possible since not everything's state you would pass can be represented as transferrable data over the network nor would it necessarily be efficient. I'd say you could reasonably use an Array of primitive values of the same type and then reference that Array when you call the method
Yes, I’m saying please sweet Jesus let us forge our own packets. I can only foresee trying to get around it with manual serialization and an array going terribly inconsistently if you do it frequently (ex more than once a frame)
But yes, non synced events I’m not that beat up over because it’s not that hard to set a variable to be used as an argument (I do this very liberally in my complex interconnected scripts) but there’s no way to know the current state of the network is correct, so doing the same there is dangerous
unless requestserialization functions as guaranteed in order packet delivery even if you change the value multiple times a frame, which i struggle to trust at face value (and would be difficult to test)
plus requiring ownership just for that kinda blows
You can kinda already make your own packets with a synced string and then parse it on deserialization, although this would be pretty limited in size so using an arbitrary format other than JSON might be good. I do not know if packets are guaranteed to arrive at different times if sent on different network frames, but I do know doing it on the same frame would overwrite the value to be sent. If you needed to increase safety when dealing with state changes on the same frame, you could make a queue system for sending off packets and loop through that with OnPreSerialization to change a value from the queue to, as best as you can, prevent the issue outlined.
I do realize that what I just mentioned is not a perfect system and having baked in support would be much better to not have to deal with jank, but such is programming
Manual synced array variables in udon sharp doesn't fire on variable change(field change callback) is this intended or a bug? I'm using on deserialization for a workaround but it bothers me.
It's known behaviour at least. If you want to trigger it, you'll have to make a new array variable that equals the old one, set the new value inside of it, then set the old one to equal the new one, and that trigger's the callback.
I don't see it changing any time soon. OnVariableChanged indicates that the variable has changed. Canging something inside an array doesn't change the array itself. Equality before and after is still true, so there will be no changed event
Doesn't serializing the array over the network count as making a new one?
At least on the clients not the master of the object
correct, remote clients have to recreate the array when receiving it so they'll trigger a change event even if none of the values in the array changed
You mean like new int[100] and change reference and re serializing it? If it works that's a nice workaround. I'll try it.
I typically do
Int[] newVar = oldArray;
newVar[69] = "Nice";
oldArray = newVar;
RequestSerialization;
so that fires onvariable change to all player including the owner?
Is there any way to send a custom network event to a specific person?
You can send it just to the Owner of an object. Otherwise it needs to go to everyone.
Just wondering, is the instance Id like from GetInstanceID on a game object going to be the same for everyone, or is it unique locally? Also if it is unique locally, is there a way to identify a paticular udonBehavior by id over the network?
No, GetInstanceIDs are unique ids that can change for a number of reasons and should not be relied on for this afaik. Can you tell me more about what problem you’re trying to solve by identifying an UdonBehaviour over the network?
so i have a class which im using for worldData. Im using it to have an id-byte[] data pair. This is how i store item data when they are in a players inventory or a chest. What im trying to do is when an item gets put into the inventory, i tell the master of the world to store a new item, then the master passes back the id. The problem is I wont know where a given non player inventory is in the scene, and i need a way to tell that spesific game object that the data is ready
im currently registering the inventorys with the world data so i have references to them, but im trying to figure a good way to order them so i have an id which is consistent for all players so i know which inventory im referencing
i was trying to avoid assigning a synced value to designate which number it is
also the world data needs to work with more then inventory, because its working as kinda a generic data for everything not assigned to a player later
I’m not yet understanding the field type(s) that are storing the references, can you break that down for me?
ill try
world_data contains a double byte array, so a worldID represents which data im talking about, and the byte[] inside contains the data
I use this to store item data in the form of a byte[] so i can have the information while the item no longer exists in the world
everything i use which needs to store information into world_data registers itself, which basicly adds them to a "udonbehavior" array, more of a gameObject array that i convert to udon behavior
im realizing as i explain this, the need and reason is going to take a lot
the system as a whole works solely around the need i had for player data and method calls with data. And i made it in such a way that i can piecemeal what functionality i want by putting prefabs i made as a child of the main script
playerinventory is one of those scripts, which chest inventory or other types of world inventory dont, they piggy back off other scripts so a player isnt restricted to putting their chests as a child of this script
when you put an item into inventory, it registers that items data with the world data, but has to send that to the master to set the realitive synced data, then kicks back the id of the newly set item data to where it needs to go
for player inventory thats simple, but for all the other inventory its not
Is “double byte array” like byte[][]?
ya
that isnt synced, i have another way to sync that data
cuz far as i know byte[][] isnt syncable yet
if it is that solves one headache, but i already solved that problem
so ya, essentially all inventory have a reference to world data, but world data doesnt have a reference to them without registering it, and i need some way to break down a gameobject reference into somthing i can sync
preferably into a byte[]
Haha reading through your response yeah, it may be a bit much for me to grok the system in some text over chat.
But I see your dilemma
i could have every inventory have a required synced value that gets assigned by the owner
but that can make it a lil messy, plus thats more synced values
I shudder to say it, but you can make sure every item has a unique name and then do gameobject.find?
and since the order of item starts isnt exactlly preditictable without changing the project settings, i cant rely on building up the gameobject reference via registering it
If that’s even exposed
it is, but thats not an option
because i need to let players make their own chests and stuff as they please
and if they label two chests the same then itll break
i thought there was a unique network id per udon behavior
You can enforce a unique name internally, though right?
Yes, every synced behavior has a unique network id
whats the way to access it? cuz i could just use that
sort it by network id
then everyone has all registered inventorys sorted the same
Not sure if it’s exposed, I’ll need to look at the properties
gotcha
i know there was a time where people were setting that id
was around when people were trying to solve the VRCInstantiate issue via network, but it was a jank fix
Well, shoot. Looking at the source vs the exposure tree, I don’t see the thing you want exposed anywhere.
i had an idea, il make an id using a combination of its transform and current name
if someone is making two world inventories of the same name at the exact some position, thatd cause more issues then their world data being outta wack
True
Despite what I think is very little data being sent, some of my networking code is still suffering from network clogs and its causing issues in my game. :/ can network clogs happen even if udon is sending very little data and its other things like avatar data, voice and movement stuff using up the bandwidth?
I've got a voice system that uses cyan object pool to assign objects to players. Then that object stores a single value indicating the team the player is on.
Then when a control system engages game mode, everyone's clients uses the team numbers to set who can hear who and how loud.
So its a single value and then a single boolean bit, but somehow this data isn't always making it.
clogged data will eventually be resolved and data should be sent still
are you verifying you encounter a clogged network by properly logging this?
otherwise i would assume a logic bug
Well, it's tricky to monitor while in world. We also have points where many people freeze at once and it kills their clients. I'm not sure if that's a world bug or a many avatars at once bug or what though.
sounds more like oversyncing
well, its also been happening when well, nothing has been happening? And like without warning either. You'd expect it to happen when well.. various game events happen but its not. I don't have any actions that take place on timers or without a user doing something
Had a log from one crashed player but it seems to indicate they just lost server connection and VRC hung instead of displaying a warning
So none of this may be my fault which is good but.. annoying XD
Are you using continuous sync for the team?
Manual
Then I will echo the logic bug theory. (sorry, that's all I can think of)
Fair enough, I'll keep monitoring things and see how stuff goes.
has something broken the test environment for syncing values? I'm doing build & test, I get a successful post serialization event on the user requesting serialization, but no OnDeserialization event is firing for the other user
nm its happening in live too, im gonna keep poking around my code and make sure i didnt do somthing wrong. Its really strange because its not throwing an error, its just not seralizing
seems when you change data type drasticly, like int to byte[] that are synced, it really messes up the whole object, and I have to reset the object. Thats what stopped it from syncing
In my logs, I can see ownership transfers for objects that use SyncMode None. I thought None means no networking at all, or have I been assuming wrong all this time?
Objects still have ownership I think, but they won't ever send network events or sync data.
Is this for items like Pickups?
No, it's not a pickup. But I've noticed that they don't appear in the list (using debug menu in game). So that works correctly I guess. It's only in the logs when a master leaves. Basically stuff like this:
[Network Processing] Transferred ownership of X to Y
Even though X is marked as None
Thanks for the additional info! There's some lower-level code that may not have been updated when we introduced NoneSync that might still be tracking ownership of those items.
I am a bit confused on how to get SetVoiceGain to boost audio of a player who simply pressed the interact button and how to make it sound for other players or how the netcode even interprets the players audio. I took a look at the player audio api documentation and it really doesn't answer any of my questions.
In the pic above I have a get local player and a vrcplayer api variable though I am not sure which instance to reference as the documentation just says "With Udon, you can change how a Player hears other players' voices and avatar sounds. For example, this graph makes it easier to hear another specific Player, boosting their audio by 5 decibels:" How do I specifically say to reference the player who clicked the button so everyone else can hear it?
Do I need to use the event OnDecerialization? How does vrchat logically send audio data to everyone else normally? How does udon interpret that? Do I need to set the script so that it assumes the "listener" that gets the "set voice gain" is the one being effected even if the person who interacts with it is the local player? if so how do I specificly for everyone else to get the local player that clicked the button to begin with?
I have also tried using send custom network event set to (all) to no avail
I have also tried get owner set to a const this
If you want to change the voice value of a particular user for everyone else, you'll need to use a For loop to go through each Player and change the value of the target player.
Ahhh
Ok that is one of my weakest links which are for loops and arrays. I will look into reformating it that way
if you only want to change one player, you don't necessarily need a for loop. You just need some way of identifying that one player
because you need the other players to set the voice gain of that one player
voice settings affect your own perception of other players, so changing the local player does nothing
the easiest way would be to take ownership and then set a synced variable which indicates what setting you want. Then when people receive ondeserialization, they just set the voice of the owner
That variable being a float?
if you want the synced variable to drive the gain directly, sure. Up to you
Well at least I have a direct answer on how vrchat handles audio.
Something like this?
Ownership volume is synced as well
or the checkmark is
you're on the right track. But you need to set the variable to do anything
I would also recommend setting this to manual sync, in which case that would also require adding RequestSerialization
it is on manual unless the variable changes per frame
then you'll need requestserialization
I don't know what that is, is that in the documentation?
nvm I found it in the documentation
Ya I don't know how request serialization works even after reading the docs
It takes into account onpre-serialization which is an event, do I set the synced variable to pre-ser then request serilization after?
Like this?
of coarse with a float value
RequestSerialization is like hitting the 'send' button after you've updated synced variables on a Manually-synced UdonBehaviour
Fixed the logic
To use it:
- Make sure your UdonBehaviour is set to "Manual" sync in the inspector
- Have the Owner of an UdonBehaviour change the value of a synced variable
- Run RequestSerialization on that UdonBehaviour
Wait by saying "on that UdonBehaviour" are we referring to multiple scripts?
The UdonExampleScene has a number of working examples of Manual variable sync working using OnVariableChange, which is an easier way to change variables for everyone: https://docs.vrchat.com/docs/udon-example-scene#udon-variable-sync
No, I'm just referring to the one program.
Navigate to Assets/VRCSDK/Plugins/, select VRCSDK3.dll and VRCSDK3-Editor.dll, then right-click and choose "Reimport"
I have a text object that i wanna display the winner of a game to all players on. When a player reaches a certain score it triggers this winnerField.text = "Winner:" +Networking.LocalPlayer.displayName.ToString(); to set their name in the first winnerfield then I set winnerName to winnerField winnerName.text = winnerField.text; and assumed since winnerName is udonsynced that it would change... perhaps im vastly misunderstanding what I should be doing here
The text for winnerName becomes the text for winnerField but ONLY the words typed on the actual text object... it doesn't say the players name like intended. just my testing text twice.
are you trying to concatenate?
I am just trying to display whats on the right, but for everyone. Idk if combining is correct, but syncing the text between all users?
I am assuming the host is on the right?
Also have you properly synced your variables?
probably not...
the text is set by whoever reaches a certain score first and just sets their displayname
Ya that would be the first thing I would try then to make some logic that (if manual uses RequestSerialization) and if continous mode is on, to use Ondeserilization.
i wanna get that to display for everyone. I thought initially all i had to do was make that text udonsynced
There are many ways to sync in udon.
Variables, objects, on change, mode syncing
You want to make sure that the string is synced in some way, usually through a variable and that the owner of the object changes some logic then serializes it to everyone else
Who has ever seen the function OnDeserialization is completely dead even RequestSerialization is called?
Well, it happens to me, and i still have not found why it's dead.
There are no errors, most part works, at local side, but remoted not.
Ah i found the problem. Unprepared synced arrays will cause sync system crash.
^^ we ended up doing some more testing
Seems like having any null element in an array causes serialization to fail
which, if you don't initialize it in start but for example define an array like
[UdonSynced] private string[] serializedStringArray = new string[10];
is pretty easy to get accidentally (as its not serialised by the inspector either)
is that a known bug? because imo it shouldn't fail here
Does the UdonSynced modifier plus private field actually work?
I feel like those 2 modifiers should be mutually exclusive
I'm trying to implement a game that generates voxels at runtime. Since udonsharp doesn't support 3d arrays I use a 1d array of bool and some fancy math's. Now most of the code executes on master which send integer arrays to everyone else. integers less than the voxel array length represents true and those larger than that but less than 2 * the voxelArray length represent false. The integer number itself is the position in the array. This works pretty well. The trouble I have is when a player interacts with an object that player becomes the owner and that code needs to execute on their machine. Now I need to send an array of int from that player to everyone else. Having that player call a function on master and giving it some kind of parameter such as an array or integer would be super but udon sharp can only call functions without parameters as far as I know. So that leaves me with sync variables which is bit tricky as there are many players and many guns. Giving each player or each gun a udonsync variable and having the master loop through those looking for changes seems like a rather clunky solution that may kill the network. I only care that the data is send not whom send it as it all gets combined the same. If anyone has ideas or useful code that be great.
What do you mean udonsharp doesn't support 3d arrays? My Tetris game in EvolvedAnt Arcade uses a multi-dimensional array that is 3 levels deep.
@pearl ocean
You already have the master sending the data to everyone else during sync. Why is that suddenly a problem when someone else interacts and takes ownership? They'd be the new master, and can now send the data the same as the last owner was sending it.
You even have an event handler if needed that lets everyone know ownership has changed.
it supports jagged arrays, not multidimensional arrays
I thought the difference was just the syntax of how it is created, and that one can be differently sized.
He said udonsharp doesn't support 3d arrays, is jagged arrays that are 3 or more levels deep not 3d?
A quick google search shows that yes, jagged arrays can be made 3d by having at least 3 subscripts, which my jagged array has.
Ok I re-read your problem and I understand better.
Yeah, having a ton of guns syncing, that the master has to look through and do stuff with might be too much. But make sure you try it first and benchmark/test to confirm it really is a problem.
Sure the solution is clunky, however we do not currently have support for syncing only to one person beyond through network events to owner without data.
I can't really think of any way to avoid that, except maybe to mitigate the issue by performance testing and finding how many guns you can get away with, and just lowering the player limit cap for your world to compensate.
Thanks for getting back to me the issue with jagged arrays is that you need to predefined them like the screenshot there. Which is fine for smallish arrays. That becomes very bulky very quickly. Currently I'm working at 10 x 10 x 10 for testing. I'll up it till it fits my world. Which just makes maths applied to a 1d array easier. As for the main problem I was afraid that may be the case. For this project I may be able to sidestep much of the problem with a few design changes. Not having any of the guns fire except the handgun when a player picks them up. That way I'll just need to deal with a few of these arrays needing be send over the network.
Hey, so I'm quite new to networking -- I have a world that has midi and triggers a particle burst with U#. I have it set to along with the burst send an event to all that plays the burst. It communicates the midi information via a synced triple. It lags behind a /lot/ on the client. How should I be going about this? Is there a "right way" to sync these midi events?
Events tend to become desynced from information. You gona need to check for a change in the information and use that to trigger the event. You can use callbacks or just check for a change every update.
I was considering doing something along the lines of having an array that stores midi notes, and if the networked array differs from the local array generate the animation - is that a reasonable way to go about it, you think?
How can I effectively test this, btw? Without needing another person?
Build & Test with 2 clients
You can get a quicker response by using Manual sync if it's currently sent to continuous. However, the people who didn't trigger the event will always have some delay based on networking factors.
That's unavoidable. Networks are slow and messy. If you use manual sync you'll want to call requestserialization when ever you want sent something.
It may be due to my failure to request serialisation after the event is called, I'll have to look in more detail. Is there some way to make one of the clients not receive MIDI input? Since they're both on the local machine, it seems both are receiving the input
Hmm, what I'm experiencing is beyond network latency, like something like 80% of the notes are dropping, so it's something I've done wrong.
I suppose unless the network is updating very quickly my current method of waiting for update to trigger particles is unfeasible, since it's likely a person is playing 5 or more midi notes "simultaneously" -- I'll probably have to store them in some sort of array or something. Does anyone know of a way this is done standard? Or am I going to be doing this from scratch basically? XD
Generally there is no default way to send it to only specific clients. So you'll have to check for that and then discard . This can become tricky. Arrays are not too difficult to use. Just a lot of looping. And if you gona share them over the network try and keep them small. What you can also do is use the first space in the array to indicate who you sending this to. So everyone checks if it's for them and if it is reads the rest of the info.
Yeah, I just need to do it more intelligently with an array - I was hoping the events would be received quickly enough that just transmitting a triple would be sufficient but it seems not
I'd love if you could call a function over the network and give it some parameters and maybe even indicate which player specifically. But there isn't.
I believe the way one sends user specific events to a users is have a behavior that sends an event to the owner, and set the owner of that object to whoever you want to get the event before you send it.
Is there a way we can do that with different usernames? IE: If i have a behaviour thats username based to test it is working for one user and not triggering for another
without uploading and getting friends in, ofc.
Build & Test uses the same username for both. You can launch clients with different profiles instead if you want to log in as two separate users
VRChat.exe --profile=1
Hmmm, ok i may give that a try. Ty.
so I have an ownership question. I think objects claim ownership when you pick it up, but im not sure the timing of it. I currently check if I own an object on the pickup event and if i dont I claim ownership, which on pick up it will claim ownership because it says I dont own it. I need to ensure ownership because I set values on pickup that need to be synced. However, I still get the warning that im claiming ownership when I already own the object. Is it in process of claiming ownership and throws an error on the network side?
its a warning, so its not breaking the program, but I'd like to minimize warnings
If you don't want to get a warning can you not just check if you own it already, and if you don't then transfer ownership?
as established in my statment, i do check, and it says i dont own it, so i claim it and get the warning
Oh sorry missed that part.
You could put your logic into the ownership trasnfered event, which will always happen after the pickup and ownership transfer has occured. But that would fire for everyone and I think pickup is local?
this doesnt occur if you already own the object
so i dont need the information to fire spesificly when you claim the object, i need it to happen every time the object is picked up
Ah ok. I've done a couple of things that work on pickup and have just depending on them doing then ownership transfer themself and it's worked fine so far.
it works fine, it just throws errors
How do I graph up a slider so multiple clients can steal control from each other? For instance, if I'm controlling some property everyone can see, I'd like someone else to be able to click the canvas and also interact with it, such that all users can see the input.
I only have this working one way, whereby one player can globally affect values, and every non-owner can only locally affect values. I would like this process to be more symmetric. Here is what I've got so far. The control panel changes a variable insider a shader. I might add logic for a timer later on (must not interact with panel for X seconds before ownership transfer is allowed) but I'm not that far yet.
All you should have to do is when a user interacts with it, set them as the owner of the object and then they can update it for everyone.
OK. I just got spam-blocked by posting a picture of the solution + a lengthy description. did not expect discord to delete that, so I won't explain it again.
I did that. won't explain. it just works. neat.
I don't understand why (float) Change works and not OnDeserialization but I think it is linked to the whole "sendChange" bool in sliderValue.Set()
But yeah thanks for the suggestion! that part of it got inserted so it worked well. I included that in the paragraph or two that got deleted without warning
can you call private methods over the network?
no, you cannot
Okay. Just trying to see what I can do to combat client users in my world, so thanks
if you need it to be public, you can also add an underscore to the beginning of the name and that will prevent it from being called over the network
I need to be able to tell the owner of the gameobject to run a method and then send back data to clients
vs transferring ownership every time someone wants to interact
Hi! New to udon networking here.
When an owner performs RequestSerialization(), are all udonsync variables automatically synced for all other players upon OnDeserialization() ?
so RequestSerialization() only works if its an udon graph/behaviour that has its sync set to manuel
and it causes all variables marked as synced on the udon graph/behaviour to send to all other clients
on those other clients it will call OnDeserialization() after the variables have been updated
(note OnDeserialization() will not fire for the owner itzelf)
Thank you!! Will I need OnDeserialization() if all I want is for everyone's variables to be in sync?
no really, OnDeserialization() is needed if you want to run some code right after the variable updated, for example update some text or something
oo got it! Thanks so much
Is it better to do a claim ownership while the network is not clogged, or should you do it at any givin time since itll work itself out?
also is it better to space out ownership for a lot of items, or do it all in one big batch?
Is it possible to save player info for next time they join?
udon has no persistence on its own yet
there are ways around this that are all quite hacky
serialising state into a password the user copies and pastes
using avatar parameters, which require the user to switch avatars, data will then be serialised into the parameters
and once videoplayers, but these are now barely useful since vrcurls cannot be constructed at run/play time
or do you want to keep data for one instance? that's a lot easier
So I'm looking to resolve the issue of lag when two people are 'buzzing in' as part of a quiz game world.
I've looked at the function Networking.GetServerTimeInMilliseconds() that I can see provides the local user with a timestamp. I'm wondering who the 'server' is in this case (the VRC world host box?)
Would I be right in thinking I'd want to have something along the lines of:
Player pressing their 'buzzer' and I call the above function and RequestSerialization().
Then whoever is the question-master player would on Deserialization, record the request and maybe say, wait up between 0.5 and 0.75 seconds before assuming no second buzz was coming.
However, if during that time, it got a second ping from the other player's buzzer, it would compare the two times and award the successful 'buzz in' to the player with the lowest server time value?
The question-master would then sending out a network event to all players to light up the true first place person's podium, play a SFX, etc?
isn't deserialization based on network ticks? you can get all the requests in a single serialization, but unless each player tracks and reports the time on their own local instance you won't have any way to know who buzzed in first
Well, I'm wanting to know what that 'GetServerTimeInMilliseconds' actually returns. Is it local time, instance owner time? VRC host server time? Something else? I'd hope it was one of the latter two because one needs shared time reference so then when players report their times, we don't need to worry about who's network traffic actually arrived first.
No idea what the value actually is, but I'm pretty sure it's the same on all clients. For your use case, it should be fine.
the server time on which the instance is hosted
Okay, cool. So I can use this then as an authoritive timestamp to know who actually buzzed first.
well maybe
after all you have lag to this too
it's a network call in the end
you will have to see if it helps
It seems like it's much faster. Though I'd need something to artificially limit my bandwidth to test that
So I been trying to create an button that only the master can push I seem I can’t figure it out or I am overthinking it. Is there documentation for this?
use Networking.LocalPlayer.ismaster to check if you are master
if no, just disable the gameobject is the easiest
or grey it out etc
I knew I was overthinking it. I was trying to use interact>sendcustomevent and trying to figure out how to change the instance
yeah, if you are trying to intercept in the interact, then you can use that function to check too, although you should disable the button since other people will be able to press it but do nothing
Whenever you call VRCStation.UseStation(RemotePlayerReference), does that network properly or does the Network owner of the VRCStation need to call UseStation
Anyone know why Udon would fail to serialize a Manual udonbehaviour after RequestSerialization() is invoked? I've got the following code:
In the logs, I see "REQUEST: Resetting for new game" on the client side.
And then on the master/server side, I see "Resetting for new game" followed by "Requested serialization"
I never see any of the TEST messages after the initial scene load-in has completed.
So, it seems like OnDeserialization(), OnPreSerialization(), and OnPostSerialization() just aren't getting invoked, and I can't for the life of me figure out why.
how did you declare the synced 'State' variable?
might also be a logic error....not sure why the players would send the reset request when the game master/owner already would have, but idk anything other than what u showed here
[SerializeField, HideInInspector] int State;
ResetForNewGame() is called by any player interacting with a button. The _Actual method is called nowhere else.
huh...unless that's some hidden feature, u have to use [UdonSynced] / [UdonSynced(UdonSyncMode)]
Ohh, of course that's what it is. I come from Unity development, so I used Unity's SerializeField instead of UdonSynced. Dumb mistake. Thank you!
what's the max bytes for continues sync?
It's variable. You'll want to check for isClogged instead to monitor for this and pull back if you're sending too much
https://docs.vrchat.com/docs/network-components#networking-properties
This doc covers Networking Components, Properties and Events you can use in your Udon Programs. Special properties you can get from Networking: IsClogged - returns true if there is too much data trying to get out. You can use this to hold off some operations or adjust your logic. IsInstanceOwner - r...
well, the total output per second is variable but strictly speaking the exact byte limit for continuous is somewhere around 200 bytes
Currently, yes - but it's not guaranteed to stay at this rate.
sure, in terms of development that's something that is not a fixed, guaranteed amount. Though it certainly doesn't change at runtime
but lowering it would break things and make people mad 😅
true and true 😄
using Udon#, is there a way to send custom events containing variables instead of syncing variables?
I need to push a struct of multiple variables on an interaction.
These events can happen anywhere from a few times a second to once a minute.
They are not delay-sensitive, so if 10 events happen in 1 second I would be okay with receiving them over the next 10 seconds on the client's end,
but they are order-sensitive, so these 10 events would definitely need to come in in the same order as they were fired.
Otherwise the very unclean but working solution would be to create an array of let's say 10 of these structs, sync that array, and always change the "next" element in the array instead of firing an event, while detecting changes to the array on the client. This would be awfully unclean and ugly though, since it'd only permit <arrayLength> events per <timeBetweenSyncs>.
Yup, as far as I know, your example described is the only way to do it.
do the changes need to be remembered?
no. Like normal events, they should be forgotten as soon as they have been received and used by listening clients.
in what sense are the events order dependant?
thanks for the info^^
it's a little disappointing; sending an event with a generalized struct or tuple seems pretty useful in a lot of cases.
I might make a suggestion on the board later
they have to be received be non-owners in the same order as they have been fired by the owner. I "could" force this by transmitting a "eventIndex" byte or something along with the data, but that'd be even more data to be synced.
and why dont u use the index of the array for this?
to give this context, I don't like any single piano that currently exists in VRC. All of them have severe networking issues, and I want to work around the functionality of udon to create a network buffer queue on the receiving end.
The method I described in the post does work already (though I don't send the entire array, I construct the array on each client to minimize the data being transfered), I just wondered whether there's a simple way of firing events with values or value tuples, which would make everything a lot better.
with events you cant make sure thay arrive in the same order
using manual sync on the variables, I currently do have them arrive in the correct order.
worst-case-scenario I give each event(struct), should such a thing exist, its own ID to make sure they're dealt with in the correct order. But again, more data equals more bad.
Not sure what you're expecting.... Network events with parameters would certainly be nice but as has been said before, it wouldn't be appropriate to your use case where the strict timing is very important anyway. And in addition, network events (especially if they contained parameters) aren't free. If you're sending the same data between Manual sync and network events, it all still needs to be sent. If anything, network events would be more expensive because they include a string.
Manual sync can send quite a lot of data very quickly before it starts running into limitations, should be plenty for this. You just need to make an event buffer made out of arrays. I would probably include a relative timestamp as well for accurate playback speed.
I would build it so that as you're playing, there's a running buffer keeping track of all notes. every time you play a note, it slots into the buffer and calls requestserialization, then when the onpreserialization comes around you dump everything from active playing buffer into an array that can be sent out.
a relative timestamp is exactly what I'm using right now.
As a host-side buffer I use the "array" of structs that are set, request sync, and are forgotten.
I just only keep a real live buffer, including the time since the last note, and information about what has been sent, on client side.
So is there something about that that's not sufficient?
That's the thing: it """works""", but I don't like it. I'd much rather have an "official" way that doing something as hacky as this.
I always like to make a visual blueprint for what I'm trying to do beforehand, and usually things stay simple.
For such a simple thing, I usually don't want to end up with... something like this xd
Also I may need to make things even less readable, since sending the entire array, or all structs every time only one is updated seems like a huge waste.
Since requestserialization serializes all synced variables on the same object, I may need to look into instantiating empty container objects at the start that each only hold one NoteEvent struct...
This sounds horrible in my head, but I suppose it may be needed if I want to increase the """polling""" rate of this script
I don't see how this is hacky. Maybe at most, it would be better to work with lists instead of arrays, or tuples instead of separate arrays. But I wouldn't expect tuple arrays to sync anyway. And if vrchat built an official script for every possible thing anybody wanted to do there would be 100s of scripts. You are given pretty low level access to networking, you can build your own protocols and strategies, it's up to you how you want to build it. That's not hacky, that's just powerful
"for every possible thing" is a bit extreme, <T> network events are something pretty basic in my book. But I guess that's where everyone draws teir line in a different place.
If we all just wanted the most "powerful" ways to interact with the lowest levels, we'd all be clanking down zeroes and ones xd
Again, network events with parameters would be amazing but they wouldn't match your use case where precise timing matters anyway
precise timing doesn't matter at all, only precise order
???? It's a piano. The time between notes matters
And manual sync is faster than network events anyway, don't you want a shorter delay?
yes, but not the time between events.
As you said earlier, the event struct itself keeps track of how long ago the last note was^^
that plus the buffer makes the time between events being received completely irrelevant
You keep using terms like struct and tuple which are not relevant here as udon doesn't support them and network events certainly wouldn't either
I don't have a better word for it. A collection of variables that are updated, and synced, but only taken as a complete set of data as soon as a special value in that set is changed.
and again, it all somehow works, I just went here to ask whether there's a simpler way to do all this
just need to fix some crashes on edge cases, which again would have been easier if such events existed.
I might look into making something like that myself in a less hacky or at least more rounded-off way then, so that I really don't need to worry about it in the main code of whatever functionality I'm giving to an object. Keeping SOLID alive and all that gibber-gabber
HELLO
yes hi
Im stuck in a pickle
Can I get a hand
I have a problem that I don’t know what I have a world with a button that will play a sound and warp effect but when you press it again the warp toggles of but how do you make it’s so when you press it once it plays one audio and then press it again it’s another sound
just to make sure, is this the right code for me to be able to sync a position and rotation?
I don’t know how to do codes
you can just add the object sync component if you want that to be synced
Strangely, just adding object sync doesn't work. If I do that, the object gets all messed up. It's a model that follows a set path on a set speed, but by adding an object sync component, it becomes slower
that's just how object sync happens to work
your code won't work in manual sync if you use that, as continous sync only updates 4 times per second
You are doing a NavMesh agent running from one point to another, right? In that case you could also use manual sync to send the target position and the start time as soon as the owner of that AI make it move. Then on the other clients, you use that to calculate the current position for the delay, teleport the AI, and then set the target position again.
no, no agent, no ai, just an object following a path
Ahh, but it's the same concept tbh. Depends on your setup, just send the required data like start or end position for the next movement command, then reconstruct on the other clients.
full code looks like this, its really simple
No need to consistently update the position.
Is that manual or continuous sync?
right now its set to continous i think
Yeah, that would be correct then.
The only problem with your code though, you are setting the NewPos on each client, thus overwriting any NewPos you are receiving from the owner.
Only set it for the owner.
how do i do that
There are a few methods for that under the Networking namespace.
Like Networking.IsOwner()
Also, the rest of the code is a bit sus. You are not even using NewPos.
The non owner shouldn't patrol along the transforms with your setup, they should just use the received position to place them in the world.
I'd recommend switching to manual sync. Then sync "current" and the start time of when it switched to that current value. Then when the non owners receives "current" and "startTime", they can calculate the position based on that.
No problem. I just had another idea if you want keep it dead simple. Just use VRCObjectSync, but make sure to only do the update logic on the owner. This way, the owner will move the object and everyone else will display the position correctly without any stutter.
Highly unoptimized though.
Will keep in mind. Currently watching a networking tutorial bc right now, I don't understand d that much about it
the owner is automatically the room master right?
By default it's the master, yes.
since i am a total noob to c# this is pretty hard. this is what i came up with but it still feels wrong
it works, somewhat. for the owner, its butter smooth, for the non owners, it now has the right speed, but is still laggy. i feel like your idea with syncing current and start time is good, but i have no idea how to implement it
For your current method to work better, you need to interpolate the movement in OnDeserialization, not just set it.
and how do i do that
I'd recommend Vector3.SmoothDamp for it
But honestly, you could just remove the NewPos and NewRot from your script entirely.
Use VRCObjectSync instead
Since it does that for you.
what confuses me with VRCObjectSync is that it doesnt appear as a thing in visual studio.
this all goes way over my head being used only to vex and a little bit of python, c# is just confusing.
You don't need to code with it for your use case. Just add that component and remove the NewPos and NewRot lines.
If you want to use VRCObjectSync in the future: Press Ctrl + dot after writing that name and it will suggest you namespaces you might be missing.
Oh, you mean the component. Strangely, it doesn't work. If I add it, the speed is all fucked
Did you already try it out? I did read your comment about using it, but you didn't check for owner during that.
And yeah, it's probably rough. I think C# is easy, but wrapping your head around Udon specifically is hard and especially networking is its own beast.
Exactly.
I think you messed up the object sync component by setting the position on the non owners before. You know, it tries to position that object just like the owner, but then in code you adjust it again to a completely different position, so it jitters and switches between positions.
Only setting position for the owner should solve that.
i ll try
nope, its still weird. in my code before, the speed was ok, but it was laggy, now, it isnt laggy, but it takes almost twice as long to reach the destination
Let me try this out myself real quick, maybe I made a mistake somewhere.
Seems to work.
I didn't use a rigidbody though:
Currently on a walk with my dog, will try when I'm back home. If it works for you it should work for me too
your approach works just fine
Can anyone show me an example photo how to update events for late joiners using Udon Graph please 🙏 😔 very desperately need help
So this took me longer than it should have.
Time to toggle objects again, but this time, for everyone! You'll see that syncing is a little bit more complicated than it was in SDK2, so to set everything up we have to tell every player to toggle that object, but also catch up anyone who joins in after the button was pressed!
All assets are availab...
So, Say i have a have a UdonBehavior Owned by player A, on that behavior it has a refrence to a different UdonBehaviour on a different object and it calls
theOtherBehavior.SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.Owner, eventName);
That should call the event for the owner of the other object, player B, and not the owner of the calling object right?
I'm still so new to Udon Graph without a visual example its just words to me. Im very sorry I dont mean to waste your time. You have been so polite to try and help me.
The text wasnt for you, that was an unrelated question XD
Just watch the video
My bad 😬 😵 😓
Yes, the owner of theOtherBehavior (player B) will receive that event. You are executing the code in the first object, but the actual function itself runs on the second objects.
i got help here a few days ago with this code, it works in combination with the VRCObjectSync and works good in game. however, i have a really really strong pc (ryzen 3800x, 128gb ram, 3090) and when im room master, it kills 20 to even 30 fps imediatley. it doesnt do that, when the ObjectSync is disabled and i think that for people with not as good pcs as me, it might make this world impossible to use. can anyone help me on how to network this script more efficiently with not sending new data every frame
i guess it makes an object follow a path
any code run in update() runs every frame, so its good way to kill framerate indeed
a quick and dirty performance boost would be to not run this every frame by doing something like
private long thickcount;
void update()
{
if (++thickcount % 100 != 0) return;
...
}
im bad with code, what exactly does it do?
Just only run that code every 100 updates (or frames)
yeah but then it wont look good for other people or would it? if i only send transform data to them every 100 updates, wont it lag? the actual movement code isnt the problem, but the networking is
So the udon behaviour is set to continuous sync, thus means your client will send an update 4 times a second only, any positions in between will be approximated using lerping, lerping is a whole technique in itzelf that I cant explain, but basicly its build into vrchat
so i basically put the whole code i have in void update now, inside the
"if (++thickcount % 100 != 0) return;" function?
Just add the
If (++thickcount % 100 != 0) return;
As the first line in your update function
yeah, so that everything else is affected by it righr?
And put private long thickcount; below the public int currentIndex
notfadeaway