#udon-networking
1 messages Β· Page 1 of 1 (latest)
they array order is different
trying to understand how to avoid this without a solution yet
nvm there are still some sync problems, someone can help me? i'm trying to do an Area (with a box collider) where people walks in and they are counted, and when someone press the button Start, it should teleport everyone on different locations, but somehow I can't really get the right syncing for this thing
You can use an object pool belonging to one person and have it be linked to the transforms of the teleport targets
I would use CyanObjectPool
how does it work? in the end I got a situation where if NOT the owner press the button, everyone get teleported to the right spot
if the owner press the button
only he get teleported
and no one else
π©
I did this, and the count actually work (it is continuous)
well prob i'm a bit tired too
what's the current best workaround for passing parameters via networked events? I've heard a few methods, but no examples/docs/etc, so anything along those lines would be much appreciated!
using U# btw
Just pass the parameters and have actions fire when the parameter is updated in the deserialisation event?
not sure what you mean. Networked events don't let you "just pass the parameters"? And as far as I know, you can only serialize variables if you're the owner of that object, and what I'm needing would need things to update regardless of who triggers it. For reference, I'm currently trying to maintain a list of all players (via ID) within certain bounds, and update all players when one leaves or enters that area.
Ah. I'd maybe use Cyan's Player Object Pool prefab, it can maybe help you do what you need
You have an object that's given to each player by the prefab on join and taken back on leave. You create a single 'template' object which the Unity script will copy and create a version of for all possible players.
It then has a script to 'hand these out' to players on join and take them back on leave.
On the object, you can put whatever scripts you want, such as one to handle sending this event you need.
And you can now know based on the object, what player sent the event.
So Player A enters the area and fires a network 'I've entered!' alert.
It also pings your 'management' object that's say, updating a list of players in the space.
But the management object checks first to see if its the owner and ignores it if its not.
But the owner goes 'oh, okay', updates its list parameter, and that parameter can then sync.
okay yeah, that seems like it should handle my use case, I'll look into it, thanks!
Good luck! Its a little tricky to get your head around but once you do it can solve a lot of these issues,
I have a few different areas where such a trigger would be, as well as similar triggers (gauging how many players are looking at a specific object), so hoping it can handle those use cases as well. Networking has been hell so far lol...
You kind of want to create a system where the player objects are shouting what they are up to and only the player who happens to act as the owner of a 'management' object keeps track of the state and syncs that out to the other players as parameter updates.
This would let you smooth out things as well, so if I player steps back and forth a few times over a boundary, you could hold off updating everyone's counters or such until the changes stop coming.
yeah, I had looked into doing just such a thing, sorta like a debounce. is that possible in udon? Like, defer execution until time between events exceed a given threshold?
The thing you have to remember (and I often forget until I remind myself) is you're in a game loop. So the best way to do that sort of thing is to start a timer which waits so many frames and then fires the second half of the logic in the Update event.
I have a quiz module I'm working on and people buzz in. When I get a buzz in signal, I check we aren't already in a waiting state (so I ignore additional button presses) and then I record it and set a bool to true and frame timer to 0.
Each frame then in the Update event, if bool is true and frame timer is < wait time, I just increase the timer by one.
Once I hit a target, the Update event sets the bool back to false so it doesn't keep going. Then fires a function to perform the follow up code where I see if both players buzzed in and if so, compare their sending timestamps to see who actually buzzed first, not which signal arrived first.
Each performance tip though. If you have something like that which is going to use the 'Update' event every frame, see if you can put its code in a secondary script and object that you only turn on during the timer phase, and turn back off when the timer is complete. That way its not firing an extra Update function to just check a bool that most of the time will be false until you're performing a check.
yeah I've ran my own timers for similar, just making sure I wasn't missing something built in. and thanks for all the help so far!
is it possible to make an event play locally for every player?
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...
would that work for a loop that changes an objects position each time?
because with my current setup, its only able to send 1 position change a second over the network, so id rather just have everyone locally see the loop themselves, then after it stops have it sync to the same position for everyone
Sure - you can use the event to trigger a method for each player, which will run locally. The timing on the sync at the end is tricky, though - once you send that sync update, it could fire at different times for people depending on how long it took them to get the first message.
thats fine, id rather have the animation end a little early than have people only see 2 frames of it lol
how do i trigger a method for each player locally?
ty!
I'm trying to find a quick way to detect player latency (one way specifically). Was curious if anyone has some advice or knows of a prefab in existence that does just that.
The problem is that you cannot send Custom Network Events (CNEs) to yourself. There are prefabs/systems that automatically give each player their own networked object, which would allow for this, but they can be a little tricky sometimes. If you do use them however, you would just save a timestamp of when you sent the request, and then subtract it from the timestamp of when you received the response. Just divide by 2 if you only need one-way.
There might still be other methods of getting your own ping, but I personally dont know any others. At least none that arent prone to errors.
Sorry, I should have been a little more specific. It only needs to be player to player, not specifically to the local player.
But anyway, I was assuming timestamps would work, my problem was that when trying said timestamps, I must have messed up math somewhere because all of my ping tests ended up being 0, 1, or rarely 2.
You can have players get the server time and use that for working out 'who shot first?' senarios.
I have a thing where when two players are buzzing in for a question, the buzz is a property sync with the time of their button press according to a server time request. Then if they arrive slightky out of order, its not a problem.
I could probably put that to use thank you. :3
would be like that ok? i wand to respawn pickup with objectsync
@sweet wolf thx alote π
This is for all objects in the world, if you need only one, then remove the cycle
i need for 6 object in the world the other none pick up got respawn buttons that i not maket
In the array, set as many as you need, and add these objects.
@sweet wolf thx for helping me i am not exp. on sync stuf
@sweet wolf i got one question the script like you give it to me is respawning all object thay all ar pick ups if sobody holding it in hand its teleportet away and i dont wand this i changet the script like this would this stil be ok ?
so its sending to all and the owner respawn it if he stil got it in hand it stay but would it be ok like that or do i need to fear to get lags or enythink like that or dsyncs or samthink with alote ppl?
It is necessary to add a check in the pickup whether a person holds it in his hand, and exclude it from the array.
customnetwork there, except for lags, will not help in any way. There is another option to remove the setowner, but the respawn will not work correctly.
@sweet wolf no idea what to do the only think i can think of is make only the master can reset all pick ups.no idea how to check if its hold in hand the script is checking only the objectsync no idea how to i check it to exlude it from the array :/ but i can try it maybe i find it if not i gona do it like i say master only button thx for the help
Yes, instead of locales, set the master to interactive. This is the simplest.
@woeful shale
@sweet wolf thx π
is on variable change considered a variable network event
No, but if the variable is synced, it will play it locally for every player when they see it change
what are the different synced options i see none, smooth and linear
smooth and linear is gone for a long time, there is none , continuous and manual
i think i found a video that goes over it
The Udon Networking Update (UnU for short, previously known as the Networking Beta) is finally out after many delays, but what actually does it add? I cover some of the groundwork on it, but there's literally hours of specifics that I could go over, which I will not be doing here.
00:00 - Intro
00:48 - Continuous v Manual Syncing
02:46 - Object...
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...
tnx
i ma watch some videos as well cause i need to learn everything with in 5 days, since my whole group is moving to vrchat
Quick question for Late joiners in a map
Do UdonSynced values on a manual sync need to be RequestSerialization()'d again? Or will they receive the values as they are currently stored?
they do not need it, it'll send the latest automatically
I was hoping for that. But wanted to be sure. Thanks Phase. x3
Totally new to this but Im trying to find an example in c# on targeting just the latest joined player (from onPlayerJoined ) with a network event from the master. Everything Ive been able to find only shows how to send out a network even to all players.
ok , so then I assume SendCustomNetworkEvent can take a player id for tis target?
AH! total lightbulb moment. Thank you very much
thanks
Anyone know if using "GetTrackingData" of another user just pulls network data we are already receiving. Or if its additional network overhead pulled from somewhere else. As I'm unsure how to even test if this is contributing as additional network data or if this just tie's into some data we already get from network IK or something else.
Would also be interesting to know where GetBonePosition pulls from as well even tho its not needed for my use case.
Use case:
Rather than syncing a object every frame or every "x" time. I plan to just have said object follow the objects owners current pickuphand y position. And then store the objects position on drop in a synced vector3 for later joiners. Why sync the object constantly when I already know where your hand is in theory. (rotation is not needed for my full use case.
Goal: avoiding unneeded network overhead and avoiding flooding the network with synced data.
tracking data of a remote user just gives you bone position. It's not any network overhead, but it's also completely incorrect because every avatar's bones have a different rotation
Well as rotation isent needed and position just needs to be "close enough" for my use case should be fine. Thanks for the info.
I think this is a question for #udon-networking, but if it's more suited to -questions, I can toast this massage and re-share over there...
That aside, I'm struggling with a map/player counter...
I have a series of box collider triggers laid out in a world. Each one has a custom made udon graph: Serialized_PlayerTriggerUpdateText.
When a player enters any given trigger, an int Addition (+1) is triggered for it's respective UI element. When they leave the trigger, int Subtraction (-1) fires.
This part works great but doesn't account for when a player leaves the instance.
I've tested a number of things, but my current attempt is to use OnOwnershipTransferred to run the _PlayerTriggerExit event. No luck there, but I'd like to think I'm on the right track.
Does anyone here see what I might be doing wrong?
Is OnPlayerLeft a thing in the graph?
yes, but it hasn't worked in my tests
I suspect it's because the trigger zone loses it's owner, but I'm not sure
It should run for everyone in the game
I'll give it a go and see if I get similar results
ah -- I remember. When I did OnPlayerLeft, all triggers got -1
(which makes sense)
I guess I need to find a way to inject a check to see which trigger the player left from -- and possibly set a new owner to run the event
The owner is auto set to the person who's been there the longest (master)
hmm... I tested this out and... couldn't get it to output anything to that log π
but after looking closely, I'm not sure I need to run through any position/raycast logic, as the playerenter/leave are enough to say which trigger the player is in
my issue is specific to OnPlayerLeft not following through with the behavior that happens OnPlayerTriggerExit
even though both events send the same custom event
How were you testing it?
This function should be on a game object that has a box collider and it will only fire for remote players when another player leaves within that box colliders bounds
I added the script to my existing trigger (box collider), and added a message const to the log input -- in playback it didn't return anything, so I swapped the get component for a direct reference to the collider it was on.
in both scenarios, I didn't get any log output
but I'm open to testing it again if I missed something
I think... my testing was flawed
so this would trigger an event when the player leaves ey?
I was testing that log by running in and out of the collider
and now I feel silly
Yeah that wouldn't work
stand by... starting unity XD
I got friday on the brain -_-
doin' a fresh build now
~launching four instances...
appears to crash the behavior when one person leaves, but I'll investigate further
here's how I tested this time
spun up four instances, moved three players into one of the triggers, then closed one of them
for the other three, the script froze at 3 and didn't update anymore
(the fourth player was in spawn, and not in a trigger -- watching the UI)
Can you expand the error and see what it was?
sure -- currently adding some logs to re-run it
and I'm curious... is RaycastHit hitInfo returning a bool?
It's expected that it will crash for the person leaving but it should function for remote players still in the instance
Oh and no
should that bool output go to the branch instead?
That might be an issue with different graph versions
Yeah the bool should be going to the branch
My version would be older
Though it could just be graph being graph
Also in your example you aren't using the OnPlayerLeft API output
Oh and no nevermind not a graph issue I figured you would have copied and pasted rather than recreate it
Yeah expected as you have a null GetPosition() in the graph
I'm not sure where to put the api player output
from the VRCPlayerApi on the OnPlayerLeft connect it to the GetPosition
oh!
sorry, you had said that and I missed it
alrighty -- fresh build/test comin' at ya
(and thanks for all the help)
man.... so close -- it seemed to be working
I started six instances
walked five out into the first trigger
left one watching the map
I closed one of the five, and it updated as expected
I walked two into another trigger zone, then closed one of them
it didn't update on that one
then I walked the remaining players back to the map to look, and the master of the instance saw a 1 in each trigger that I'd 'player left' from, while others were inconsistently showing 2 and 0
I suspect my trigger method is gonna be too unreliable to get real numbers for everyone in a given instance
someone dm'd me a sharp solution that uses cyan's object pool
probably overdoing it with the info but ... when I went to test that, installing object pool in my project just started an infinite error loop
I figure that's a problem for tomorrow's me -_-
If you just need to keep track of the number of players within an area I have a better way of doing it than counting with an integer
would it work with six different zones?
(cause that's literally all I want to do... just show a player count on a map)
Yeah it also wouldn't use any networking
I'm listening :3
@sturdy geode
interesting
testing against physics... that's kinda wild
wow.... so simple... works perfectly in emulation
gonna spin up some instances and see how it goes
it's flawless
jeez... I've been hitting this problem with trial and error solutions on and off all week, and you solved it in just a handful of nodes π
not sure if its possible but i got a script thats called "wandering AI"
i got a model walking around in my world
but he is not networked
is there a way to have it so that the position of the model is the same for every person in the world
even late joiners ?
Sure, it sounds like a VRC Object Sync component might help here. You can learn more about how networking works in VRChat here: https://docs.vrchat.com/docs/udon-networking
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...
VRC object sync didnt work
How did you use it? How did you test if it worked? I can help you better if you can explain what's going on in more detail.
i'v ehad the object sync on the part that has the wander AI on it itself
i had it on the model itself as well
and i usually just loaded up VRC twice
through build/test
It's not a good idea to have multiple Object Sync components on an object like that. Does the object have a Rigidbody somewhere?
anyone know how to get smoother sync on objects? I have vrc object sync on an object and it's jittery for other players
Is it possible to have VRC not tween objects to locations? A third party system I'm using is fine normally, but when it gets a little laggy, the objects (when moved from A to B) clearly tween back to their original location and wreak havoc in their route smashing everything else out of the way.
Interesting, thanks. I redid an entire world at one point when some other system had a similar issue as I was told the "correct" way to handle this was to drop objects out of the world and let the respawn system handle it!
how do you sync something for late joiners https://cdn.discordapp.com/attachments/657394772603830360/1014005883677716580/latejoiner.PNG
not sure if this is correct way, but it seems to be working. trying to follow along playerbush video.
for this example it seems simple, the bool pretty much says whether the gameobjects are inverted
Since the player is taking ownership of this GameObject in that first flow from the Block up top, you can simply have the second flow connect directly to the "Set Toggled" node instead of jumping through a network event to change it
alright ty, explains why it didn't work before where the interact would just change the bool. not allowing second player to use it
now the issue I'm having is the gameobject with this behaviour is off by default. and the keypad that toggles the object is also off by default and for some reason doesn't sync even if I edit their script to set a sync bool to true. Idk, brain hurts figure it out later
I did figure it out by using a custom event to graph, and using another graph just for sending custom events that can be off by default
umm how can i transfer variable data to new room master when old room master leaves? because even with sync option enabled on a few variables that i need to have synced they're getting resetted for others when master leaves
if it's a synced variable then it will transfer to the new owner when the old one leaves/gets ownership taken away
i was asking for that because i have script where i have few variables synced + script can only run if player is master so i woΕ't get duplicated networkevents being called from everyone in the world but when master leaves the game few variables get resetted? i need to check it later but basically i have 1 variable that's being set to true when different synced variable = 0 but when master leaves that variable is being set to true even when that synced variable value is over 900
it's probably better to check for the networking owner of that object instead of the master, but if it's synced it should transfer whenever they leave. Make sure whenever you modify synced variables you set the object's owner to the local player and request serialization after you changed the variables if you're using manual sync
alright i'm gonna later do it and let you know if that helped with my problem
okay i found the problem, i didn't allowed to update UI + 1 variable before it checks if player is master to do code that only master should run
The biggest thing you're missing here is that you're not setting owner to the local player when trying to set the value
if you have that, then it should work. Are you sure that this sample code is exhibiting the same issue? Perhaps there is a difference between this and the original code that causes the issue
The biggest oddity here is that you're using a property but not really doing anything with it. Like there's really no point in having it, if you're just going to use ondeserialization for everything anyway public int MyValue { get => _myValue; set => _myValue = value; }
but unless the property was set up wrong it shouldn't actually break anything
so maybe it is set up wrong in the original code?
it's up to you really. Typically people either use fieldchangecallback or ondeserialization. But using ondeserialization and implementing fieldchangecallback but not doing anything with it is just a bit odd
properties can add a lot of extra confusion, yeah. It's best to avoid them unless you know what they're doing and why you need them. They have pretty specialized use cases
ondeserialization is much more straight forward and easy to understand
absolutely nothing
ondeserialization is what happens after the values have been updated
so simply printing the value or doing whatever you want to do with it is appropriate
So for a setup like this, even with networking, it wouldn't update properly for late joiners?
On click, it sets the animator bool and writes the updated mesh to the collider. Thing is, for later joiners the door will either be out of sync or just stop working for the other player.
Are you using any Synced variables in this setup? Late joiners will not receive that event.
Checking...
This is the only variable that can be synced.
Actually...gimme a sec I wanna try something, brb.
Got it working! Thank you Momo. π
Anyone able to help me out and figure out why the scripts disable themselves due to error? I'm trying to get the lights to move for everyone in an instance when a button is pressed. animations worked and when I set it up for local only it worked fine, but the sendcustomnetworkevent seems to be causing issues and im not sure why.
I tried using the event variable synced and it made no difference
^this is also my first time attempting synced animations so if its spaghetti coded I apologize
Your getbool node needs something plugged into it. The eror log should mention what function it was trying to do while it crashed
in picture 1 or 2? The getbool from Target 2 graph is UpDown which is the animation toggle, and the "toggle spotlight rl updown" graph is referencing ToggleStageLight from the other script
In the first pic, in the onplayerjoined event
I got it working, heres the working script. basically removed the second script and pushed it into one reference
theres a bug with this, if the player is not master the script will do nothing on player joined which is not the intention, but I can fix this fairly easily by setting a false value for the branch to push a network event to the player that joined
also changed the networkevent to just a custom event because not everyone needs to sync everytime a player joins
yo can i ask for someone to make a working cassete tape player
i already have the open and close and cassete 3d model
i have money if you want to be paid
Do you just want it to move or do you want it to play music as well
As long as the model has separable pieces im confident i can whip up the motion, but i dont have experience in sound stuff in unity so im not sure how long that would take me to learn
Ull just on trigger check what cassette it is then drop, animate it in then either play a clip or load a link
P much yeah
I dont think it would be hard to learn i just dont have any estimate
Upon collision or trigger like you said just drop and then write the animation math, then play a sound clip that can be attached to the cassette as some sort of game object
Ezpz except i dont know the specifics of vrc's sound system
i want it to move and play music
still not too hard
can it also like eject the cassete tape when it opens
yeah simple movement stuff shouldn't be too hard
the trick will be tinkering with the sound files
I'm not confident I could get it done for a reasonable commission but it's definitely doable
yeah udon just uses "play"
for audio
and you can prob use
audio source -> set audio
or something
well i meant more like being able to know when it finishes and stuff
oh tbh idk
You can get the length of streams and clips
nice
so bard can you do it or naw
mmmm when do you need it by
let me get back to you tomorrow
yeah
been briefly scanning forums and discord history but can't seem to find anything about this specifically, so maybe im just dumb but is there anything you need to do to get audio synced in the networking sense? I.e. do i need to do anything so that all players can hear audio i start from an object interact, and will late joiners hear the same audio everyone else hears?
just sync a var and tell it to play the audio with a local check
Nice ty
Ok, so I'm guessing there isn't really a good solution for this, but if there is I would love help figuring it out.
So I'm making a Dungeons and Dragons world with a system to import custom character sheets.
So I have an HTML file people can fill out, then a little extractor executable that I made to take all the data and put it in a "|" delimited string.
I have a little Udon Sharp script that reads in the string through InputField and cuts it up and sends out the data to various UI gameObjects to display on a character sheet.
I've got it working locally, but I'd love to have the data string sent to all player in the instance. It's a 3k+ character long string, so I only want it to sync when someone pushes a button.
Is there a good way to accomplish that?
I was playing around with the [UdonSynced] type variables, but when I tested it, the game ground to a halt.
3k string length is well within the limits of manual sync and may be a little chunky for string split but not unreasonable. Are you sure it wasn't trying to decode it every frame or something?
Also it would be significantly cheaper if you did the newline replace before the split
I think I did have it on continuous.
Yeah I added that as an afterthought since you can't enter in tabs or newlines with vrchats updated keyboard thing when you click on an input field. I'll tinker around with synced variables some more. I don't know if I need to add a string variable to sync the _dataInput.Text then wait a second or so and run the spilt.
renderDataToUI is only called when you push a button next to the input field in game.
Originally I just put a [Udon Synced] tag on the _data[] array before it's even initialized and for some reason it just ground everything to a halt. I'm still just trying stuff. Thank you for the advice.
Hey, I'm having an issue with VRC Object Pools that leads to an entire game crash (single player when they trigger something) in a certain circumstance when the pool is exhausted. I suspect it's networking or ownership related. I can share more details with devs as this unintentionally crashes the game, despite udon (from what I understand) running virtually.
To give a bit more context, the problem occurs when an ownership transfer happens with the object pool being empty. It seems that the VRCObjectPool fails to check if a pool is empty after a ownership transfer happens, causing it to try and spawn in an object, causing the game to crash. Here is a reference script that causing the crash:
I suspect the reason your fps tanked is because it was spamming errors about how it was trying to sync too much for continuous. The limit for continuous sync is about 160 bytes. The limit for manual sync on the other hand is 50k bytes. Changing it to manual should fix that issue.
You can have the data array be a synced variable, that works. But you'll need to have the splitting operation be in a different function from the part where it reads out from the data. When you get the function called from the button, you would need to set the owner to the local player (this allows you to change the variables), then split, then do requestserialization (if it's manual sync, this tells it to send it out to other people), and then create a new function like "parseData" where you would put everything else like read out strings and check boxes. Call that at the end of the function that is being called by the button
Then add the ondeserialization event. This event fires when somebody receives data from the network. When that happens, you would want to trigger the same parseData function that's going to do all the things. That's how everybody will run the same code on the same data.
I would also recommend doing some data validation and make sure the data array is exactly the right length, because right now you have it hardcoded to access all those indexes and if someone gives bogus data it could very easily run out of bounds and crash the script
Any suggestions as to what would be a good check? I made one that checks if there is any inactive gameObjects to spawn in, but there are also cases of gameObjects being set inactive, but not returned to the pool; which would be a problem here
Hey, thanks for the help - will test these checks when I get home. For my case, there is no reason for the spawned objects to be set inactive (though I may have them return to the pool). I'll let you know how it works π
Thank you so much for this. It gave me very clear direction to navigate all the documentation and tutorials. Thanks for the reminder to validate stuff, I was definitely just letting it kill itself with bad data. I don't know how you can be such an amazing person to just swoop in and solve all my problems lol. Thank you for just being so amazing!
I could kiss you @frozen igloo lol. Thank you again for your help. I was struggling to understand the documentation on synced variables and stuff.
Pretty much did exactly what you suggested.
I got your method to work. Fortunately there's no use case in my scenario where I would need to set a spawned GameObject as inactive. I also learned how to Udon Graph if/then statements and set variables, something easy in code but not straightforward for the uninitiated in Udon Graph!
I'll credit you in the world I'm making (a pillow fort builder with pillows that spawn from sheep pickups!), unless you say otherwise!
Glad it helped ^^
I would still like to know what causes it to crash though. It's such a bandage solution...
do variables get synced eventually on manual sync without requesting serialization
When other players join, that can trigger serializations sometimes but don't rely on that
I need to reliably sync 3000+ objects active state, they are never all active at once but due to the fact that we can not sync instantiate operations, I have no choice but to create all the objects before hand. The current system I have kinda works but if thereβs a lot of people in the world then it starts breaking down
Iβm making Garryβs mod in vrchat
There are 178 unique props you can spawn
And there are 19 of each
For a total of over 3000
Currently I have each unique prop in a group
And that group has a udon behaviour waiting for network events to be sent to it, once it received a network event telling it to enable specific prop, it will activate it for all other players
The props themselves each have a behaviour in it that simply sends the the group object the network event when it is spawned or when a new player joins and the object is active.
I donβt need to do anything for de spawning since I use a synced ball to despawn them, so itβs global
Even though I made sure to add a buffer so that when a player joins, the prop first checks if itβs active before sending the event to enable, it still sometimes likes to spawn props that have previously been de spawned one a new player joins
Iβve tried using the default object pools, and sure it worked but I was rocking 10 frames per second since they are so damn unoptimized
Since there was 178 object pools
My system is a bit unstable, but I get much better frames
I also tried just making my own separate object pool that does not sync anything, and use those instead, while also having one big default object pool that has all 3000+ objects
But that did not work either
I also tried using an integer array that gets synced every 8 seconds, and that worked, for about 8 props. Then it stopped syncing
And now Iβm just using my own object pools that donβt sync, and my group and child method
Which seems to work other than the occasional ghost props that like to come back
Also can you please add support for method groups with variables ex. public void ExampleMethod(int Index)
Cause last time I tried that with U#, it said udon does not support that
here you can see the size of various variable types in raw photon https://doc.photonengine.com/en-us/realtime/current/reference/serialization-in-photon
Global cross platform multiplayer game backend as a service (SaaS, Cloud) for synchronous and asynchronous games and applications. SDKs are available for android, iOS, .NET., Mac OS, Unity 3D, Windows, Unreal Engine, HTML5 and others.
and add limits for what each players can spawn. Even garrysmod servers tend to limit about 100 props per player
edit rereading paragraph, skimmed too fast
The problem with that is that I canβt tell which player spawned the prop and have it synced to everyone
Cause what you are implying is that each prop needs to have an implicit owner as to who spawned it
the simple answer is that the network infrastructure of VRChat is very different than any source engine game, this is a difficult goal to adapt without sacrificing quality or latency or something
Exactly my point
Iβve been told itβs impossible, but Iβve spend over a year working on this and Iβm not about to just throw it away
I think on a smaller scale it is possible, but you will have to do your own custom implementations on a ton of things
like I don't think you should be relying on the default object state (pos/rot) sync
I donβt know how to make my own object sync
well first thing to know is that you should do manual sync, since network limits are a ton higher for those: https://docs.vrchat.com/docs/network-details
Try not to sync everything; consider what you can determine from the minimal amount of information shared. For example: if an object will move on a fixed or predictable path, then its position may not need to be synchronized and instead its initial location and velocity may be sufficient. If there e...
200 bytes compared to 49 kilobytes
I am currently using manual sync
Iβm not using any variables atm so I tried using no sync, but network events do not function with no sync
Iβm simply relying on the objects themselves
well, this is off the top of my head, but I would guess every object should be a hybrid kinematic sync / local emulation system. Where every physics object most of the time runs locally, but upon the owner of the object sending out a serialized update frame with an update for that object, all other players local objects briefly switch to a kinematic mode to correct for what the master position / rotations are
further optimizations can be done if the objects kinematic states go to sleep / awake in a proper manner
if spread out of various players, this can be decently optimized
the bad news is that prop interactions from props of different users when both have active forces upon them may be weird
so it may be best that all props within a "contraption" belong to one player
As much as I understand what you are implying, I have no idea how I would actually make that
Also it prob does not help that each prop has 1-100 children responsible for accurate collisions
Since rigidbodies do not support non convex colliders
Iβve done my best to optimize them manually
When Iβm home later if you like I can show you the project in unity and explain it a bit better
I am pretty busy myself, but I can take a peek. I am actually working on a similar problem, but I am dealing with 10s of objects at most
Iβm on my iPad rn and I donβt remember every little detail off the top of my head
If you are working with only double digits then my solution would probably be the best bet, at least according to what I know, which is not much π
honestly, I would start with smaller projects before deciding to upstage the unity physics system or photon's networking lol
What is the maximum amount of items you want to display? 3000 sounds quite a lot. I'm not familiar with garry's mod, but I don't think you want to have that many at once, do you?
If you don't, then you can create a smaller pool of let's say 100 generic objects that you sync for everyone. Then, when an object is spawned, that generic object takes on the actual attributes of the unique prop (like mesh, colliders, etc.). And all you have to do is sync the unique prop id for that to happen.
Yeah, this is the way to do it. I have a "prop library" with 128 props, and then each prop can transform into one of 500+ templates. As a result, you can have 128 crates out at one time, 128 guns, 128 bagels, or more likely mix and match, with 20 crates, 20 guns, whatever
I was told about this idea in the past, but the problem is that each of my props have multiple mesh colliders/box colliders responsible for accurate collision, I'm not sure how I would make it sync those since each prop has a different amount of them.
instantiation
you can't instantiate synced objects so you'd need to have all the syncing happening on the pooled objects, which is annoying and tricky. But you can have the children be instantiated and define the actual behavior
so if a object with a rigid body randomly recives new children with colliders, it will update it?
yes
ok so that could actually work
so for each type of prop i define a prefab with the coliders and have it instantiate when it is spawned?
i never thought of it like that
also this is prob a dumb question but quest compatibility is out of the question correct?
not at all
ive heard syncing between platforms is tricky
quest can do all this too
like i will be holding one thing and for quest i will be holding something else
I mean yeah, if you mix up your network IDs
but that has nothing to do with this technique
oh
the instantiated objects can't sync, that's what makes it difficult. You have to do all the syncing through the pooled objects
ok so 128 objects, each have mesh/box collider for the vrc pickup, each have vrc object sync, and each have mesh renderer
and those are in a pool
is switching the pool owner to the person that spawns a prop a good idea
cause it does not work otherwise
well that's one of the tricky bits. If you have one person spawning at a time and you need the spawning to be instant, then yes you can take ownership of the pool and spawn immediately
thats what i originally did
but if you expect multiple people to be trying to spawn at once, then that could run into issues where you try to spawn something and then it gets stolen
huh?
this was when i was originally using the default vrc object pools
i had 178 of them
created a lot of lag
were you taking ownership of all the pools when you tried to spawn from one pool?
was this lag after someone recently joined the world?
oh, fps lag not network lag
um idk, that sounds unrelated to networking. I have no idea what you'd be doing to cause that
yeah I know about that
yeah i had people complaining about that but i had no idea how to fix it until recently
ok so i have a question about the vrc object pool
does it sync if an object is activated but not with the spawn() method
like a seperate script activates an object in the pool
and the owner is the same owner of the script that activated said object
Hi there! I'm losing my mind on this issue I've been dealing with for days now.
I'm trying to do a toggle on networked objects that are assigned to a player when they join the world.
Essentially I'm trying to get a particle system to begin playing it's animation when the particular player interacts with the toggle. I can't figure out how to make it so that when one player interacts with the toggle, the animation begins playing for that particular object for everyone. I know the object sync is working when I have play on awake set to true, cSause i can see other peoples particle effects properly. I guess I'm just not targeting the correct object? I'll post a screenshot of my code. I know what's happening is when I send the Network event to everyone, its just running the callback, which target each players individual object and begins the play animation, but it doesn't update that for other people. so each player will see their own particles begin to play but not see anyone elses. Sorry if this is a bunch of rambling, any guidance would be greatly apprecaited!
oh my god, never mind, i figured it out. In case anyone was wondering, this achieved what i was going for:
`
Hey there. I could use some advice on a matter concerning vrc object pools.
The documentation makes it sound like, as long as the owner of the pool is doing the TryToSpawn thing, that the state of those objects is synced and the objects that become active are updated for everyone.
I have a pool of about 30 objects that are supposed to spawn 5 at a time. I have a check in the update loop of the spawner that looks for if the number of objects is less than 5 (specifically 0) (they are objects being destroyed by the players) that it will then check to see if whoever killed the last one is the owner of the object pool, if they aren't, they become the owner, then they do TryToSpawn 5 times, but that part just isn't syncing up with other players
cant seem to figure out how to sync variables, i did get it working through sending from local to the owner and then the owner updates all, but then the local has to wait for the owner.
so here my question, how do i make a player that is not the owner sync the rest without waiting for the owner?
(on udon graph)
Can anyone advise me as to how to pick the closest of an array of objects within an int defined range and sync this over the network? Trying to have an AI target the closest player in an area and target them.
Doing this using an object pool.
I am looking for someone who can make a personalized roulette wheel for a world, the modeling is done but I need to make it functional.
anyone got the issue that later joiners may not receive manual sync vars correctly on join? the owner need to post the vars once again after the joiner has completely loaded?
Manually synced vars will not sync automatically on connect. As the name implies, you'll have to manually request synchronization.
As a matter of fact they do (or at least should)
I've never seen them do π€
But if they do, how would you prevent it?
In a lot of my use cases it'd not be very good if stuff synced before I want it to...
But I guess so far I've always went the safe route of firing a "sync Panic" on join, where everything is set to default on the client, and manual syncs are requested right after
Oh, I think this is a better channel
Who is an owner of a networked udon script, which is disabled?
and is it possible to make first person to enable it to become an owner?
or at least check on enable if there is an active owner?
what will happen with OnOwnershipRequest when the object is disabled?
Something thats important to learn when being new to Unity is that a "disabled" GameObject does still exist. What disabling GameObject does is essentially just disabling all of its components. And what disabling a component does is simply remove the component from Unitys Update Loops. A disabled component will still execute code, when called directly by some other object. This means that even a disabled GameObject will have an owner - the instance master by default. (Be aware though that some functionality needs the object to be enabled at least once to properly initialize it)
To answer your questions directly:
- The last person who was the owner or when there was no previous owner the instance master
- Yes, using the OnEnable method/event and simply doing Networking.SetOwner
- Every networked object must always have an owner no matter what. You also cannot differentiate between the instance master "actively" owning an object or just being its default owner.
- It doesnt matter whether its disabled or not as explained.
so I can test if this object is enabled and then refuse transfer
Yes you can do that
so like this
well yeah but you can simply do return !gameObject.active;
a friend recomended
gameObject.activeInHierarchy, in case parent is inactive
ok thank you
are networking events called on disabled gameobjects?
I think they must have been enabled at least once to properly register on the network, but yeah if they are initialized, it doesnt matter.
Thanks! Do they have to be enabled for a certain amount of time though? Disabling them right on Start seems to break the scripts
It not connected
wron channel π
I can't get the enemy, called cactus, to spawn for everyone in the same place for each player
Random Range will be different for everyone, so you want to sync the output of it or the spawn location as well
So one thing I tried is making a synced float variable called ranSpawn that holds the random.range result. I tried putting that in localplayer.isOwner and out of it. still, the enemy will spawn in different spots for each player.
Maybe there's a better way
How are you handling it for the users who recieve the ranSpawn int?
gonna be honest with you, I'm pretty new to networking. is there something I'm supposed to do with a synced variable out of just syncing it. All I did was sync the variable and then wrote that line of code there in Update.
Basically you want to set up some behaviour/code that you want to happen once the data is received by other users
I believe a lot of it is covered in here:
https://docs.vrchat.com/docs/udon-networking
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...
this seems to be the answer to my question but I still cant seem to wrap my head around it
more I think about it, not sure what Im doing is possible. the best solution is to have the instance owner generate the random location, but then how am I suppose to get that to the other players.
If you implement your own deterministic random function then you could initialize it with a seed maybe
We don't have access to the Random.state or Random.InitState I don't think, so we can't use that x
But we do have access to random state
I figured this is probably a better place than in udon questions...
So I haven't poked at udon/udonsharp in quite a while now, but is there still no way for the owner of an object to detect which avatar/client is sending a custom network event?
the owner could have a LastPlayerID variable that is updated by the client with their id whenever they send an event
nope, but there are some workarounds, albeit a little messy
Here's an example of how to do it the other way, where the owner of an object wants to send a custom event to a particular player; but the same kinda method would be more or less how you would go about doing it the other way. Either that, or use this method with a player object pool, and get it to tell your player to play something
Does OnDeserialization need an is owner check? I see it in a lot of U# code, but I can't seem to trigger a case where this fires where this would be true.
Also I see something about serializing byte being bugged - what's the buggy behavior being referenced?
That depends on what you'd like to achieve! OnDeserizalization gets executed by non-owners after networked data has arrived.
Normally, the owner of the script is the one send the data, so OnDeserialization is not executed for them automatically.
Are you trying to prevent the Owner from executing it, or restrict it to the Owner only?
I found out the answer I was looking for elsewhere: it was a past networking bug.
Same with the issue of byte types not serializing on the network correctly
Ah, one of those! π
All past bugs that have since been resolved :D
Excellent! I suppose you were browsing old messages?
Source code actually! Primarily USharpVideo, but also other projects.
As for the byte stuff, udonsharp docs hosted at vrchat's thing
Ah, I see.
https://udonsharp.docs.vrchat.com/ this one
A compiler for compiling C to Udon assembly
Hmmm do you have the page referencing the bug with bytes? π
https://udonsharp.docs.vrchat.com/vrchat-api#synced-variables
These are the variables that are listed as available for syncing across the network. Note that partial support exists for byte, sbyte, short, ushort, and ulong, but are currently bugged and may not give you the results you expect.
But that's the only instance of that I could find
Oh yeah, this page is outdated as well: https://udonsharp.docs.vrchat.com/frequently-asked-questions
Questions
Oh? What bits are outdated?
[...] don't work in Udon and UdonSharp yet. These include, but are not limited to, the following:
Enums not already defined by Unity Generic classes (Class<T>) and methods Inheritance Interfaces Method overloads Properties
U# 1.0 has most of that!
Oh yeah I have already used enums wheee
But enums defined from within a class does not play ball
Yeah, I just created a separate file within its own name space. That'll work globally
The error message when you define it wrong can be confusing.
class MyThing : UdonSharpBehavior {
enum ThisDoesntCompile {
Lol1,
Lol2,
Lol3
}
private ThisDoesntCompile oops = ThisDoesntCompile.Lol1;
}
I wish I could do that
(idk if I messed up the syntax but I'm talking scoping definitions)
Yeah, I just created a separate file within its own name space. That'll work globally
I mean I mainly use enums for state machines
Am also learning the horrors of doing 2-way RPC networking in udon... hooooh
Well, pseudo-RPC
OnDeserialization can be useful for the master, too. Depending on how you design your code...
For example, for my worlds, the master calculates the state of the world - but all the visuals are handled in OnDeserialization.
And in UdonSharp it's pretty easy to call OnDeserialization manually!
Fairfair!
For that kind of thing tho I'd rather keep it in a separate method and just have OnDeserialize call it. Explicit > Implicit and all that
Ohhhh yeah, that can be tricky!! π
You can make it work, if you manage your expectations π
Thankfully my main shindig is distributed systems l o l
So I can make it my bitch
But it's ah... "fun" limitation
Reasonable! Though I prefer to make sure my master client's not missing anything π
(And UNet feels like3 a copout)
Depends what you're doing ig lol
For me I'm working on a minigolf system with tiers of managers
And learning that I now need to redesign it as I can't have the global one manage score for all players and keep players own ones on their client only oops
Fortunately VRChat is working on a Player Scripts feature, which lets you define scripts which exist for every player.
In the meantime I've been using CyanLaser's object pool system.
Neat. Though idk if that'd solve the issue here, the issue is communicating data back to the shared manager from all players.
Also why cyanlaser's over the built in VRC one?
Cyan's automatically manages giving out the script to players. It sends custom events when a player is assigned an unassigned, which is neat
With just VRChat's object pool you'd need to build that functionality yourself.
Ahh. Sounds neat.
Though I'm weird and like to manage it all myself with one big singleton
lmao
I was wondering. Does a random number need to be synced if it's ran on everyone's computer since it isn't truly random?
yeah, if everyone generates a random number they won't be the same. Best for just the host to generate and sync it
What if I sync a seed?
Everyone will start with same number and same number order. But late joiner will have to catch up with the early player, thus not truly synced.
Oh interesting. Thank you.
There's ways around that! With some limitations.
That's a valid option! It's great for turn-based games, or games that are mostly deterministic. https://docs.unity3d.com/ScriptReference/Random.InitState.html
For example: Your could have a seed that is randomized at the start of the game.
And if your game has multiple rounds, you could call Random.InitState with the seed + some other data, to generate the same numbers for everyone.
Hey all!
I am getting a null reference exception any time I try to access the Networking.LocalPlayer functions. Including the Networking.LocalPlayer.IsValid() Anyone encountered something similar?
Can you show the code
It happens when the player is exiting from an instance. Is that the case?
The error only shows in the Console after exiting the build, but the function is never called when playing
What happens when you log networking.localplayer
Then it should be good. Did you verify that GetPlayerHandPos is working correctly?
Ah! Looks like it actually has something to do with the object layers. In order to GetPlayerHandPos I need to confirm it's touching an object on the climbable layer
Does getting layer names work differently in VRC vs Unity?
User layers don't have the same layer name as in vrc. So it has to go by layer index instead
gotcha! Thanks so much for helping me Bard and Renfrew! Very appreciated
I have come back with another question.
When using ObjectSync and VRC pickup, the lag is quite severe. I want to be able to teleport dice and roll them but it looks so bad for the other players. Is there any way to make synced physics objects look better?
Instead of ObjectSync, you could write your own object sync with Manual sync which results in less latency. E.g. syncing position and rotation at an interval.
Another route you could take but is a can of worms is writing your own deterministic physics
Here's the visual difference for the latency between ObjectSync and Manual sync. Note that the aircraft are flying at a decent speed so the difference is greater at these speeds
the red models are the positions represented by manual sync, behind them are the object sync method
is there a way to see what variables have changed in a network sync tick (on receiver end)
this may be what you're looking for
https://docs.vrchat.com/docs/special-nodes#on-variable-changed
These are "Special" nodes. This includes flow control and special Udon features. Block Splits flow into multiple sections. One flow input, multiple flow output. Executes all right-side flow slots from top to bottom. Branch Inputs: Bool - System.BooleanBranches execution based on a conditional evalua...
Seems like the params is only new value and old value without knowing names
can someone give me a basic example of when someone should use Continuous vs. Manual synchronization methods?
oh, i just looked above, am I correct in thinking that Continuous is used for something like the transform of a synced item that someone is carrying, and Manual would be like, updating the transform of a synced item if some interaction moves it or something?
yep! Manual is good for values that update less frequently, and don't need interpolation.
got it, and Manual synchronization is preferable for like, closest to being actually synchronized between clients right?
i think i heard that somewhere
like it has a higher priority than continuous or something with the network?
That's right - Manual items are typically faster to sync up than continuous items, which may be deprioritized if there's lots of traffic because it's assumed that they will send more updates and can be interpolated.
I have an issue with OnPostSerialization() and OnDeserialization()
For my understanding, OnPostSerialization() is execute on owner after RequestSerialization() completed and OnDeserialization() is execute on non-owner receive data from owner serialization.
But after I do
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
...
public override void OnPostSerialization(SerializationResult result)
{
if (result.success) UpdateRoom();
}
public override void OnDeserialization()
{
UpdateRoom();
}
public void UpdateRoom()
{
...
It do nothing, I also have Debug.log() on OnPostSerialization() and OnDeserialization() to test, it also no logs. (Variable syncing is working fine.)
So what should I look for to have both networking method work.
does creating GameObjects at runtime desync stuff?
I don't know by create but ...
Using VRCInstantiate Doesn't sync the created gameobject.
If ypu need to sync, you'll need VRCObjectPool instead.
As I know creating gameobject on runtime can be done only by object spawn.
And this does not sync on network with sdk 3.0 so you have to use object pool or make your own sync method
not worried about sync. You're able to "construct" instances of classes this way
So am I right that the general way you wanna handle networked events with arguments is to not do that at all and instead drive everything with synced variables and potentially a junky state machine or otherwise state diff + merge logic?
There has to be a better way to test networking :^)
The way I've seen people do it and how I do it personally is have 3 synced variables, 1 is the target which can be an int for player id and -1 for all, the second is the function to call and the third is an object[] array containing all of the parameters. When you receive a packet, you'd parse who the message is for and then SendCustomEvent and inside the function, you reference the object[] array and type cast entries in the array to parameters you'd expect.
One thing to note though and what can make your project way more complex is that serialization doesn't happen immediately, so you'll have to implement your own queue system to ensure messages get sent. multi dimension arrays cannot be created at runtime, so my work around has been to just use a normal array and partition it where each section can hold the target, function, and 3 parameters before the next section of the array begins and OnPostSerialization, I send off the next set of variables.
The only real downside to all of this which you can fix with some extra logic is that late joiners may run the code if the variables sync to them. which can have its own implications depending on if they need context or not.
and ofc, a client can only send data if they own the game object you're abusing.
Huh. That's an interesting method of doing RPC... Makes sense. Neat!
Well, there is no reflection in Udon, so it's not like you can do it many other ways
Yeah no that's totally fair. And I mean on the no reflection front, plenty of systems have to work like that in various languages, so that's not foreign to me. But the 3 synced variables is interesting.
Can the network handle serializing an object[] where each element is a different data type? Assuming all are primitives
you could reasonably get away with 2 if you just want everyone to process an event. Everyone receives it anyways
yeah. If it's syncable, it can be a mixed data type array. All of the entries are casted to Object which everything inherits from anyways. You just have to cast back
Casting bit makes sense, yeah. Well shit, that's neat.
nodnod Am familiar.
ah. Forgive me. I interpreted your message wrong
Lol you're good
Idk if that's the final way I'll go about things, but definitely a tool to keep in my back pocket.
I have some other problems to figure out first. Next udon test I need to do is if we have a double-issuing problem if I try to use ownership to implement a racy lock
I really want to know if there's an alternative, but I'm yet to even comprehend how a system that would be more ideal would be layed out considering parameters can be mixed data types and there is no reflection. You can't even spread an Array into a classproperty call
The racy lock one is definitely one thing that can be used if it works - it'd eliminate the need for a pool of objects entirely for RPC, if you're willing to pay in a bit of latency when spammed by multiple users - which is not the usual case for when you'd be using something like this.
Need to test but to copypasta the idea I sent elsewhere...
Definitely not ideal for high volume traffic
Okay. I have an ass-backwards idea, but I want to know if anyone here knows of any VRC bugs that will make this unstable:
On trigger, set local var as a pending request. Immediately request ownership.
First one to request ownership keeps ownership, by refusing to transfer it afterwards.
It performs what it needs to, then after a delay, releases its own lock (i.e. allow ownership transfer flag) and calls an event for any other player to request ownership who has an event queued.
Essentially implementing a racey locking mechanism via ownership transfer
The main question there: does VRC have any known bugs that can occur when multiple clients request ownership at the same time prior to ownership actually settling
Something to test tomorrow regardless, but if anyone knows where this can break it'll save me some trouble
unless you somehow implement an ownership transfer queue
So each client has a non-synced queue stored up, and if that queue is not empty, on "hey it's free" event sent globally, all clients race to take ownership and lock it to themselves if they have pending events
I'd probably rather sync an ownership queue somehow
Very janky idea but I despise the whole pool of 100 objects
100!?
Problem is I don't know how I'd get the source of the request
Okay maybe not 100 but you get the idea.
I dislike the 2x player count of cyanpool, or even the 1x of manual
At least for a properly plug&play system
yeah there's no way to get the instigator of a network event afaik
The actual use for this is simple - a simple "start" event that allocates an object from a pool that's managed by a completely different system that's held exclusively on the instance master
For something as simple as that I really don't wanna use a pool. It's not a high-throughput system.
So it feels wasteful
the race system you're describing would heavily favor pc players since quest's networking stack is awful
That's fine. They aren't racing to be first, just racing to get anything to happen at all.
As long as eventually everyone who fired gets a turn, it's all good
depending on the traffic, a player may never get to send a message at all
Once they do they get their own player-owned object to manage the traffic on their own and there's no contention
It's just the initiation event
And I don't wanna allocate to everyone in the world, just to those who actually need it
I will - but to do so I need to know who wants one
And that's where the racey system comes in
what I thought you were trying to do was one synced object to rule them all
Nah not at all. That'd be insanity.
This is just the thing that enters players. Then there's a global manager, and a per-player manager.
Per-player only exists if they ask for it
Idk your type. That very well could have been you. Some of layouts of projects I've seen are sadistic
Lmao
I'm for optimizing away as much udon as possible because the VM is heavy as hell, so I want to avoid too many instances of the udon VM running at once
Well, where I can manage to anyway
(I don't actually know the overhead of it, but still)
Well, the event system makes sense because it isn't on a loop
I mean I know how it's built in terms of the ASM and memory layouts and stuff but in terms of how it's executed.
Some claims have put it close to 30x slower than native C# (or the result of IL2CPP idk)
I forget the exact number but I remember being upset by how many iterations of while (true) { i++; } I could do in 1ms
Not that many lmao
Just don't use EXTERN
i++ uses extern :P
That I do know sadly
Which I mean is fine for small stuff but I want to keep the execution budget of my entire system under 5ms for all components at world cap of 32 people
hard or soft
well, either way, that's a tough to work with budget
I wanted to somehow offload everything to compute shaders, but nothing there
Graphics.Blit letsgo
Could look into audiolink's guts.
That one does bidirectional stuff
I think some of VRSL does too for the moving heads? But not 100% sure.

But yeah audiolink does its proper FFT analysis on-GPU AFAIK
bi-directional is just what I need. I really want K, V storage, but not wanting to implement a hashmap in udon
I know that at the very least you can pass in params, and you can read out pixels off of a CRT in udon. Idk how far the params go but could do packed encoding if you're willing to limit data types. Pack a bunch of ints into a single float and all that guff
Might be able to go further, idk full details
Been a minute since I've looked :P
There's an xml encoder/decoder for udon, so that is reasonable. However, there's the overhead of CRTs
There's some degree of overhead, but if you keep your tex size down it should be alright, right? It's mainly a memory-bound issue.
Like max 32x32 or smth
(I mean I'm assuming, but I may be wrong)
No clue. I haven't messed with CRTs enough to know, I've only glanced at it here and there lol.
https://github.dev/llealloo/vrc-udon-audio-link/blob/master/AudioLink/Scripts/AudioLink.cs is the master script that manages everything tho
whatever. Way off from networking. Iβll figure something out. Thanks for the insights and pointers. I need to sleep
Ay it's all under the umbrella of "breaking vrchat with black magic to bend it to our will" lmao
Sleep well!
I think I just got an insane idea... Vrc allows for external urls and servers... It might be possible to create a prefab of a working phone complete with contacts etc, have that prefab connect to a local webserver which then uses an app on a cellphone to place and recieve calls and text messages
Essentially bringing a working cellphone into vrc
that sounds like a security nightmare
I have played with shader / CRT stuff in VRC and a lot of it works, and they are expanding it recently as well
Not really it would only communicate on a local network similar to the Microsoft phone companion app that allows the same thing
oh so I misunderstood
Ye it would be a local server running on the pc
you possibly could do that through a weird midi implementation currently or OSC when that rolls out to udon
so it wont be a local webserver for vrchat, it will be another protocol
but you can do it... technically
umm with manual sync do i have to call RequestSerialize() on late joiner to get him synced with values?
no, that's not required
ah okay
I'm having a bit of an issue with a script that I've been using for quite awhile, but the recent changes appear to have made it no longer work correctly. This script is supposed to sync a particle system, to be playing or not playing. Currently it works for people who are in the world at the time, but if a new player joins the world, the toggle is backwards for them. So everyone sees the particles on, they see it off and vice versa... Any ideas what could have happened and what I need to change on this? I hope it's something simple that I'm overlooking and another set of eyes might see something I don't :)
You could use Synced variables (with manual sync) instead of Network Events, this way you dont have to have an event that checks the current state of the particle every time someone joins as synced variables are automatically updated when someone joins
hmmm, I'm pretty green when it comes to this stuff, I'm sort of just struggling my way through it using other scrips (jetdogs) but unfortunately it does not appear to be updated anymore so don't have much of any examples to go on that are current. So if I were to do it that way, I would just have to use the Toggle Event section of the script, and set the toggle variable to synced?
Synced variables are a little difficult to explain. Basically only the owner of the script can make changes to synced variables, then the owner can send those changes over the network to other people with Serialization events. That data is also received by people who join later on automatically. I made this graph with groups and comments, hopefully I am able to explain it clearly, but if you have questions about this graph let me know.
Thanks...I think that sort of makes sense, I don't quite understand the purpose of the flipped bool, would that not make it do the opposite of what you want? (maybe that's where I'm getting confused)
The bool is a synced variable. Its value will be synced with everyone on your world (even late joiners) So everyone will have the same value (either true of false) So you can use that value in the particle system to know the exact state of the particle system (If the value if FALSE, the particle stops. If the value is TRUE, the particle plays) Everyone will be on the same state
When someone presses the button again, it will get the current synced value (same with everyone) and flip it for everyone.
oooh ok right
I will give this a try. I would assume this would also work with non particles as well
You can use this for any toggle (2 possibilities) that you want to sync with everyone (like a game object, collider, other components, particles etc) Just simply put the action for possibility 1 on the TRUE branch, while the possibility 2 on the FALSE branch
Hi, I'm gonna sneak into this conversation if you don't mind...
I actually have a few questions on serialization, I'm finally starting to understand it...I think...
Except all the tutorials I see use OnInteract, which then gets local player who interacted to set as the owner...since owners are the only ones to change scripts...
- What if I was to do OnTriggerEnter or OnParticleCollision, since only the owner can change the script or do these just work without having to SetOwner?
(Or do I need to get the owner of the particle/collider and then slot that in as the SetOwner Player for this script to work?) - Some tutorials showed I should use OnDeserialization instead of just using the SendChange, but others showed I can use SendChange, which would be best to use with late joiners in mind?
Events like ontriggerenter and onparticlecollision happen on all clients, so if you're modifying a synced variable you need to make sure you filter it out so only one person is making these changes. You can do that by making a branch that checks if the owner of the other object is the local player, or if the owner of this object is the localplayer. Which one you choose is entirely up to you and whatever kind of architecture you're going for.
OnDeserialization and OnVariableChanged are very similar and can be used for the same things. The main difference is that if you have multiple variables that you're reacting to at once, you should not use OnVariableChanged because the order you receive them is not guaranteed. Note that OnVariableChanged happens for everyone, while OnDeserialization only happens for people receiving the data. So after you've done RequestSerialization you would need to also run the code that does the things with the variable.
also, don't do this where you have multiple flow going into one node. It breaks things. You already have a custom event there, so just call sendcustomevent continue
Ah ok, so for those events, could I use GetIsInstanceOwner on a branch that runs a sendcustomevent "continue" to ensure that it only runs the number addition once?
And for OnVariableChanged what I'm doing is checking each time there's a change to see if it equals a certain number, if it does then stuff run afterwards... (Pic below)
I'm kinda getting lost in your response though...
"OnVariableChanged happens for everyone, while OnDeserialization only happens for people receiving the data."
I thought OnDeserialization happens for everyone when RequestSerialization is run, just not for the owner of the script? Which I would have them run an event to do the changes with everyone else then...
So if I'm understanding your response, I would want to use OnDeserialization then since it's running through all of these to check the number it's on vs just one simple change like a bool on a door that's opening and closing?
So would something like this be better?
IsInstanceOwner does not refer to networking, it refers to the person who created the instance. So if they leave, then nobody will be instance owner. You should use Networking.IsMaster if you want the oldest person still in the instance to do it, or networking.isowner if you want the current owner of this object to do it
Oh ok, I thought IsMaster is outdated and read to use InstanceOwner instead
that documentation is talking about people who try to use IsMaster for things like opening a special door
Networking.IsOwner is more correct though because it more directly refers to the person who owns this object
also it looks like you're checking ContinueInt against multiple different things, but that doesn't matter. If ContinueInt is your only synced variable you can safely use OnVariableChanged
So if I had multiple synced variables that then all get changed...
I can do what I did in the original graph with OnVariableChanged, as long as I'm not stacking the variables?
Like if this number equals 3 AND this number equals 5, then run this...
And other than the IsInstanceOwner, this graph would be set up correctly for syncing, just make sure it's set to manual and the variable is marked to synced...and I could change OnDeserialization back to OnVariableChanged if I'd like too, otherwise it would be fine as is?
no no no, NEVER bring in variable lines from different flows like that. It is completely wrong and won't work at all. Variable lines from one flow should be entirely self-contained within that flow.
The reason why you shouldn't use onvariablechanged when you are using multiple synced variables is because they update one at a time. So you may receive one variable and it's changed even, then another variable and it's changed event, etc.
So if you use onvariablechanged for one variable and you try to get another variable, it may or may not have been updated already. But ondeserialization happens after all your variables have been updated so you can be sure it's the latest data.
If you do have multiple synced variables but the thing you want to do with one variable does not depend on whatever other variable is, then you can just do that entirely self-contained as well
Alrighty, yah sounds good then...
I think I got the info I needed and you have been a great help with serialization stuff, I've been working on an event for a while now that needs to be synced but things just kept breaking after I fix one issue...
With this info and the whole "Don't cross the streams" which may have been a big issue for me, I think I can get this to work now, thank you!
2022.4.1. released?
network process modified now?
in main server?
Hey there, I could use some clarification / advice concerning VRCObjectPools. I'm making a game that utilizes nav mesh agents with synced variables (mostly HP, as well as target destination, and a few others) stored in a VRCObjectPool. It was my understanding that VRCObjectPools mostly stored the active state of whatever was contained in the pool, but I'm having some desync issues where, when the owner returns the object to the pool, it's not always updating for everyone. I'm kind of stuck now, wondering if it's something to do with the VRCObjectPools? I'm about to start writing my own pool logic for the enemy pools but I'm not 100% sure that it's even the pool that is the issue. I guess mostly what I would love some advice on is whether or not what I'm trying to use the VRCObjectPool for is a good use case (objects that can be interacted with by other players that have multiple synced attributes). I'd really appreciate any advice. Thank you!
how do I send an argument over a custom event? I'm trying to make a gun, and I'm assuming I want to do the raycast in the owner's code, before the network event is sent, and then send the hit transform over the network event to all clients
is there a better way to do this?
Unfortunately there is currently no way to send arguments. The way most people do it at the moment is to use RequestSerialization+OnDeserialized to send events this way. When it comes to this, the serialization is atomic - so it will always be a full snapshot, as long as you're using manual sync.
Just note, when doing so, you can't have different sync modes for multiple scripts on the same gameobject - this includes the built in vrcobjectsync type - so you may need to make a dummy gameobject if you want continuous motion + manual firing.
Alternatively, you can do continuous, and just use the update of the data you want as that sync mode and set interp to none. Mixing interp modes won't cause issues.
Are their any good object sync alternative prefabs out there? Been having issues with vehicle sync using the default one, ever since the recent changes. Would also be nice to load it onto manual sync instead of continuous
I have basic object enable/disable syncing for late joiners, It's really simple to make, this is JUST the sync part, I have code offscreen to work the button but that's not needed
(sent this for other's who may be suffering the same fate I did)
that's not the proper way to do it, you're supposed to use synced variables which will handle late joiners automatically
you shouldn't use networked events for anything that has a long staying effect like a toggle, button, slider, whatever. It should only be used for things that have to trigger at that moment and won't have an effect on the world after they happened, like a particle or sound effect
most of the time you should probably use synced variables instead of network events
This is not the wrong way, this is a simple implementation if there are not many objects.
This is often even better because you don't have to mess around with the owner.
It is, you're supposed to use synced variables for states, doing it like this is not only pretty messy code-wise, it also doesn't guarantee that the state will get transferred properly in some edge-cases like when the master is on quest and the headset goes into sleep mode
If you don't wanna mess with ownership because you need a lot of people changing a persistent state at once, you should use a player object pool instead, but in this case that's not necessary because it's just a button toggle as far as I can see
gotcha, For now I'll keep this method cause it works but once I learn to make a better method i'll apply it
I'm looking to make a system where a player can pick up an object, place it down on a grid space, and a prefab can spawn there.
I also want it so that other people can see the object be placed there, and late joiners will also be able to see the prefabs.
I'm not really sure how to setup those systems, can someone help?
new udon version after vrc network update in my project causes terrible time lagging for all network script events. object sync works fine, but all scripts which send network events from master to slaves run events for them after improper time lagging. can not guess what causes it, because there is no any apparent errors. just any network event happens for other clients with lag over 1-5 minutes. pens write text by their own after using them, billiard is not working at all, because join event happens after 1-5 minutes. player may work only for 1 person in room, because url sync happens for slaves after too long time and clients have repeating of same video fragment in cycles. but the same version with old udon has no such problem at all. idk how to watch stack for vrc network transactions, because i suppose it is overflooded of some sync requests. any ideas?
cross post but man ive been getting back into udon the last few days and its come a long way. kinda curious though, has anyone done any experimenting with creating objects which sync "selectively" so to speak? For example, like an object pool which only spawns objects for some of the users on a server, rather than enabling it on all players' machines. I know the sorta "master authoritative" system vrc has doesnt necessarily lend itself to this, but i definitely feel like it could be useful. Right now, my main idea was maybe having some "unsynced" way of keeping track of whether the object should be active and somehow find a way to only send RPCs to wake the objects up for the appropriate players. However, if i were to target the objects owner, it would (at best) activate an individual object for each player rather than all objects for all players who have opted in, so that solution kinda falls apart. definitely a bit of a ramble here, but figured wouldnt hurt to ask what others have discovered!
Why would you want to not sync those objects for everybody
So in my particular case it is each player gets a collider that follows them around (if they opt into the system). However, rather than syncing the positions of each collider across the network (which would add a lot of load), I decided that since any given player already is receiving the location of other players, I will have the local player be responsible for making everyone's colliders follow the proper person on their own machine
So trading a little extra processing for greatly reduced network load. However, I would like to make it so that players that aren't using the collider system at all don't end up getting that performance hit from having to move around a bunch of colliders they don't even care about
Is it that much of a performance hit?
I would have guessed a bigger problem would be inconsistent positions of the colliders, though the disparity may be too small to be an issue
Hmm I guess it wouldn't be. I don't know much about udon performance but I recall hearing that it's quite a lot slower than normal c# and putting anything in your update function causes quite the performance hit (such as having each collider teleport to follow it's particular player)
But I could be completely wrong about that. I think the disparity should be small enough tho that it's not worth the network lag. What's important to me is that each player's collider is in the right position for other players. Which means that if each player's machine is teleporting all of the colliders to follow all of the players in the world (no object sync) they'll always be in the right spot for the player who needs to interact with them
Although that has me wondering if I even need the colliders networked at all, if I can just keep track of everyone who should have a collider and tell the opted in clients to instantiate a local collider for each of those players...I would need to do some stuff to help people who opt in later on
When using manual sync and request serialization, does this scale the owner's outbound traffic with the number of players in the instance?
Actually this would make the collider position more consistent, because it matched up with where the player is for other players, and normally in udon things don't arrive at the exact same time as other things like voice and IK
no it does not. You only ever need to send to the relay server once, and then that server takes care of sending traffic out to everybody else
hmm ok
notes the link on the vrc docs for the networking examples package doesn't work.
Hey, is there any assurance in terms of order of operations between SendCustomNetworkEvent and RequestSerialization() (assuming synced on one side, waiting for serialization, will everyone else receive those in the same order?)
manual sync serialization generally arrives faster but that can change depending on network connection, amount of outbound data, future updates, and the cycle of the moon. Don't rely on it
Shit, alright. Is there any common way to differentiate late-join state OnDeserialization vs an individual "request" of serialized vars? (I know of the local var "is first deserialization" trick but I'd hope there's a better option)
generally I'd recommend building architecture where you don't need to worry about that
I'm trying to solve some inconsistencies with object pools and assigning stuff to users (without cyan's pool) and I may need to build my own lol
I'm trying as much as possible but there's state of "is owned" vs "is not owned" which is separate to enabled/disabled
State is basically disabled -> enabled and not owned -> enabled and owned -> disabled (always in that order)
And encoding that into an array is kinda janky considering what I'm doing
I want ownership to be managed by the objects themselves, not the pool
Mmh... then again... I think I'm gonna go back and think over the architecture a bit more.
Thanks for the info!
yeah there's definitely ways to make that without caring about whether or not it's the first serialization
Okay so I'm trying to do a button (for a concert world) that play a sparkler particle effect. The particle system does not loop, it stops on its own after a few seconds.
My problem, however, is that the event doesn't seem to be sent to other people in the room, it only plays locally. Am I doing something wrong
I'm working on the same thing, this works
I'm in the dark how to make my lights change colour globally thoguh...been fighting with various methods for 6 hours with no breakthrough. Docs are too vague and no examples
My issue is that this is not a particle system that uses a bool. This is a particle system that plays once per-press, because it's not set up to loop. I have a few particle systems that do toggle, and those work just fine
OMG we need to share info, we are working on the same type of thing....hmmm, the only thing I can think of if it's not lasting as long as you want, is to make the particle run longer, or maybe there is a way to do a for loop to make it do it again.
I'm trying to press a button, that will send an int value to another script attached to the light, to make it change color. So far nothing works
no the problem is that, it works and plays right locally, but the cue isn't being sent to everyone else
The script I have basically is a toggle, press it once to start it, press it again to stop it. I suppose if you took the stopping part out, it would just turn on and end when the loop finishes (maybe) the sync is working on mine
an on-off toggle won't work here because there's no reason for it.
hmmm, so more of a push and hold and when you let go it stops?
hmmm
hmm I see you are using a particle array, I had no luck getting that to work, and had to just add one after another...I don't know if that would have anything to do with it
hmm so this changes the colour of the light, but if I sync the button, it breaks as soon as another button is pressed because you now have two buttons with different owners fighting with each other, I need to figure out how to make the light itself be the item that syncs, and not the button
I'd love to see what you are working on once it's published, it looks really nice
Used CustomNetworkEvent instead and it worked
I started the entire script from scratch and I'm still getting nowhere, I'm about ready to give up on this and just put a big huge warning saying don't turn on more than one realtime light at a time. and be done with it. The docs are far too vague on how this works, and with no example you are just left in the dark.
I've just wasted another 3 hours, I cannot get the stupid variable to go from one script to another, it does not tell you how to do that
If any one from VRC is seeing this can you PLEASE update the link to the example package, the link on the site does not work.
script on the actual light
script on the button
I don't know what I am doing wrong
Your logic is pretty terribly flawed. What you want to do is transfer network ownership of either const gameObject (or const this) or the UdonBehavior's gameObject to Networking.LocalPlayer and there is an event for on ownership transfer and then set variables in that event and then request serialization of this gameObject, not another script unless you're trying to set the variable of another UdonBehaviour. There is a method called like TrySetVariable if you want to set the variable of another script. Then, you'd RequestSerialization of whichever script you modified variables on and is manual sync.
As an aside, what you did wrong in your pictures (if they'd even work) is SetOwner wasn't passed a GameObject, so trying to set nothing as owned by the LocalPlayer. You also do nothing with GET Color[].length
This is just one attempt at this ive tried about five different things based on other scripts and nothing works, so I'm pretty much at giving up point. This stuff is way too difficult. Been fight with this for close to two weeks with no breakthroughs
I was trying to base it off the material changer script I posted several posts up but I can't get it to work, and do not understand what that graph is doing. Its just magic I guess π€£
I'm confused because I'm dealing with a light, not a game object and any doc's don't mention anything about lighting control or how to do it outside of am animator (sdk2 method) so I'm just shooting in the dark
Basically what I'm trying to do is have a set of buttons that will change the realtime light colour for everyone in the world.
I tried just putting a light for each button, and the having it turn one light on and set the rest to off, but this doesn't work because the ownership of the buttons conflict and just causes all the lights to strobe. I don't see a way to have it clear the ownership on the other buttons if a different player pushes one.
Using this example, what would I need to change on this graph to get it to change the color on a light, rather than the material on a game object. I assume the 'button' wouldn't be any different because all that is doing is passing the variable to this graph, but on this graph, I have no idea what I need to do to get it to deal with a light instead of a game object.
A lot of nodes are missing input values. I'd just recommend something like Udon# if you're more inclined to code rather than noodles since Udon is way more difficult to read and is basically just C# at its core
That's not the issue. It is completely valid to leave a gameobject, udonbehaviour, or transform instance blank and it will self-reference to the object that this script is running on
if all you want to do is change the color of a light, then you need to swap out the renderer for a light and use light set color
I think they're using like a central interface for each light
ok, so...I've modified this script, but I'm not quite sure how to implement that into this. This script does nothing when the button is pressed
currently they are all individual lights because it's the only way I can get it to work, but if someone comes and pushes all 6 of the buttons and turns them all on goodbye frame rates
trying this
<gasp> OMG the light finally changed colours....THANK YOU!
seriously if this syncs to other players you made my evening
it won't
I put that snippet in the above screenshot
it's the script I'm using for the material changer (which works) but I'm trying to apply the same concept to lights
there's another script on the button
and what does it do?
you set an int on the button that sends the number to the light, which has the preset ints for each colour assigned
oh, ok then yeah that would sync
So on the light you have an array of colours, that match the button integers
oh thank goodness
you should set that to manual rather than continuous though
right
I should probably do that on the materials as well (changes the backdrop)
Thank you again both of you for reaching out and helping on this, I appreciate it
if you want your lights to not be so expensive, disabling shadows will have the biggest impact
ok I'll try that and see what the effect is...it may not be needed for this particular light group as it's just ambient light
So the 'get component' is what is pulling in the actual variable? I'm just trying to understand what it's doing so I can learn from this π
get component is what gives you the reference to that object
ok, so it knows where to send the int variable to
yes
I see,I was fhaving a hard time finding an explanation of what that did in the docs
I'm not really a programmer, but struggling my way through it
most of udon is just based on unity, so you can look at generic unity tutorials like this to understand what components are https://www.youtube.com/watch?v=etTZYeTrpZU
Basics Playlist: https://www.youtube.com/playlist?list=PLzDRvYVwl53vxdAPq8OznBAdjf0eeiipT
In this video we're going to learn what a Component is, what it's used for and how it relates to MonoBehaviour.
If you have any questions post them in the comments and I'll do my best to answer them.
See you next time!
Grab the game bundle at https://un...
I've been reading throuhg some of the unity docs, but they aren't always overly meaningful
I will take a look at that video though thanks
the main difference is that instead of making a monobehaviour, you're making an udonbehaviour. And to create your code, rather than using C# you are using graph (though you can choose to use C# through Udonsharp)
right...I'm not that great with C#. learned Python.
heh, technically udonpie is a thing that allows you to code udon in python. But it hasn't been maintained for a long time and probably not super great
hmm never heard of that
well, regardless of what compiler you use you still need to be familiar with core unity things like components
yeah and the order
well, testing in world, I'm only able to get integer 0 (red) when I try to change it nothing happens, it works when I do build and test though...so weird...it hast to be close
Update on mine; I switched it to a CustomNetworkEvent and it worked fine now
@frozen igloo I'm not sure what has gone wrong but it hasn't worked since that first night. I'm so lost :( The graph is identical, I haven't changed anything, but it won't change colors anymore. I did have it always coming on the default '0' integer, but now when I change it it doesn't even do that. I have a feeling it has to do with the sync check boxes and the continuous manual thing, but regardless of what I set these to, it doesn't work. Nothing happens...No idea what I did as all I added was the additional buttons for the other integer values. (Argh!)
OK so I've got it getting the 'default' int set in the graph again, but the buttons that send a new integer to the light, do not see to be doing anything...nothing happens when pressed, so I seem to be back to where it's not sending the value to the light again
Just a quick little question, in U# are there still UdonSyncing issues with byte/sbyte/short/ushort/etc. or have they been resolved? The UdonSharp docs say they have issues, but I noticed some other parts of the docs seem to be a bit outdated so I'm unsure.
Thanks for pointing that out! Those issues have been fixed for a while.
Mind sharing which docs page contained the outdated info?
https://udonsharp.docs.vrchat.com/vrchat-api#synced-variables at the very bottom of this page is where it mentions the byte/sbyte/etc. syncing issues.
And https://udonsharp.docs.vrchat.com/networking-tips-&-tricks#known-issues mentions you cannot set synced variables immediately after setting ownership, I think that's been resolved unless I'm reading it wrong. If I notice any other outdated UdonSharp docs, should I make a canny post or just mention it here?
Hey, shouldn't OnDeserialization fire when a late joiner connects?
I'm having a few inconsistencies
i've got an in world log, and when OnDeserialization is fired it'll log "Deserialized"
but for late joiners, the text never appears.
this is my code:
public override void OnDeserialization() => OutLog.text += "\n Deserialized";
ondeserialization happens when you receive synced data, not just when someone joins. So there are a couple reasons why it's not behaving as you might expect. One of them could be that if the object has never sent any synced data. If it's manual sync and you've never sent requestserialization, then it won't always send anything. Though that's undefined behavior, sometimes it does send on it's own. Another reason could be if you are not the person who joined, you won't get ondeserialization. This was changed recently, as it used to re-send serializations to anybody when one player joined. But now it only needs to send to that one player
I understand those bits, but I could have sworn it would fire on the late joiners client when they load in (after some data's been serialized once)
Are you trying to log late joins with ondeserialization for any specific reason? Just curious since you could also use OnPlayerJoined
No, I need to know when data has arrived to the late joiners, but this event that should be for that doesn't seem to be working
Turns out I'm not getting OnPostSerialization when calling RequestSerialization. Is there a common reason for this?
iirc, OnPostSerialization only fires when you have other people in the instance (you can't be alone). I might be wrong but I vaguely remember hearing that somewhere.
I just ran into an "issue" (that's probably intended) where my udon scripts synced variables aren't updating if an ObjectSync is on the object and nobody is holding it. It looks like the ObjectSync is causing the object to sleep and stop sending network updates. I don't think this is documented behaviour, but it kind of makes sense for optimization. Anyone know of any way around it?
OnPostSerialization isn't exactly when clients receive data, just when your client bothers to pack the data to be transmitted and then send it off. There are no acknowledgement packets or waiting for a client to respond. Anything async needs to be implemented by you
I'd personally have a way of acking, however you want to do it
just make an empty game object as a child of that object and put your udon script on there instead
Hey, I tried that but it also didn't seem to work π©
Maybe you can make an empty object somewhere else (outside the objected synced 'object')
hmm, some sort of "manager". that could work!
Is your object active(enabled) all the time?
yup
Maybe it could be a bug. Developers did not have thought about using object sync with synced variables.
quite possibly. I should probably create a repro project and submit it. worst case scenario, they say "no its not a bug"
Even if it turns out to be a bug, it will take years for them to fix it haha
is the udon trigger world event over network fixed wothout creators having to name variables beginning with an underscore
or does that kid kirai still have this game crippled
@frozen igloo thanks man, I just implemented your method on my prop spawning system and it works great!
at least before i got banned i tested it XD π
What method?
this
ill make sure to credit u in my world
I accidently remembered Sacheverell helping me instead for some reason, I must have gotten you two mixed up somehow xd. When I have access to my account i will fix it.
@frozen igloo how does a player who IS NOT the owner of an object request ownership when the script is run on the side of the player without ownership.
TLDR during OnDeserialization a void is run which is needed to give ownership to a player, but because OnDeserialization doesnt run on the objects owner, ownership cant be transfered. im a bit stumped xd
You don't need to be the owner to setowner
i initially thought this, not sure why it wont transfer then
If you do NOT add the OnOwnershipRequest event, then anybody can transfer to anybody.
If you do implement OnOwnershipRequest, then non-owners cannot transfer to other non-owners. Non-owners can only take ownership to themselves. If you don't explicitly need the functionality of OnOwnershipRequest, you shouldn't use it because it changes how transfers work and adds more latency.
yeah thankyou, i had initially worked this out and use the request but it caused a bit of a logistical nightmare trying to have both accept it, that i then found out you didnt need to as i had other checks in places to ensure it was the correct players transfering ownership
i guess there must be something else in my code that is stopping it functioning correctly
can you elaborate more on what you're trying to do?
right gimmi a sec xd
basically, a specific number of player will have an icon above their head, these are synced objects and follow the player (this works fine), on start the player is checked for if there on the list, if this player is assign the ui to them, (using a synced object pool not the vrc one tho i tried using this with a copy of my code in udon graph but it gave the same result so i concluded it wasnt the fault of my synced pool in u#) the issue im getting is the first player (master) correctly get the icon assuming there name is on the list, the second player to join passes the checks but isnt assigned a icon
@frozen igloo i think i know what the issue is now, when a player joins the synced boolean array i used to store the states of each icon (have they been assigned or not) isnt being updated for new players before an icon is assigned
are you doing that in start?
on start im requesting serialisation on start
on the non-owner?
RequestSerialization is what you do when the owner has changed any variables, that's how you send data out to the other players. It's not used for other players to request latest data from the owner
ahhh okay gotcha
currently whena new player joins the master will request serialisation, during deserialisation it should be updating those variables
you don't need to requestserialization in onplayerjoin either. Late joiners will receive the latest data
all you need to do is call requestserialization any time you modify the data
okay ill give that a try now thankyou
OnDeserialization is the event that the late joiner gets when they receive the synced data, that's where you should build your UI or something
ondeserialisation rebuilds the ui after assigning the changed bools
or should do xd
what do you mean "after assigning the changed bools"
could you show some examples of what exactly you're doing?
so when a player is assigned an icon a synced bool array[itterator] value is assigned, then for the next player whos elidable to receive one would take [i+1] icon
ill run a test with some stuff changed to what you previously mention then if nothings changed yeah ill send you the code snips
also i think i need to change some logic and it should work
@frozen igloo ive found the issue, when a new player connects the [UdonSynced] public bool[] isnt updated, even when the master requested serialisation before the player joins
can you share the code where you're creating that array and trying to use it?
haha yeah im trying to workout the best way to show you xd
just a pic
Please die
?
@urban birch
hahaha
well, one thing is that you never take ownership of the object this script is running on
and you do have a player.ismaster check but it's inside two for loops, so I'm a bit unsure what exactly that's supposed to do
also what is sf_state supposed to do if it's just a bool? If that only indicates whether or not it's active, don't you need to also sync which player is at which index?
yes thats already being done, the master check was for if the first player to join is the master AND on the list it needs to run differently or i got some weird issues, and does this script need to transfer ownership as when the method is called the VRCPlayerAPI player is given as the new player
is this being ran from onplayerjoined?
i stop doing that when you said earlier, im now trying something again using it
The variables that are being passed around have absolutely nothing to do with who the owner is
unless you're specifically talking about the OnOwnershipTransferred event
okay cool, ill keep trying stuff thanks for the help
i feel like ive been going in circles with this for 3 days revising the code constantly to get the same issues
what could be the issue when SendCustomNetworkEvent gets called, but then the function its supposed to trigger never fires (play in editor works fine but in build&test it doesnt)
i made sure its the correct name, is it because its an instantiated object?
Yep, that's exactly it.
π
i hate this
Welcome to networking stuff. You gotta create a pool of pre-prepared objects if you want to spawn them.
this means i gotta prespawn thousands for a big player sized world π
for most of them to probably never be used
what's your use case that would need thousands?
fish system, for example if i wanted 40 max players, have multiple bodies of water with different fish to catch, that the player can hold for an infinite amount of time untill he decides to turn them in for a reward
so there's a couple different optimizations you could make. First of all, you don't need to make a whole pool of objects for every single different type of object. You could instead have a single large pool of something like 100-200, and each object in that pool can transform into any template you want
the other thing is, if you have a whole backpack system, there's no need to store the actual object. Just store the data representation of that object, and release it back to the pool so it can go off and be something else while it's stored away
what if all 80 players decide to hold on to atleast 10 fish
you could also implement a stacking system
it's not easily possible to hold on to 10 fish anyway. You only have 2 hands
you can let go of them
so if they're on the ground, you could have them despawn after a period of time
they kinematic
you should definitely have some kind of cleanup routine regardless of what you do
and that argument applies to any kind of pool you do anyway
which even then is silly because if 1 player just wants to chill in the world by himself he now has to preload everything
preloading 200 props is a lot better than thousands
i think i went over this, it would have to be way more than 200 to cover all cases
200 is also still a silly amount
you're welcome to adjust that number up or down as you need
and that's one of the benefits, it's a lot easier to adjust that one pool rather than adjusting every single fish's individual pool
but that limits players being able to possibly catch a certain fish
so does any pool you do
and thats why i hate pools
well it's the only option
unfortunately
It's not that bad, and besides I personally enjoy working with a template system where every single possible item can be represented as data. When you're working at a large scale, that helps to keep things sane
Won't 80 players + 800 fish at the same time give you more performance issues than the trouble is worth? Those seem a bit unrealistic to me.
Also, at that point, it's probably better to solve the problem by designing around it. Like giving people easier access to trade their fish. Or let them transport the fish in an easier way.
I also agree with Phasedragon, having that many objects spawnable and synced with each is only possible with a pool of generic objects.
For fishing you'd probably want to take an animal crossing approach where they have a few fish shadows visible near the fishing rod and then when you reel it in it generates a random fish, all stored as numbers instead of gameobjects.
very good point. You really shouldn't be in such a situation in the first place
again, whyyyy would you ever have all 80 players like.... laying out their fishes on the ground in front of them
each player having a backpack with 10 fish, by all means though. That's why it's so important to be able to represent as data, so that things inside backpacks don't take up space in the pool
and this yeah, it would be a lot of bandwidth to sync all positions. You'd have to test it but you'd likely hit the limit
also consider under which circumstances you'll actually hit 80 people. That level only really happens in unique, organized events, like community meetup. If such a thing happens, you can temporarily increase the pool limit. But under normal circumstances you can have a more sane number. With 40 player cap, even the most populous public worlds stop around 35 to 40. And those are worlds where the design is to hang out around a mirror. Game worlds don't get nearly as many because there's simply no reason to be in such large instances when you want to play a game
i just like to cover all possible cases π
You could reduce the cases by lowering the player cap
but that does not fix my underlying issue
what's the underlying issue?
that i have to copy paste a bunch of objects, and that people have to preload something big when its not needed
those issues are exactly what a generic pool would fix though
once you have the generic pool set up, you never have work with pools again
you only work with templates
If you know how you can sync instantiated objects
I do it in my world I'm working on, I might release the instatiation system as a prefab one day
Can only instantiate Kinematic objects but can sync and instantiate thousand or more of them
The problem usually becomes the fact that once you reach some amount of objects it starts lagging your game hardcore with how many objects you get
I'm having an issue where a synced switch via a button, will work the first time a player presses it, but if they go to use it a second time, the button has to be pressed twice to get it to do anything...Any ideas what might be causing this?
I suspect what is happening is the bool is set to true for the person being the owner, and when they go back to use it again, they are still the owner so then it sets them as 'false' not the owner and it doesn't work until it's flipped again, I don't quite see how to just keep this variable as true whenever the button is pressed, rather than flipping it.
aha, this seems to work
Not really a question but more of a enquirey. How many object syncs on Ridgidbody objects can you have before networking becomes unstable
And does this vary with peoples internet and ping
While this isnt a direct answer, this should help https://docs.vrchat.com/docs/network-details
Try not to sync everything; consider what you can determine from the minimal amount of information shared. For example: if an object will move on a fixed or predictable path, then its position may not need to be synchronized and instead its initial location and velocity may be sufficient. If there e...
Does anyone know the max amount of public functions a udonbehavior can have?
You probably get hit by performance before you hit max anyways
I'm not sure if this is the right channel to ask this but I have a question regarding transferring data in and out of VRChat.
Is OSC the only way of achieving that or is there other protocols that can be used?
Udon can receive MIDI
But it can't send MIDI?
no
:/
but udon can write to the debug log, and you can make a program that reads the log
Yeah I get that, you can do a lot by running a extra program but it's not very accessible since it requires you download something extra
well you are asking about ways to get data in and out of vrchat....
having an extra program to send/receive is kinda the baseline there
I feel like that's very basic functionality.
Being able to get data in and out via various external apis and different protocols are building blocks of the internet.
But VRChat is completely gatekept, and doesn't even a way of any kind of IPC between different worlds from my current understanding.
FYI: There is a feature request for Web API stuff https://feedback.vrchat.com/vrchat-udon-closed-alpha-feedback/p/vrchat-udon-web-api
arbitrary web api access is intentionally restricted
Would be nice if someone from the VRC team then could comment that feature request. By votes it's really popular
They're currently working on remote string/image loading which is a step in the right direction
Yeah it's intentional gatekeeping, and the reasoning or rather lack of, is complete ungrounded since everyone in the world has access to a browser and basically is constantly interacting with arbitrary code and data.
And there is almost zero security issues, if some basic standard security measures are taken in place.
Well, there is a bit of a privacy issue. Http requests to someone's private server could log your ip address, which at least narrows your location. Cookies, if allowed, coud be used to track you, etc.
BUt it would be nice if they could, I dunno, offer some limited form of web service hosting that is curated. But that would eat resources the company doesn't have.
you need special deal with VRC to get that
ip adresses can already be grabbed with video players, since they're also making http get requests
https://ask.vrchat.com/t/developer-update-15-december-2022/15518 though I'm pretty sure they're already adding "api" support in the future but idk how limited it'll be, since they call it "Remote String Loader", hopefully it won't have the dumb restriction of not being able to make urls at runtime without the VRCUrl input because that makes it a whole less useful than it could be
Welcome to the Developer Update for December 15th, 2022! If youβd like to catch up, you can read our previous Developer Update from December 8th. This is the last Dev Update for us until January 12, 2023! After this, weβre on holiday! Despite some of the team taking time off, teams like User Support, Trust and Safety, DevOps, and other tea...
Yep, I thought about that after saying my line, but that's what the "Allow Untrusted URLs" setting is about. Lets the player decide their risk tolerances, rather than it being decided for them. World webservices might be less obvious than a video/media playing.
You won't be able to make URLs at runtime for sure, I can nearly guarantee that.
that's such a shame
Hey guys, really simple question I can't for the life of me remember the answer to - Does the VRCPickup script automatically sync events triggered by their use method?
no, it does not
Ah cool beans! Thanks
Hi, I'm letting a plane follow the player in my world, but the player self can not see it after not moving for 2-3 seconds. While other players can. Does anyone know why?
what method are you using to move it?
like this
can you rephrase your original question? I'm not quite sure what you're asking
I set a Plane object to follow the player when they enter world. But when player is not moving for a while, the plane disappear to himself, while all the other players can still see the plane.
but if this is following the local player then "the local player" should be everyone
so are you talking about the first person who joined the instance?
do you have any other nodes in that graph? Maybe something is causing it to halt
On the beginning, yes. I used SetOwner for following players, but they all have same issues.
no that's all
does this have an objectsync on it?
yes
ah, this code is probably interfering with that
right now everybody in the instance is setting it to their own position. So that's fighting the objectsync, which is trying to move to the owner's location
if you want this to follow the owner, then you should remove objectsync and use networking.getowner instead of localplayer
Ok, I see. Thank you very much!
Weird question: How many SendCustomNetworkEvents per second do you think are acceptable for a world? The player count will probably be limited to the single digits.
It really depends on the quality of network of the people in the instance, how far they are away from the region server, etc. But if you're doing less than 10 per second you'll be fine. Though you can send bursts of hundreds or even thousands as long as you don't do that continuously
That being said, you should probably make sure that there's a good reason you're not using synced variables first, because that's going to be significantly better and easier to work with.
I'm trying to build a simple tower defense. I wonder how many enemies and towers are acceptable. Every enemy and tower has different states like moving, standing still, attacking, etc. I'm not sure if synced variables are the right tool for that kind of job. I think most network events are changing the state of an enemy or tower. Since every enemy and tower can change their state on their own, I wonder how many is too much.
no, that's exactly what synced variables are for and exactly what network events are not for
Is there somewhere a good doc how the synching of the variables work?
Like how often etc
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...
There are a couple unique things about network events. One is that anybody can send them as opposed to synced variables which only the owner can send. Another is that late joiners don't receive them. Those details make some rare situations require a network event. But in most cases a synced variable is more appropriate.
Oh, I think RequestSerialization is the way to go then?
yeah, that's when you're using manual sync. Manual sync is pretty much the best way to sync. Continuous exists for some situations as well but generally you should default to assuming manual
manual > continuous > events
Ok. Alright, I think I've got the gist on how many syncs are Ok. Thanks for the answers!
I'm using a desynced station to try and create the illusion of a ring space station type world. I'm keeping track of the player's location using synced objects but I'm seeing this really choppy behavior on the remote side. I'm new to udon and networking so I'm not sure how I should go about making this better
what are you using to sync it? continues, manual or VRCObjectSync?