#udon-networking

1 messages · Page 13 of 1

finite sierra
#

you just change the values of the tower in the editor. for each instance.

twilit pewter
#

Network Ownership is a 5 way handshake with all players and I can't be requesting a new owner for every shot that gets fired between 20 players and 50+ enemies. This is the most performant alternative to resort to using SendCustomNetworkEvent over attempting to rapidly update a variable from local only projectiles.

twilit pewter
finite sierra
#

your litterly creating a tower. cannon whatever it is

#

what exactly are you trying to make even?

twilit pewter
#

The result is a unique cannon and damage method for each combo of cannon and damage.

finite sierra
#

what exactly are you making? or trying to do. each cannon is what? and what do they do to a player?

twilit pewter
#

The hit enemy basically calls the corresponding function to relay how much damage it has taken and how much enmity that player must now have for that enemy.

finite sierra
#

you dont need to do any of that. what you are trying to do is well odd. you never change ownership of a projectile.

twilit pewter
#

I'm not

#

Projectiles are local only.

finite sierra
#

as everything else is

twilit pewter
#

The enemy being hit needs to share over the network that it was hit with how hard and by who.

finite sierra
#

for what purpose?

#

if you hit an enemy it just needs to locally know it has been hit. and update it based on that

twilit pewter
twilit pewter
# finite sierra if you hit an enemy it just needs to locally know it has been hit. and update it...

That won't work if multiple players are shooting it and needs to respect that its been hit by each. With projectiles being local only, I don't need to sync projectiles. Projectiles will not be accurate anyway given latency, which would cause desync if I tried relying on them. It must be shared via SendCustomNetworkEvent when the local player has managed to have a projectile from their cannon hit the enemy.

finite sierra
#

it will work. if you update it when you locally hit it. just update the Hp of that enemy. based on that you dont need to update projectiles or show other peoples projectiles.

#

also no games ever sync projectiles. its based on various hit scans and other methods

twilit pewter
twilit pewter
#

Basically it boils down to an enemy being hit.
I hit the enemy with my local projectile, now the enemy must relay to other players that I hit it, both with how hard I hit it and that it was me who hit it.

finite sierra
twilit pewter
#

SendCustomNetworkEvent cannot contain arguments, so that means there muat be a unique named method for each combination. This script generates those.

#

I'm looking for something that doesn't have to generate a new script with these via a string and duplicating compiles.

#

Like this is super cursed and I deeply wish for a better solution.

#

While it works reliably, I wish no package to ever include it.

finite sierra
#

there is no need for that either.

twilit pewter
#

Awesome!

#

That's what I want to hear

finite sierra
#

you just need to update it locally. and whenever a change happens to something make sure to sendcustomnetwork event

twilit pewter
#

That's why unique methods for SendCustomNetworkEvent is necessary.

finite sierra
#

its not..

#

again

#

that many methods is extreamly bad and not going to work in the end. it only clutters everything and most likely will overload udon.

twilit pewter
#

It works and keeps 90fps in VRChat with 30+ people

#

That's 20 people shooting cannons that may be the same target.

#

These aren't one hit kills

#

I'd use synced variables if they weren't as costly or prohibitive via needing a change in ownership

finite sierra
#

that just shows me its one person and locally.

twilit pewter
#

It's the recording I have on hand, I can share the world id for you.

finite sierra
#

it will never work in an actual online setting.

finite sierra
#

a cannon does not need to know how many times its hit or who. all it should be concerned about is when it gets damaged to share its health to everyone else.

twilit pewter
#

It does

finite sierra
#

why.

#

a npc never needs to know those things

twilit pewter
finite sierra
#

no

twilit pewter
#

It's not only health that's each enemy cares about.

#

Enmity as well

finite sierra
#

what is Enmity

twilit pewter
#

Enmity is a priority list of who the enemy needs to target.

finite sierra
#

and thats based on what

twilit pewter
#

Based on who has damaged it and by how much.

#

Each shot isn't strictly 1 damage. There's 4 values of damage that it could be hit by.

finite sierra
#

that can still be done locally. you just check against a threshold that type of an npc has. when X has dealt enough dmg to go over the threshold send out to everyone else who the new target it and they will target that person

twilit pewter
#

If I use just one single SendCustomNetworkEvent, how will I manage to share what value of damage it should take and who is doing the damage?

finite sierra
#

that doesnt matter. you check that locally.

#

when someone locally has done enough damage

#

if someone else has done locally that much dmg it would switch to that person

twilit pewter
#

If I'm not tracking other players hitting the enemy, how will I know they hit it?

finite sierra
#

locally.

#

you just make sure that each npc is the same across all people in the world.

twilit pewter
#

I love what you're promising and I trust that you're heading in a good direction, I'm just struggling to follow.

#

What you seem to be reaching is using a race condition?

finite sierra
#

sorry i am not always good at explaning lol.

#

imagine you have 4 players okay?

#

and lets say 32 npcs

#

you start the round and let them do what they need to by it shooting a player or something else.

#

lets say all 4 players shoot a different npc each

#

and say that player 3 has done enough damage to a single npc to meet the threshold

#

then that npc sends out a networked event to everyone else that it and every other npc is now targetting player 3

twilit pewter
#

Right!

finite sierra
#

you just need a single string or a int. that is UdonSynced

twilit pewter
#

Who is updating the synced variable in that case?

finite sierra
#

and check against that against a list of players in the world to find the proper target

#

the local person

#

who dealt the dmg

twilit pewter
#

That means changing network ownership is necessary.

finite sierra
#

well everything in a world is by default owned by the first person in the world.

twilit pewter
#

Yes ^.^

finite sierra
#

you can change the npcs locally known owner to the local owner.

#

on start that is.

twilit pewter
#

That's a 5 way all player network call each time it needs to be updated.

#

That's way more expensive than using a SendCustomNetworkEvent

finite sierra
#

your missunderstanding it

#

only one person calls it

twilit pewter
#

Ah!

finite sierra
#

everyone else gets updated based on whatever that local person updates it with

twilit pewter
#

So SendCustomNetworkEvent is a relay to the owner to update the synced variable. I've done that before.

finite sierra
#

you can target Owner or all

twilit pewter
#

Yep

finite sierra
#

the local npc targets you. the owner. which then sends out to everyone else what needs to be updated

twilit pewter
#

That checks.

finite sierra
#

and every other person then updates it based on it

twilit pewter
#

How do I tell the Network Owner how much damage I did and that I'm the one who hit the enemy? As is SendCustomNetworkEvent is anonymous.

finite sierra
#

that one allows to use parameters

#

locally you do that. its all known locally only until you tell it otherwise

#

since u techincally dont need to know how much dmg someone else did . unless you want to track that to.

#

but that might not be possible with vrc

twilit pewter
#

That means the Enmity list can't be facilitated then.

#

If I'm the network owner, get the SendCustomNetworkEvent, how will I know how much damage to sync and who shot it?

twilit pewter
finite sierra
#

if you want to keep the health updated for each npc you will run into a limit of vrc.

#

we can only do roughly 200 bytes continuously which isnt that much

#

and roughly 11 kb a second

#

but i suggest you try to use the thing i linked above

twilit pewter
twilit pewter
#

Was a best guess essentially.

#

Compared to a byte for Health and more, seemed to be worthwhile to minimize network traffic as much as possible given how rapid enemies could be hit with a lot of players.

#

Changing Network Ownership > Updating a Synced Variable > SendCustomNetworkEvent

vapid pagoda
twilit pewter
#

Exactly

#

Talking in terms of cost given 11k bandwidth

vapid pagoda
#

Network event callers works nicely if you index every npc and simply sync the index and damage parameter, then apply it on every client

#

Afaik it has also been optimized to reduce as little bandwidth as possible

twilit pewter
vapid pagoda
#

Its what im doing in zombie survival

twilit pewter
#

My thought was that even updating a variable was more costly than SendCustomNetworkEvent.

#

I do imagine that would be more accurate and less prone to desync.

vapid pagoda
#

Dont over optimize, too much, only where it really matters

twilit pewter
#

That's why I didn't care too much about desyncing. Just a best effort.

vapid pagoda
#

And thats mostly the world geometry itself

#

Hmm, i think changing ownership constantly has its own downside, especially if you sync positions too

twilit pewter
#

I agree. I'm not changing network owner and just updating the health and target essentially. There's an enmity list I keep local only.

#

The current target just pulls from the network owners local enmity list.

#

Logically, the player in the instance the longest should be the most accurate anyway.

#

The Network Owner gets the SendCustomNetworkEvent, and then updates everyone else ideally.

#

Takes what would have been a 6 step network handshake and lowers it to 2.

vapid pagoda
#

Hmm interesting! Though youd need to create a new method for every damage variable

#

But if you only have a few, i suppose it should be fine

finite sierra
#

you do not need to create a new method what so ever.

twilit pewter
vapid pagoda
twilit pewter
#

It does make me want to go back to the drawing board and see where I could rely on UdonSync more, but that isn't feasible in the case of what I originally asked.

#

I know I can use UdonSync more and have practice in that. I'm hoping to reduce the network handshakes from 2 to 1.

finite sierra
twilit pewter
#

SendCustomNetworkEvent = 1 handshake
Updating an UdonSync Variable = 1 handshake
Changing Network Owner = 5 handshakes

vapid pagoda
twilit pewter
#

This is the cursed automation in question.

vapid pagoda
twilit pewter
#

Thats even worse I'd imagine lol

vapid pagoda
#

but keep in mind, more public methods, create more look up time in udon

twilit pewter
#

Right. Another cursed alternative that provides two variables still, explicit deny on RequestOwnership with further scripting. Not humoring that though since it understandably generates network garbage.

#

Really just need a simple argument in SendCustomNetworkEvent

#

Would make this far more reliable and avoid this discussion entirely.

#

I do think Udon 2 has a solution though. Native Player Networked Objects would give us a proxy we could use.

#

Absolutely can't imagine there'd be a better alternative and makes arguments in SendCustomNetworkEvent moot. Just sync variables that the player already owns and relay that to the targets.

#

I do think that's what HostileLogOut was building up to, but no use of SendCustomNetworkEvent is needed in this case, keeping the handshakes to 1.

#

Super hyped for Udon 2 since this will be rendered obsolete for what will be made native.

cerulean zealot
#

my health system for my NPC works entirely different lol

#

I base it off D&D where the DM is the owner of the NPC and keeps track of damage. but in an action cycle kind of way.

random breach
#

can someone help me pls. i want to make it so this "punisher" mesh spawns on the for every person who joins my world but its not tracking the player. It's spawning i a clone but not tracking

strange token
#

That might be your issue here

obsidian python
#

instead using the Instantiate, VRC object pool would be better for that I think

frozen igloo
#

It doesn't need to be synced, and it doesn't need to be in a pool. Instantiating is the correct plan if you want to be able to see other people's, but those nodes are just not properly handling it

finite sierra
finite sierra
#

@frozen igloo btw i dont assume there is a way to have the data sync that happens when someone rejoins to be disabled? so you can handle it yourself instead? or is it possible to overwrite it?

random breach
random breach
random breach
random breach
strange token
#

Oof ima wait for phase cuz I’ve no clue tbh, I don’t read graph very well

finite sierra
random breach
finite sierra
#

precreate all objects in the editor in unity.

#

each player then should have a array of those objects. and when someone join. then get the array of VrcPlayerApis. and assign the objects based on the order that has.

#

then you can locally for each person update your their local objects position to where they are

#

oh and remember to set Network.setowner for each object to that person to

random breach
finite sierra
#

eh yea. you just Create a 3d cube in the editor. and copy it til you hit the desired amount

#

also if you need to learn how to code you may need to look up some tutorials on youtube @random breach

random breach
#

no yeah i definitly know the basics but the only think i was struggling with is which node makes, the object that spawns on each player, global so everyone can see.

random breach
finite sierra
#

thats because you either did not have a object for that other person and you prob did not set the ownership that that object to the other person.

random breach
finite sierra
#

no. cause u only update local. u need to update the non local person

#

which u can get through who owns it

random breach
#

ohhhhh ok so which networking node is for non local players ^_^

fringe creek
#

Should I avoid setting synced variables on an object if the player is not the owner of said object? As in should I instead rely on the deserialization logic?

tulip sphinx
#

you cannot set any synced variables on object you dont own, be it continuous or serialization.

fringe creek
#

Good to know, I was under the impression that the variable would just be set locally until the next deserialization occurred

normal sonnet
#

I've been reading the docs, and I'm a little confused about preserialization

In the past I've made local sliders that update the value of a separate material with a single manual synced float. Only the master could use the sliders, and I didn't use preserialization, just manual sync, request serialization and ondeserialization.

On this new setup, I'd like to have a single trigger that pulls all the slider positions of the master, updates a bunch of floats based on that, syncs them to everyone else, and updates materials based on the floats. Which step of that would I want to use preserialization on?

frozen igloo
# random breach does this look right for everyone to be able to see the object globally?

If you want to make it so you see objects floating over everybody else's head, then what I would recommend is this:

Create two datalists: one for tracking all players and one for tracking all objects

OnPlayerJoin

  • Add player that joined to the player list
  • Instantiate an object from a template
  • Add that object to the object list

OnPlayerLeft

  • Find that player's index in the player list
  • Remove that player from the player list
  • Use that index to find the associated object in the list
  • Destroy that object
  • RemoveAt that index in the object list

Update

  • Use a for loop to go through both lists at the same time
  • For each item in the list, set the object to the player's position

Let me know if you have any specific questions about how to do any of these steps

frozen igloo
# fringe creek Good to know, I was under the impression that the variable would just be set loc...

You are correct, that is what happens. Technically there's nothing stopping you from doing it, but it is quite messy. Usually if you need to have some kind of local cache that can differ from the synced data, you'd be able to handle it much better if you had those be two separate variables. Then when a serialization comes in, you can compare the synced data with the cached data and decide how to handle the disagreement

fringe creek
frozen igloo
#

if it's a really simple system where you always want the incoming data to override your local state with no additional considerations, yeah go for it

frozen igloo
# normal sonnet I've been reading the docs, and I'm a little confused about preserialization In...

OnPreSerialization is just saying "I am about to send data" which means it's your last chance to grab the latest data or package it into some format you want. You don't need to use OnPreSerialization, the alternative is just grabbing that data at the same time as you do requestserialization. One reason you might want to use OnPreSerialization for that is if grabbing data is kind of expensive and you're doing requestserialization a lot, so you don't want to cause a bunch of hitches every time you might send data, only cause a single small hitch when you actually send data

cerulean zealot
#

Preserialization is great for scripts that grab variables from other scripts when activated.

#

Like packing things into a neat box for the postman.

#

I then use PostSerialization (only executes for the owner of the object) and Deserialization so things execute on clients "at the same time"

normal sonnet
frozen igloo
# normal sonnet omg dragon 🥺 🌺 Thanks for the explanation ❤️ you too pika~ I didn't know abou...

If you don't have a strong reason to, you don't need to use onpreserialization. Could just set synced floats inside the interact.

Also, you don't need postserialization, that is simply a confirmation that things have been sent. It's like a receipt and only the sender gets it. So similarly, you could just set the materials to match the sliders directly in the interact as well.

Or, alternatively, I like to have an "ApplySerialization" function, which is not an official thing, it's just a name for a custom event. In that function is where I'd set the materials to match the variables. Then you can call that function both from the interact and from ondeserialization, and everyone will run the same code all in one place

echo pasture
#

So I have an udon script that is supposed to steal ownership of an object. Now two players can steal ownership from each other rather quickly (within a fraction of a second). I've found that after stealing ownership from each other several times (i think around 8 times) the ownership breaks down and both players becomes owns of the object (so it becomes a local object) and ownership can no longer be taken because any attempts to take ownership are ignored with the following message "Ignoring TrySetOwner attempt on [GameObject] because [playerName] already owner". Has anyone else experienced this issue?

finite sierra
echo pasture
# finite sierra sadly it can happen. you have to put in a delay for it. so its not spammed and y...

unfortunately i don't think i can add a delay because being able to take ownership quickly is a crucial part of the behavior i want to emulate. I do my own check to see if the player is the owner before taking ownership, however it also appears the the SDK also does this check as well because it gives me the message about ignoring TrySetOwner (in my previous post). I think the best i can maybe do is bank on a third player coming by and stealing ownership from the other players if such a situation ever occurs, and also give a warning that such a thing can happen.

frozen igloo
echo pasture
# frozen igloo Is it critical to take ownership quickly, or is it just critical to send data qu...

it is critical to take ownership quickly. The behavior i'm trying to emulate is a weeping angel kind of behavior where the object can move and hunt down players that have looked at the object. The last player to look at the object is the player that gets chased so it is critical for that player to have ownership of the object and receive the most accurate/up-to-date position. The situation where ownership becomes a problem is when two players are looking at the object and one player (lets say player A) rapidly looks away and then back at the object. In this scenario Player B (who is still looking at the object) becomese the target/owner of the object, and then Player A becomes the new target/owner when they look back at the object.

stone badger
#

I'm going to suggest that folks endeavor to create test projects and/or game objects that can be used to test these sorts of networking things. I see questions similar to this but never (I believe) see any definitive answers. If there are limits (and there are) then a test system that a) demonstrated it, be) could be tested by others and c) used as a basis for workaround solutions would seemingly be useful.

#

Whether a solution works (or not) or works well can depend upon a lot of factors, not the least of which is the code being used. Doesn't it sound reasonable to develop these types of standardized test systems?

obtuse echo
#

Otherwise yeah, I'd agree to use player owned objects and then use everyone's is looking states to resolve the weeping angel state

waxen meadow
#

Hey how do make it so a bunch of different triggers change an int in an animator? I tried this but its not working? the whole thing im trying is having different parts of my world teleport a tv to it using an int animator (im new so anything would be great!)

obtuse echo
obsidian python
#

this is how your animator should look like

waxen meadow
wooden saddle
#

is there way make world Udon script where visitors cant join or put any rank visitor or below in jail room by default?

timber ferry
#

and that sounds like it would be against TOS anyway

wooden saddle
#

that's sad because that would solve crashers problem if Vrchat only take note from my request to add group shields us the did for avatars the can do it for group instances edit ranks that can join 😑

jaunty fjord
#

You'd be better of setting your Safety settings so that it doesn't show the avatars of Visitor rank users

wooden saddle
#

that dont help clients can crash you even if you in safe mod

#

and banning them dont help the can always make new account so i have to always ban any one that got visitor rank every time my group ban list getting big lol

strange token
#

I’ve never been crashed by a robot avatar… what

wooden saddle
#

all the need join lobby and crash every one in that world

#

happen to me many times

#

or brakes world colliders and no one can click on any one

lone zealot
#

The most important point being that you are only allowed to "Apply a moderation to a user that is misbehaving in that given instance"

#

If you have problems with a user like that, then I recommend opening a ticket with the VRChat Trust & Safety team and not try to take matters into your own hands

wooden saddle
#

the problem is you never know whoy crash world

#

so i have to ban all visitors

lone zealot
#

Also this is the wrong channel for discussions like this...just fyi

sinful mango
#

So ive made plenty of worlds in past but im just looking into a whole new segment of networking and NPC's, trying to start basic with statcis NPC's heads tracking a player in proximity, anyone tackled this before or have some insight?

cerulean zealot
#

@sinful mango hello!

#

yes. I've been specializing in that area

sinful mango
#

Oh? Super! please enlighten me to it, im struggling to find any major source on the matter, and my tests have been less then succesful

cerulean zealot
#

ok, first things first, what do you want to achieve?

sinful mango
#

so my want atleast currently is to have npcs look at the player within a vicinity, i have them all animated as i have 6 around a world but to add some interactivity im wanting them to look at a player if they get close, local ofc

cerulean zealot
#

So players will see the NPC looking at them, but not NPC looking at others, correct?

sinful mango
#

Mhm, i think it would suit better in this case

cerulean zealot
#

The code for that is this simple.

#

ok, so, obviously there is a threashold that players will cross, or get near, where there is a boolean flipped that will allow all this to happen.

#

you want a aim constraint on the headbone of the NPC, and you want to use the GetBonePosition of the head bone on VRCPlayerAPI

#

and have that be a target of the aim constraint.

#

This is your LERP that will adjust the time from 0 - 1 and then back to 1 - 0 this will allow you to set the weight of the aim constraint between look at the target to default neutral.

#

from there it's just setting wieght

#

All of this you want to make sure it's run on POSTLATEUPDATE because that is after when the IK solver has been executed on vrchat.

sinful mango
#

vrcTupStare I admit im regretting my choice here, ahh its been too long since i touched udon.

though by looking through this is a much more interesting method, i was using an idea of adding a look at constraint on the npc and using a get.postion of a player to activated based on a local collision or radius, but this seems far more accurate, not that i fully understand it admittedly

cerulean zealot
#

This is a method of having the NPC turn their heads toward a player and look at them in the eyes. Then turn their heads away when done.

#

if you want your NPC's to follow the player, reguardless where they are in the map, you can go with your method.

#

there is a second part of this code, that checks for distance between the NPC and player, and also checks for angle difference betwen neck and head bone, that will issue the exit command when a threadshold is reached. This prevents heads from spinning 360

sinful mango
#

vrcTupCry I think your method is far superior here, and moderatly less terrifying, i dont suppose by chance you have a slightly clearer pciture of the left half do you? i cant fully read which some are for reference apologies!

#

or by sheer chance if youd be up for helping guide me through this crash course on hand XD

cerulean zealot
sinful mango
#

🙏 thank you so much there!

cerulean zealot
#

Here is the additional code that checks for distance and angle to switch off the aim constraint if a threashold is crossed.

#

it needs to be on update for some reason. It has to do with reading transforms in unity

sinful mango
#

strange indeed vrcBotThink

#

well for my rather small knowledge on all this, alot of these must be variables with custom names to help differentiate their use and context through the graph, I think i can can do this..staying positive

cerulean zealot
#

a tricky "Gotcha" trick with Constraints is that you have to set transform that is going to be looked at as a constraint source, THEN set it as a constraint source on the aim constraint. THEN set the weigth of that constraint source. It has to be in that order.

#

im glad your doing local only cause getting other players to see NPC looking at other players is a WHOOOLLLEE other bag of worms

sinful mango
#

vrpill This already is a massive bag of worms pika....like dear god ive made a mistake in wanting to try this

#

this is currently putting my brain on meltdown mode

cerulean zealot
#

haha...yeah...

sinful mango
cerulean zealot
#

this is rather simple compared to...uh.... getting players to see NPC looking at other players...

sinful mango
#

holy

#

this is why there is no god

#

XD

cerulean zealot
#

nah, i lie, that is just the code for "NPC to navigate to pickup object that has been thrown and interact with it."

#

🤔 I should make a wall.... in my world that has all the scripts layed out...

sinful mango
#

that would be helpful definitly, also I saw, thats quite a feat indeed! clearly an expert in udon at this point lol

cerulean zealot
#

Code for "Animation Root Motion Drives the motion of the NavMeshAgent of the NPC"

sinful mango
#

and once more, i think my brain just poofed

#

vrcTupCry yep, im already part way lost in the graphing, ah i have much to learn on this

obtuse echo
cerulean zealot
#

@sinful mango if you are more familiar with text based coding you can do that.

#

@obtuse echo wait....wut?

obtuse echo
cerulean zealot
#

hrrrrmmm???!! 👀

sinful mango
cerulean zealot
#

@obtuse echo is this used in conjunction with blending layers in the animator?

#

@sinful mango yeah that feeling never quite goes away. That's why it's fun, its a giant puzzle to solve.

sinful mango
#

vrcTupCry This puzzle is beyond me, but..if i get this figured ill be able to get it all working im sure in the end

obtuse echo
sinful mango
# cerulean zealot

Ahh its killing me, what are the Set isNotActive and Set isActive? im assuming a few are there like it but i cant figure it out

cerulean zealot
#

@sinful mango when isActive is true, it will lerp the TimeElapsed from 0 - 1 when set active is false it will lerp from 1 - 0

When isActive and isNOTExiting is both set to false. The unarynegation makes them both true, so the logic AND will only output true if both inputs are true. that allows the "gate" to be open to check when the AimConstraint weight is 0. when that happens it proceeds to the exit code.

#

Logial AND works like this:
false + false = False
False + true = False
True + Flase = False
True + True = True.

#

Booleans are like minecraft redstone. if you disregaurd the strength of a signal.

sinful mango
#

Hmm, I meant just to add them in, in the search function for now, im no where near the ending parts, the rest i think i can find

#

like this is all i have so far in recreation, trying to add onto the "Is Valid"

cerulean zealot
#

yeah the "isValid" is only there for my script so it doesn't crash if the player being looked at leaves the world while they are being targeted.

#

because your script is only for local. It shouldn't be an issue.

sinful mango
#

That makes sense then, though how am i actually adding them? since those nameings dont exist i assume there custom? back with the "IsActive and IsNot existing" since im trying to follow the code as Im honestly still at a loss with this, it could be just not getting it or misunderstanding here im not sure since searching for them they didnt appear

#

ah forget it i think im jsut realising now XD oh lord, a whole learnign curve here, apologies i got it

cerulean zealot
#

you have nothing to appologize for, this is all part of learning.

#

lets take a few step back. Do you know about different data classes?

#

like booleans, floats, integers, and that stuff

#

@sinful mango

sinful mango
#

Yeah ive got some general understanding, ive had the vrc creators guide up too incase, but I realise its the whole aspect of points ahead beign called back further, just took a moment to realise, though no doubt ill find something im clueless towards after, this is still the first section afterall, i havent even applied anything to the npc or player yet

cerulean zealot
#

yeah, most of the reasources i've been using have been unity scripting API, Microsoft C# documentation, VRC documentation for specifically VRC related stuff, and ChatGPT to bounce ideas and learn syntaxing off of.

#

the two booleans in my code is to prevent the code from executing all the time when it not needed.

sinful mango
#

Definitely well practiced and delved into it then XD, ah can't say he same for me, ive had some udon graph use for teleporting and object spawns etc the normal stuff, trying to expand into newer stuff

#

I think my next goal would be dialogue appearing but have it randomised

cerulean zealot
#

@sinful mango yeah I haven't touched dialog yet. that's a whole thing of like... combining strings? perhaps? Idk.

sinful mango
#

I have a few potential ideas to try but it's a far concept currently lol.
Also with this headtracking system will it break any pre existing animations ive done on heads or will it exclude them while it looks at a player and return when a players out of range?

sinful mango
cerulean zealot
#

thats a custom event

finite sierra
#

@cerulean zealot getting other people to see a npc look at someone else is pretty easy and fast. can be done with 2-3 lines of code

cerulean zealot
#

it's just more code to handle turning off the script

#

@finite sierra you gotta isolate who is making that call and to who it is going to look at.

finite sierra
#

well u dont even need to do that.

#

yep thats easily done if have have a object owned by a player that the npc is looking at

cerulean zealot
#

there are a million ways to do anything.

sinful mango
#

Finally i think the first section is done

sinful mango
cedar crescent
sinful mango
cerulean zealot
#

@sinful mango afk will reply. L tr

cerulean zealot
#

@sinful mango so this is where the nuances of programing and code start to come into play. with @cedar crescent offering their solution, and im offering my solution to the same problem.

The code I presented is something I came up with, and it works for my project because it's a small part in a MUCH larger system. Vavassor solution works because it's just focusing on "head tracking player head"

Vavassor and My solution are not compatible with eachother though.

sinful mango
#

I see I see, so to a fine point it really comes down to a whole factor of trial and error too, based upon the circumstances of use and application, atleast how im seeing it

cerulean zealot
#

exactly! everyone comes up with their own solutions to fit their needs.

#

now, i'll be honest, there are people here that know a lot more than I do when it comes to this stuff.

sinful mango
#

Ah well theres always bound to be someone who'll know something to a deeper level, though in the case of my testing, ive got more work to do in making it function clearly lol
though its admittedly nice trying something new despite the challange it is

cerulean zealot
#

lol, I find it fun that the challenge never ends. I have a cow that stops suddenly, and doesn't navigate to where it needs to be for some people and im trying to dig through my code to find out why

cedar crescent
#

Also my solution only works on humanoid rigs because Unity's IK doesn't support generic rigs.

There's a third solution I've also done. Which is to manually update the bone position/rotations using U# in LateUpdate. LateUpdate is after all animator stuff is updated. So this method overrides whatever the animator is doing. It's a little more math. I only did this because I already needed to manually modify bones for other reasons.

sinful mango
#

ah lucky in my case to a degree, since ive done a ton of animations ive had to switch to generic rigs, plus i find its working a little better but future tests could prove otherwise.
though so far granted most my work has been remaking the graphs, the npc im testing just staresblankly in a direction which, is definitly interesting, like its unable to locate the player, but issues for tomorrow lol

cerulean zealot
#

my solution requires to manually find the bone and axis that you are going to aim at the target becasue I work with so many generic rigs.

sinful mango
#

yeah vrcAevSip guess ive got work to do, but all part to the fun, gotta big brain this

finite sierra
#

hmm i am actually wondering if there is a way to tell udon not to sync something when someone rejoins. like the late joiner sync thing. but manually do it?

obsidian python
#

but on second thought, it wouldn't be good, it would sync for everyone when you call it

finite sierra
obsidian python
#

it seems like the onVariableChange method gets called whenever the player joins, even if you set it to manual sync

obsidian python
#

but it's still possible, but it depends on how do you want to use it. because the owner can sync it everyone when he wants, and the local player could turn it on and off the sync easily, but if you want the owner of the object to enable and disable the sync for a specific player, that can be a lot more challenging

cold laurel
cerulean zealot
#

@cold laurel could be useful in delivering history in batches.

normal sonnet
#

What's the correct way to manually sync variables across multiple udon scripts at the same time?

do I have to run request serialization is each of them? or just one after i've run the events in each to get the synced variables where we want them?

strange gyro
#

Yep run RequestSerialization on each behaviour that has their variables changed then each behaviour will fire off its own OnPre/Deserialization events

#

They're not guaranteed to all happen at the same time though so coordinate changes to data accordingly

finite sierra
cold laurel
cold laurel
cold laurel
finite sierra
cold laurel
#

But from everything that has been stated so far it sounds like you're misunderstanding how to synchronize state in a robust way.

finite sierra
finite sierra
#

but to give you an idea. of what i am doing. everything in the world is by default not synced by design. however there are a few things that are. one is a sync button that well syncs you to others. another thing is some Text that floats above you when you sync. and third thing is a collider that gets enabled based some rules i created that determines who can interact with who etc.

#

when someone leaves it breaks those things for the rejoined person.

#

i use no Contiounes cause its uncessory. i use manual purely

cold laurel
# finite sierra i am not lol? how do u even abuse it lo?

It's very easy to abuse.
As an example I'll be incorrectly syncing a bool.

public override void Interact()
{
    bool currentState = gameObject.activeSelf;
    SendMethodNetworked(nameof(SetEnabled), SyncTarget.All, !currentState);
}

[NetworkedMethod]
public void SetEnabled(bool enabled)
{
    gameObject.SetActive(enabled);
}
cold laurel
cold laurel
finite sierra
cold laurel
#

Are you doing anything else than this?

[AddComponentMenu("")]
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class Example : UdonSharpBehaviour
{
    [UdonSynced] private bool _canInteract_Synced;

    private void SetCanInteract(bool canInteract)
    {
        if (!Networking.LocalPlayer.IsOwner(gameObject)) return;
        
        _canInteract_Synced = canInteract;
        
        RequestSerialization();
        HandleSerialization();
    }

    public override void OnDeserialization() => HandleSerialization();

    private void HandleSerialization()
    {
        Debug.Log("Can Interact: " + _canInteract_Synced);
    }
}
meager quiver
# finite sierra hmm i am actually wondering if there is a way to tell udon not to sync something...

The usual way to do this is to detect if the event is old in OnDeserialization() - you get an argument out of it that contains both send and receive time. If receiveTime - sendTime > 5 or something like that (5 seconds since value sent in this sample) you can tell it's a late joiner sync and ignore the change, if you are performing changes from within your OnDeserialization.

However, since you are using a custom RPC system/layer as you mention - Miner28's NetworkedEventCaller - you may need to modify it to support this use case. As it stands, the code appears to re-run events when late joiners join, so you need to design your systems in such a way that late joiners are properly handled, or modify the code to add a way to signal that an event should not run if the aformentioned condition (or whatever other threshold you like) returns true.

In general, by the way, I'd avoid using such systems as a blanket way to do things unless you truly understand both vrchat's networking model (including how late joiners behave) and fully understand the architecture of what you are building. Most RPC systems implemented in VRChat have certain limitations or situations where they can fall over, because it's difficult to make them truly general-purpose - even when making your own. You really need to make sure what you are using is fit for purpose, and this system you are using looks more useful for game worlds than anything - most game worlds do not deal with late joiner sync, and just lock players outside until the round ends. You absolutely can use something like this, but it's easy to misuse it if you don't fully understand its limitations.

finite sierra
meager quiver
# finite sierra also no. because everything is fully synchronized lol. its only when you leave a...

With your example of a button here, it sounds like you are either using network events, or using this system to send the flip state - this is not going to work with late joiners.

The way to do this in a late joiner-safe way is to store the state in a synced variable, and either use the FieldChangeCallback feature or OnDeserialization() to actually update its state. Any other method is ephimeral - i.e. after it's happened, every client forgets about it, so it won't be late joiner synced.

#

In short: NetworkedEventCaller for a toggle button will not work correctly for late joiners, or anything else that needs to be late joiner synced in a way you need to be able to depend on the behavior of.

vapid pagoda
cold laurel
#

^^^^^^^^

finite sierra
normal sonnet
obsidian python
#

I have a question about a turned based game (for example a turn based card game), it would seem like it's the correct way to do to reduce the latency for the players, but I don't really know if it's reliable, because this way I would use the SetOwner() and RequestSerialization() together. But I don't know what could be happen, what if one packet arrives faster than the other? Let's say is it possible that SetOwner executes faster than the RequestSerialization for the other player? So the RequestSerialization would be ignored? or am I overthinking the possibility that it would break?

#

So far, I didn't really have issues in my game, it works fine with this networking system, but I didn't test it enough in a real world scenario where people can have unstable connection

obsidian python
#

because If I think about it, it can reduce the network latency by 2 compared to if the game wouldn't change owners in every turn

obtuse echo
obsidian python
#

I just remember, there was a staff member, and he told me it's not recommended to do SetOwner and RequestSerialization at the same time

obtuse echo
obtuse echo
obsidian python
#

i found it

#

but if I would use the onDeseralization, it would defeat the whole purpose of trying to speed up the ownership transfer

#

when waiting for the onDeserialization to happen, it can take up to 200ms or even more, depending on where you play

obsidian python
#

also it's more faster if the owner of the object is the one who's making the ownership transfer, otherwise, the transfer time also doubles when you would do it on the OnDeserialization if the player would request the ownership from someone else

cerulean zealot
#

I always just have the new owner set ownership on themselves

#

I can't conceptualize why I would ever need to "requestownership"

obsidian python
#

if a non-owner wants to get an ownership of an object, they must require permission from the owner who can decide if it's grant you or not

#

in a turn based game and maybe in other situations, it would make sense to transfer the ownership of the actual turn owner, because the game is predictable, you know what player comes next

cold laurel
#

You should have a synced int for whose turn it is.
When you receive the synced data you compare if the id matches the local player's id, if it does. Take ownership.

cerulean zealot
#

^yeah that's what I do

#

there is a deserialization that happens between ownership transfer. The new owner takes ownership

#

I just have to make sure that the ownership transfer doesn't happen often in my code.

#

its like... gated behind a state machine

#

if that makes sense

obsidian python
cold laurel
cerulean zealot
#

@obsidian python how often are you wanting to transfer ownership on things?

obsidian python
cerulean zealot
#

how long is a turn?

#

on average

cold laurel
obsidian python
cerulean zealot
#

sooo.... more than a second?

#

more than 2 seconds?

obsidian python
#

because players too lazy to put down the cards

cerulean zealot
#

so I really wouldn't worry about latency then if it's under 2000ms

cold laurel
#

Latency won't be a problem?

#

:(

#

Why am I being ignored

#

lol

cerulean zealot
#

headpats kitkat

obsidian python
#

what if the owner of the object refuses the transfer?

#

is just adds way more confusion to it

cold laurel
obsidian python
cold laurel
cerulean zealot
#

you have lots of wiggle room

obsidian python
cold laurel
#

Because they can't in that case.

obsidian python
#

well, that explains a lot of things, then yeah, I should use the OnDeseralization method to safely transfer ownership if it doesn't adds any more latency

cold laurel
#

Yup!

#

As long as you prevent players from placing cards before it's their turn you'll be fine

obtuse echo
# obsidian python

Hmmm that has to be a different context or some kind of misunderstanding. From my personal experience setting owner to local player and then immediately requesting serialization makes the data propagate to everyone's OnDeserialization call 100% of the time. That is the recommended way. Your example is different as you are setting the ownership for somebody else, which always caused issues for me. I haven't even tried doing that in a while so I can't speak about details and can only recommend the first way I mentioned.

cold laurel
#

^

obtuse echo
#

Also seems like people gave you the example already, that's exactly what you should be doing

obsidian python
#

also, even the documentation isn't saying about that you actually own the object when the OnOwnershipTransferred happens, what can cause a little bit of confusion, but yeah, thanks a lot for explaining

#

it only says "ownership may change back" but it doesn't confirms that you own the object already or not

cerulean zealot
#

question about VRCObject Pickup and VRCObjectSync. If I have an udonscript on the same game object as the two other components, will setting that udon script to manual sync cause issues?

obsidian python
#

they work differently I think, you can have almost unlimited amount of udonscripts on a single gameobject

#

so they shouldn't affect each other

#

ah wait, but if I change the sync mode on one of them, all of them changes

#

i'm not sure then, but I guess, they shouldn't affect them, and even if you have manual sync, your CustomNetworkEvents would still work, just like if you pickup an object, it would use an event or something

cold laurel
obsidian python
#

but you can't use a manual syncing udon script and vrc object sync together anyway

cold laurel
cerulean zealot
#

my brain...

#

multiplayer is an evil puzzle... don't do it people....

strange token
#

@cerulean zealot if you need any help just ask! Networking can get annoying but VRC has this handy hive mind that lives here and boy do they fix all your problems

#

lmao

strange gyro
#

Basically the rule is that you can't have mixed sync modes on the same gameobject

tulip sphinx
#

dont share multiple behaviours on same object, ez

humble girder
#

I do share multiple behaviours on same objects. But of course they are None sync. Other than than I just group them by Cont, and Manual sync.

cerulean zealot
#

So my agro state of my npcs were not transferring ownership.

#

🫠

#

Vrcplayerapi.getplayerbyid is not the same as index number of getallplayers

#

And holy love of udon..
Having someone who is more knowledgeable about udon than you to test the world is a GODDSEND 😭

me testing multi-player, I've been just relying on my friends and people I know. They don't make worlds or program, so all feed back was very basic understanding.

finite sierra
north thistle
#

it'd be impossible for the index to be the same as id in most cases I'm pretty sure; I don't believe the ids of people who leave are reused

cold laurel
cold laurel
finite sierra
finite sierra
north thistle
#

well if the first 3 people in a world leave and there are three people in a world, they will never match

finite sierra
#

well yea. but thats just how that is

cerulean zealot
finite sierra
#

hmm? a world wont be up enough to hit 2.14billion

humble girder
cerulean zealot
humble girder
#

I'd be surprise if you have enough resource to do it.

cerulean zealot
#

And then I need 2.15 billion participants. Easy

cold laurel
cerulean zealot
#

@cold laurel I know back in one of the first furralitys there was a gap between "click to join" and before world being initialized, where that person didn't count towards the instance. And the check if you were allowed to join was only on the "click to join" part. So the instance allowed all 400 people to join in and stack ontop of eachother.

strange token
#

I’ve seen discussion around “instance restarting due to its age” I wonder if PlayerID cleanup triggers that message

#

In which case you’d just get the instance refreshed if you tried overloading the playerID size

lone zealot
tulip sphinx
strange token
#

This may sound like a broad question, but just how much better does your syncing feel when you have all players including the local player react to a change in OnDeserialization instead of changing it locally and just serializing it for other players?

#

Like, if you were teleporting a group of players including yourself, and you moved that process to OnDeserialization, would it actually appear that all players are teleporting at the same time, or would there still be some amount of "you teleport first, others arrive after"?

cold laurel
#

The only way to do what you want is to override the remote player's positions locally.

strange token
#

:o

#

thanks for the info!

cold laurel
#

any time :)

finite sierra
#

hmm is the VrcPlayerAPI GetPlayers a ordered array or is it not ordered based on the ID?

sturdy hornet
#

so im trying to get it to sync for late joiners but its not and i dunno why

#

oh wait i broke it up one sec lol

#

also how would i make this a request serlization

north thistle
# strange token This may sound like a broad question, but just how much better does your syncing...

If you want an event to happen at the same time for all players you can try delaying the event for the local player and using OnDeserialization(DeserializationResult)'s sendTime property to sync the delay for everyone. Still even if if the teleport event triggers at the same time there is still a network delay until the local player sees the remote players' movement (it should be a bit less, though)

strange token
#

oh shit that's a great idea

sturdy hornet
meager mauve
#

Think this may be more of a networking question.

small raptor
#

Hello,

I have to make an asset for one of my worlds, the goal is to make a tablet to manage permissions and access on the map. The first to arrive must have all the permissions and access the tablet to give the permissions to the other ( so far I manage ) but the problem is that when he gives the permissions to another person he must have the list of players synchronized with the owner but I can't do it... Even if I follow the VRchat documentation...

So I'm looking for a kind soul to help me by private message!

obsidian python
#

and maybe if an admin opens up a door, or toggles a gameobject, it should be visible for the late joiners?

#

because if that's the case, you can just make an udonSynced boolean, and listen to the variable change events where you toggle your object. and you don't even need to deal with the late joiners this way.

sturdy hornet
#

And use it on more important stuff

sturdy hornet
obsidian python
#

the player needs to own that object if it want to change the synced variable

obsidian python
#

you want to use the bool newValue for the SetActive, and you can remove the LateJoiners variable, I don't see a reason what are you using it for

sturdy hornet
#

the tunred on one?

obsidian python
#

the TunredOn Change event gets called automatically for the player when he joins, you don't need to worry about the late joiners

#

but basically, what you are trying to do is: have a button that only the whitelisted players can press, that enables another button for all the players? in that case, it's supposed to work

sturdy hornet
obsidian python
#

yeah, but they don't update as long as you don't call a specific method that would update your objects, unless you have the synced variable in the Update or FixedUpdate loop, or as you used before, it's gets updated in the variable change events

#

so, all of your synced variables update itself whenever you use the requestSerialization or use the continous sync, but you need to listen for the VariableChange events or use it in a Update() or FixedUpdate() loop to have them synced with your objects

sturdy hornet
#

cause its on interact rn should i make something for on player join?

obsidian python
#

if the secondary button of yours only enables the visual effects, then it should work completely fine, because it gets enabled on the TunredOn Change event

obsidian python
#

have you tested it?

sturdy hornet
obsidian python
#

i think if you click on build and test last build, then it will join to your existing instance

sturdy hornet
#

one sec

obsidian python
#

but first, do make a new build

#

then on the late joiners, use your last build

sturdy hornet
obsidian python
sturdy hornet
sturdy hornet
obsidian python
#

yeah, that's hella a lot of pain, but you can use the editor's clientSim for smaller things, it's definitely not as accurate sometimes compared to the game, but it's usually works

sturdy hornet
finite sierra
strange gyro
#

Testing networked stuff in play mode isn't all that reliable, I usually launch a couple of VRChat clients with different accounts to test syncing in local build and test mode with some powershell commands:

# Launch build and test client with main account
C:/path/to/VRChat.exe --no-vr --enable-udon-debug-logging --watch-worlds --enable-sdk-log-levels --enable-debug-gui "--url=create?roomId=2213&hidden=true&name=BuildAndRun&url=file:///$([uri]::EscapeDataString("$($ENV:USERPROFILE)\AppData\LocalLow\VRChat\VRChat\Worlds\scene-StandaloneWindows64-MyProjectName.vrcw"))"

# Launch build and test client with alt account
C:/path/to/VRChat.exe --no-vr --enable-udon-debug-logging --watch-worlds --enable-sdk-log-levels --enable-debug-gui --profile=1 "--url=create?roomId=2213&hidden=true&name=BuildAndRun&url=file:///$([uri]::EscapeDataString("$($ENV:USERPROFILE)\AppData\LocalLow\VRChat\VRChat\Worlds\scene-StandaloneWindows64-MyProjectName.vrcw"))"

Replace C:/path/to/VRChat.exe with your VRChat client path and MyProjectName with your project name to match the file path at C:\Users\<username>\AppData\LocalLow\VRChat\VRChat\Worlds\scene-StandaloneWindows64-<MyProjectName>.vrcw

tulip sphinx
#

why, theres nice launcher in vcc that do that

strange gyro
#

Never used it before, does it handle the build and test URL as well?

tulip sphinx
#

uuuh it has option to launch each time you build for 0 in sdk

#

otherwise you just select whatever vrcw you got (i beleive the latest build is selected by default) and launch whatever clients you need in one click

strange gyro
finite sierra
strange gyro
#

Yep, but you can launch it with multiple clients on different accounts

finite sierra
#

guess i need to make multiple accounts to use the online function.

#

otherwise the local is pointless

strange gyro
#

If your world logic doesn't rely on every player having a unique display name you can still launch multiple clients with the same account for testing, otherwise yeah multi account is the way to go to be sure everything's gonna work correctly

finite sierra
#

eh i mean as the offline testing != the same as having the online world. because i have tested things that works in offline but in online it messes up completely

#

like for instance when there 10-15 users it messes up some things

#

and i rely on ID's not display names

tulip sphinx
#

afaik only chairs are still unreliable in local test, at least was a thing year ago

#

otherwise its just some code flaws

#

in local test networking is still performed via servers, just world file is not being downloaded

finite sierra
#

well i had a few tests already with 10-15 people and it works well syncing them all but as soon as they then teleport to another place that enables a interaction on them it loses references to some people. and things dont appear to interact as it should

#

and i tested that with 15 offline clients

dreamy plaza
#

ok so I have a pickup you click and sends a network event that plays a random sound, what’s the best way to sync that random index, such that which sound is played lines up for everyone? Reading the docs it seems like variables and events sync at different rates, and events can’t have parameters.

tulip sphinx
#

option one - on same pickup use synced var and play sound on variable change. make sure that random cant be the same. option two - child object with manual sync that recieves event from main pickup's use, sets variable, requests serialization and then plays sound on deserialization(+locally).

jaunty fjord
north thistle
#

Having someone on the other side the world help test your world might also be nice to test for networking race conditions you never considered before

spring basin
#

Hello everyone, sorry to disturb but I was wondering if there is any way to make the VRCinstantiated objects synchronized?

tulip sphinx
#

sure, just keep synced stuff outside of instances themselves

vapid pagoda
spring basin
#

Many thanks for the answers!

ocean orbit
#

Hi guys, another question :((
I’m trying to make an among us-like game where roles are divided imposter/crew
I wanna pick a random player to be an imposter and have the ui “you’re an imposter” while other people get the ui “you’re a crew”

However I can’t get it how to show different screens using the network system in vrc
Any ideas how to start this??

Thanks always

rigid temple
# ocean orbit Hi guys, another question :(( I’m trying to make an among us-like game where rol...

Not a pro by any means but I'd probably set it up such that
-Instance master decides what team teach player is on
-Sync an array for each team
-SendCustomNetworkEvent({Target all}, {name of ShowUiFunction})
-ShowUiFunction called on every player, this check which array they are in, and then runs an animation to show their respective screen.
Make sure the SowUIFunction is public or else it won't get called

#

This does require telling the user, on the backend, who the imposter is which isn't good for preventing cheaters, however you'd have to be hacking to see that data but by that point the lobby's probably already too far gone

north thistle
#

Yah, only the information of who is the imposter needs to be networked. Stuff like UI logic should be handled locally. If localplayer is imposter then render imposter UI, else render crew UI

frozen igloo
dreamy plaza
#

so now that the Network ID utility is broken for the past like 3 SDK versions, how does anyone make quest worlds anymore? Do quest creators just stick with some specific SDK version, or is there a third party tool that works around it?

hoary frost
#

i havent had any issues with my quest worlds recently

dreamy plaza
hoary frost
#

do you use different scenes for windows and android?

dreamy plaza
#

of course

hoary frost
#

i see

#

i use easyquestswitch so i dont have that issue

dreamy plaza
#

I guess everyone does

#

try using EasyQuestSwitch on a scene that has hundreds and hundreds of objects. Ah yes let me just mark every single one individually by hand to have its material replaced with the quest shader

tulip sphinx
#

tis crazy how theres still no mat replacer

hoary frost
#

yeahhh darn

dreamy plaza
#

but it requires it being a separate scene

tulip sphinx
#

i tried that one, was pain

#

ended up just manualy placing replacrable stuff in diff folder then copying it to pc/quest folders via explorer when switchin. prob should work on one.

finite folio
#

Guys, can you please help me figure out how to make inventory by type? that is, taking some object in your hands, putting it to your chest, releasing it, it disappears into the inventory, while the task is being completed, then how else do you need to find several objects to open access to completing the task in the dialog.

I kind of tried to do it like in that video https://youtu.be/hsnBrLQizDo?si=dVWhwDoqXixmJ0Yb, only I tied the box collider to my chest, but the object does not perform the action because it is not in the script itself, it will not work separately.

I want to find out how it can be done in the form of a name so that it is executed separately, or in the line of the object where it needs to be placed in the script.

I need answers, although I am ready to get negative ones, that this script with inventory cannot be done. And so, I don't want to wait a long time without an answer to this at all.

Here's a video on how to make a door that requires multiple pickups to unlock. This can be coins, or something completely different like keys, pictures, etc..
In this tutorial, I make a door that requires 3 coins to open

This tutorial also covers how to make a door open using an 'animator, play' node; something I haven't covered before. I also ...

▶ Play video
tulip sphinx
#

to start, you want to use name of collider with 'contains' node to check if its a proper item and use some naming scheme for them ie ItemVodka ItemBread etc

#

then it will work with any object anywhere just based on its name

#

to store an item you ofc can use an array but actually i guess an easy way is to reparent item transform to your inventory so its literally ends up in it and when checking for quest conditions you just search in your inventory object.

finite folio
finite folio
tulip sphinx
#

@finite folio dm me

north thistle
#

You can also sort items into layers and either have the collider only collide with those items or check what layer the collision object belongs to and go from there

finite sierra
#

anyone knows what the EOS update thing is in the Log for worlds?

hearty vale
#

If I have a pickup with object sync (continuous sync) and an udon script with continuous script on that same gameobject

can it have a sub-gameobject with an udon script that is manual sync? or must the sub-objects be continuous sync too?


Can I use RequestSerialization in a continuous sync'd script?

Does OnDeserialization ever fire in a continuous sync'd script?

frozen igloo
finite sierra
#

@obsidian cedar with your networkcaller thing if i have lets say 40 people in a world and i target all 40 people would that mean it takes roughly 13 seconds in total to send to all or is the Limit you have hardcoded to .33 only if its called multiple times?

#

or would it be limited per network caller?

obsidian cedar
#

so if you send an event to everyone it'll be "instant" if no event was sent for 0.33s or max 0.33s
Ofc you have to note the latency etc.. so it will SEND to all at once but based on each person's latency it will be received at different times

#

And also NOTe, due to VRChat limitations you can't just send something to just 1 player, it will always send to everyone regardless of anything. But what I do in NetCaller is on the receiving side I check some target info bytes to check who the event is for and ignore it if it's not for the player

finite sierra
#

i assume if i use the SyncTarget VrcPlayer API then it only sends to that person correct @obsidian cedar ?

obsidian cedar
finite sierra
#

ahh gotcha i just missunderstood what u ment by it thanks.

weak hinge
#

Would a networking expert be able to look over my code if possible? I am having an issue where OnDeserialization is being called constantly and I am really confused as to why

north thistle
#

is the behavior continuous sync?

weak hinge
#

oh, I think so

#

i've never had to change that setting before

north thistle
weak hinge
#

sdfjaksjhdfkjsldfjkhsaf

#

it was because of this

#

thank you lol

#

I was struggling with this for longer than I want to admit

#

but thats the way of code I suppose

north thistle
#

I once spent an hour or so trying to debug a problem caused by if (gameObject = void)

strange crane
#

I have a VRC Pickable up that I want to play an audio clip thats synced with everybody else. The issue I am encountering is the fact the script has to be Continuous and keeps calling OnDeserialization. Is there a way prevent it from being called multiple times on a VRC pickable up.

tulip sphinx
#

a. you dont even run Ondeserialization event (and you sohuldnt, for continuous sync)
b. your local code both plays stuff locally and calls network event that performs same stuff again. network events unlike ondeserialization fire for owner as well
c. at least say what behaviour you expect/get

strange crane
#

But biggest issue for this is the value dosen't sync before the event is fired.

tulip sphinx
#

overall just move everything to a child object with manual sync, both easier do deal with and less network data. onpickupusedown transform.getchild(0).getcomponent....SendCustomEvent...

strange crane
tulip sphinx
#

what

#

child will be locally stuck to networked pickup

strange crane
#

Got it but basically this.

#

then send custom event?

tulip sphinx
#

im pretty sure pickupusedown is local

strange crane
#

It is

tulip sphinx
#

ie you need to hold pickup already

#

so why set owner

#

wait what

tulip sphinx
#

cant you just do it all in child script?

#

ie set owner etc

#

pickup can just send local custom event

strange crane
#

Got it

tulip sphinx
#

probably doesnt matter but seems more streamlined to me

strange crane
#

Lemme check if what your saying works

north thistle
#

You can probably use a FieldChangeCallback on a networked value to do what you're looking for

#

something like

[UdonSynced] private int _vl;
public int V1
{
    get { return _v1; }
    set
    {
        _v1 = value;
        PlaySound(value);
    }
}```
tulip sphinx
#

and what if random is the same

north thistle
#

that should have the same indexed sound play for both the owner and remote clients

#

This will also cause the sound to play for late joiners when they first join the instance, though

#

Oh, I see what you mean now by random; good point

stone badger
north thistle
#

that scales terribly; best option is using a manual sync and putting the event into pre/deserialization

strange crane
strange crane
north thistle
#

yah, have to make it a child

#

in general having any synced behaviors on an object VRC Object Sync seems like a bad idea because VRC Object Sync seems to shut down all syncing on the entire object if it hasn't moved in awhile

stone badger
strange crane
stone badger
finite sierra
#

anyone else had issues with the rejoin function for a world? i have observed that if you rejoin a world immediately it can result in some objects being null. which i find rather strange. but if you do not immediately rejoin and you choose to go back home first and then rejoin then it will work as normal

finite sierra
#

oh. i found out why. i cannot rely on ID's assigned to player that joins a world.

finite sierra
#

seems like i found a big bug lol. if two people join at the very same time both people get assigned the exact same ID PlayerID

strange gyro
#

You sure it's not just something wrong with your script logic?

finite sierra
#

yep.

#

i just looked through my logs. and somehow it ran OnPlayerJoined 3 times even through only two players exist. and also the logic only runs when your master.

hearty vale
#

do networked variables need to be public

is it possible in a manual sync'd object for RequestSerialization/OnDeserialization to misfire on an object that is potentially rapidly changing owners?

stone badger
finite sierra
#

doesnt matter. it still happens

#

there are duplicate collisions on the ID which causes two masters to people to be the same

lapis lodge
#

So I have an object with ObjectSync and at this time PlayerPickup.
The object which is in the scene at start, is synced between players in the world, however I want to take this behavior a step further. I want to create new instances of the object that are also synced between players. However, objects that are instanciated are not synced and are local. So what must I add to the code to ensure that objects that are created are networked synced?

frozen igloo
frozen igloo
finite sierra
lapis lodge
# frozen igloo You need to use an object pool, using objects already there. You can either use ...

What does this mean exactly?
Let's take an example from the world, "Trash Compactor" where as, there is a large cannon that shoots trash when a trigger event is called. An object is then randomly thrown out of the cannon onto the arena below.

When you are referring to an object pool, are you saying that all the trash is not being instantiated but there are a large pool, like traffic stuck on the road, above the arena already there on world start waiting to shoot out when the trigger event is called?

tulip sphinx
#

yes

#

it grabs first free item, probly even has pools for pianos, pool for tyres etc since its easier and shoots one of them

lapis lodge
#

Wow....

#

I did not know that this is how it worked.

tulip sphinx
#

its not like its stuck tho, its disabled and doesnt do any networking when so

#

but ye it already exists in the scene and when projectile dies goes back to being disabled to be reused later

lapis lodge
#

This is going to add a bit more complexity to what I had already in mind.

#

If not already to what I was wanting to test. (It's been a while since working in unity) But an idea to test was to give each instance an ID with a range, call all ID's with a range and type (in this case a ball) and then add a component (the network sync) on the active state (or awake) and see if that can trick it into working.

#

But I don't know if someone has done that already or not.

tulip sphinx
#

what

#

in runtime?

#

wont do a thing

lapis lodge
#

Yeah in runtime. A script that adds the networkSync component to an object after the "game" had started, won't do a thing to add networking is what you are saying.

#

Well shucks.

tulip sphinx
#

anything networked should have an unique network id on upload

#

if all you need is vrc sync you can reuse them, i have a world with a pool of 150 empties (default vrc sync also quite heavy on bandwidth but eh) that can be any form or shape.

#

then you throw out what you dont need and can make new ones (in fact reusing same pool objects)

#

but its not the easiest stuff

lapis lodge
#

Wow... Is it a bug or intended behavior that instantiated objects can't be synced?

#

Because if that is the only way to do it, seems as that is the only way to do it then.

tulip sphinx
#

again. anything that should send the data across network should have network id, assigned when building the world. its intended. if you need smth simpler/less data heavy/manualy synced than vrc sync (like, idk, small minecraft zone) you can outsource it so you actually destroy/instantiate stuff locally based on a single script containing synced arrays of block data etc. but thats not viable for continuous sync of large amount of data since theres no selective sync.

lapis lodge
#

So here is a question, how do you keep up with 100+ objects in your project? If you have to create a pool, where as in an instance one object being changed affects all instances to that object, which is ideal for testing. Now you must change 100+ objects, MANUALLY. I mean, am I missing the logic here in how inefficiant this all is?

#

Did VRC at least create a tool or something to make this all easier?

tulip sphinx
#

wha

#

' a pool, where as in an instance one object being changed affects all instances to that object'

#

?

lapis lodge
#

Every instance of an object is a clone, an exact copy.
A pool of 100 objects are that which are independent of another.

Networking doesn't exist with instanced objects (because VRC either is preventing this purposly, or they don't know how to network their game)

A pool must be created of objects in order to invoke networking capibilities. How do you then keep up with 100 objects when you wish to change the behavior of all of them?

tulip sphinx
#

they use same script, why should i change anything on them. otherwise if i realise i need say capsule collider as well as cube i fix first instance, delete others, hold ctrl+d. but thats rare

lapis lodge
#

Don't you mean first object?

tulip sphinx
#

well ye

lapis lodge
#

Very inconvenient.

tulip sphinx
#

you can script it, just easier to not to.

plush tiger
#

Can you not just have a prefab and update the prefab?

tulip sphinx
#

ye good idea as well

plush tiger
#

Myself, I have a custom pool script I made that I just hit a button and it generates the pool objects for me and assigns a few certain variables that the prefab can't hold.

lapis lodge
#

Hmm.

strange token
#

@lapis lodge you can technically get networked instantiated objects, but it’s true that you can’t actually sync changes to the instantiated object itself, so all the networking data would need to be handled by another “item manager” and the more you have to sync on those, the more you’re bloating its manager.

Make an item networking manager that has an array of all your object types. When a player spawns an item, they just update their “active inventory” with the index of the item they spawned so others know to spawn it too, but then you have to do the same for that object’s position, you need custom handling for applying networking to objects that are picked up, thrown, and despawning. Etc etc. it’s a lot of manual implementation to make this work 👌

#

You’re basically completely rebuilding item interactions alongside it, but it is possible, and it does look very pretty if you get it working, but it’s a lot of work you’re giving yourself in the end

#

This world uses this system for all of their items spawning, because there are a lot of item types, and they wouldn’t want to pool all of those for the player count or it would probably bog the game down

lapis lodge
#

Aye, and that is a huge benefit of instanced objects.

plush tiger
#

What I'm doing in my item system, is my pool is a list of Item objects, and each item instantiates the visuals along with a descriptor of the item that stores the item data, then I only really need sync what the item type is and the item class that each object is will update the visuals and effects

It is certainly rough not having something like an InstanciateNetworked, but we do what we need to within the limits we have.

Like, the amount of destruction I would give to have structs

frozen igloo
#

yeah, a more advanced pool where it manages a collection of generic synced objects and then instantiates additional things under each object is really handy for large-scale worlds with many items

#

I set up a pool with over 300 "template" objects and gave them each unique names, icons, and IDs. Then there were 150 generic pool objects, so at any one time you could have 50 apples, 50 swords, 50 shields, or any other combination

#

such a system is also a great foundation for building more complex interactions involving props, because you have more context on what something is supposed to be and you can distill the entire existence of the prop down to just data. Because of that, I also made stackable props, inventories, and save system. It's a lot of work but it's very rewarding to have such a system because it can become the basis behind many other features

plush tiger
#

Similar, I have 128 item holders and a number of descriptors, the holders handle any of the networking stuff, the descriptors have the data. Its for a lethal company like world so there are multiple behaviors for items, like flashlights, radio, generic scrap, noisy scrap, items that do damage etc.

finite sierra
#

@frozen igloo i found that i am encountering Network Race conditions. is there a simple way to avoid this issue? if lets say 10 people join at the same it gives the wrong things to wrong people.

plush tiger
#

I have the instance master distribute player owned objects in the OnPlayerJoined event, but I don't know your use case. Like, why are players attempting to take ownership of things on join? Can you defer this action to an event sent by the instance master after assigning an ID? Or maybe use the player ID?

frozen igloo
frozen igloo
#

I'd highly recommend it unless you're putting on an event this weekend

finite sierra
frozen igloo
finite sierra
#

i assume the other would be Request ownership transfer?

frozen igloo
#

eh, I'd not use request transfer for this case, it's not reliable enough

#

I was thinking more like determining owner of each object based on inherent factors that don't require additional networking like playerID

#

that's a more oldschool technique though, when networking in general wasn't even reliable enough to have master handle it. But it makes up for the clunkiness by being extremely reliable

#

but even cyan player pool is starting to look oldschool compared to playerobjects

#

There's really not much of a reason to build your own player pool at this point. If you desperately need something now before persistence goes out, use cyan player pool. Otherwise, use persistence playerobjects

finite sierra
#

hmm.

normal sonnet
#

I've been thinking about race conditions too for an upcoming project 💖

There's going to be a big rush from people to claim ownership of certain objects on a list at the same time

Are there other terms or ideas I should be researching for handling this?

spiral basalt
#

Whats a good way to check if a script variable has been synced

obsidian python
spiral basalt
#

thats smart

normal sonnet
#

Is the code for syncing object positions optimized? Like even though it's continuous, if there's an item sitting still, it's not generating network traffic right?

vapid pagoda
finite sierra
#

Like to other udon behaviors

meager meadow
lapis lodge
#

I have two objects, need one object to teleport to another object's location where that object is network synced. IE a pinball moves to the pinball spawner.

This is what I have, but I feel I am doing something wrong here. Can anyone help so that I may learn how to get this to work?

lapis lodge
#

Anyone around?

north thistle
#

why are you using a user input to do it and why are you doing it every frame?

frozen igloo
lapis lodge
#

Exactly, to check for input, it must be in the update to check for the event.

#

I tried to rework the code a bit, but still giving issues.

#

Am I using "teleportTo" correctly?

frozen igloo
#

Yeah that's the direction I was going to say, that line before was unnecessary and causing problems

lapis lodge
frozen igloo
#

as for the teleportto, that's simply not a function on gameobject class. To teleport a gameobject, you would want to get it's transform then call setpositionandrotation

#

that said, things are different if the pinball has objectsync. Does it?

lapis lodge
#

Yes, yes it does. as this be a game with multiple players to each, being able to knock the ball into the other players "goal" or what ever it is called in pinball.

frozen igloo
#

ok then if it's synced you would need to first take ownership of it, and then call TeleportTo. But you can only call TeleportTo on the VRCObjectSync, not the transform or gameobject. TeleportTo is basically the same as setpositionandrotation except it also tells remote users about the teleport as well, which makes it actually teleport instead of just lerp into place.

#

additionally, regardless of what you're doing with this specific code, it looks like you don't have intellisense hooked up and that makes coding a lot more difficult. You should ensure that you have it set up properly so that it will be able to recognize what functions exist, show you a list of options, auto-correct capitalization, and show you exactly what's wrong when it's a compile error

#

the first thing to do would be to go to file > preferences > external tools and ensure that something valid has been set as your external script editor. Looks like some form of visual studio you have, so make sure that's plugged in. Then, open the scripts by double clicking in unity, not through the windows explorer

lapis lodge
#

I think something broke.

frozen igloo
#

what kind of migration is this? That's not a thing that should be necessary

lapis lodge
#

I did what you said, and it gave me some sort of error and opened up a website with this migration report.

frozen igloo
#

close visual studio entirely

#

make sure that it's selected as the editor in unity

#

double click a script in unity

lapis lodge
#

It be downloading something now... I don't know.

#

XD

#

This is why I like to just stick to the 3d modeling lol, so much more simple.

strange gyro
#

You should probably install Visual Studio Community through Unity Hub if you didn't originally to make sure it has everything needed for Unity projects

finite sierra
#

hmm has anyone encountered issues where players dont get initialized?

lapis lodge
#

Not sure what all this is about.

north thistle
#

Does it matter what version of visual studio you're using? I know Unity likes to have a certain version installed depending on your version of Unity

lapis lodge
#

That's a good question, I don't know.. But it is acting as if perhaps the case?

#

That is what I am using.

#

I do have a 2019 version of VS as well. Should I try to open in that?

finite sierra
#

just use Visual code lol

#

its far lighter, faster and better

north thistle
#

you have to spend more time configuring stuff for code iirc

finite sierra
#

you dont lol

#

just install Vs Code + Unity tools and boom it works

lapis lodge
#

Well I don't think it isn't an unity package issue, I think it is a VRC package issue.

#

Just about everything on that "Solution Explorer" states VRC

lapis lodge
#

I don't know what is going on anymore but I think my project just broke.

#

How do I fix this?

keen cedar
#

Anyone know why the SENDCUSTOMNETWORKEVENT
isnt working for me in this instance.. if i connect interact to the set active it works fine but the send customnetwork even does not work at all

strange gyro
#

Is the behaviour Synchronization mode set to something other than None?

keen cedar
#

where do i check that sorry ':)

#

im learning

strange gyro
#

In the inspector of the Udon Behaviour

keen cedar
#

nah its none

#

should it be manual?

strange gyro
#

Yeah set it to manual

keen cedar
#

do i still need the custom network script?

strange gyro
#

Yeah, None just means that the object isn't networked so network events or variable serialization events won't fire for other players

keen cedar
#

if i can trouble you, whats the difference between none, manual and continuous ?

strange gyro
#

Continuous will automatically fire synced variable serialization events on a fixed interval, Manual has to be triggered manually using UdonBehaviour > RequestSerialization

keen cedar
#

so manual is the best one to go with in this instance then?

strange gyro
#

Yeah Continuous is mostly used with pickups that use VRCObjectSync, Manual is what most things use nowadays

keen cedar
#

ahhh i get ya

strange gyro
#

Especially if you're not actually syncing any variables

keen cedar
#

thank u! i appreciate the insight

#

ok another issue with this
|

#

my ranom array seems to be not syncing with players

#

what it does is sets a random object in a array to active. but it seems to be grabbing differnt cards for people in the instance

strange gyro
#

Yep since you're telling every client to run the logic locally they're going to generate a different random value on their client

keen cedar
#

T^T

strange gyro
#

You'd be better off syncing a bool array to represent the active state of each object and have the client that triggers Interact set a random object and the corresponding bool state in the array then RequestSerialization, then in the OnDeserialization event clients can iterate through that bool array and apply it to the gameobjects so everyone has the same state

#

That will also make sure it syncs for late joiners

keen cedar
#

so sorry im like wrapping my head around that one

#

ahaha

strange gyro
#

(ActiveCards and Cards should have been marked as Public)

keen cedar
#

ohh

#

lemmie try that one

#

seems right?

strange gyro
#

It's missing the ActiveCards node hooked up to Boolean[] Set's instance

keen cedar
#

shouldn the cariables be public aswell

#

?

#

variables?

strange gyro
#

Yeah they should both be public

#

Rest of it looks okay

keen cedar
#

so do i put the cards in the array in active cards?

strange gyro
#

Put your card objects in Cards and set ActiveCards to be the same size as the Cards array and leave the array values at false

#

Unless you've got some cards enabled by default in which case set the corresponding array values to true

keen cedar
#

naahh there all off

#

by defult

strange gyro
#

Oh I forgot to add SetOwner on the gameobject

#

Gotta do that before modifying ActiveCards or it won't apply the changes

keen cedar
#

willl this auto sync withou the custom event trigger?

#

also set owner node on the gameobject? in the graph?
for all on just one of them

strange gyro
#

Yeah when you call RequestSerialization all players except the person who called RequestSerialization will fire the OnDeserialization event with the updated synced variables

keen cedar
#

ahhhhh

strange gyro
#

Also anyone who joins the instance will fire OnDeserialization with the latest synced variable state

keen cedar
#

perfect?

#

i think

strange gyro
#

Yeah that looks fine

keen cedar
#

man Udon graph got me like

#

i wish i could dragg all 48 card objects in the array to the inspector in one go.
i have to do em on by one

#

ok time to set

#

test

#

works in unity.. now to try in vrc with ppl

#

btw @strange gyro thank u a bunch id be slamming my head if it wasnt for you

#

fyi reason for this is a custom board game idea i wanted to put in vrc XD

#

everything is working BUT the cards till you helped me with that so cheers!

strange gyro
#

I guess the only thing you'd want to improve after this is the random card selection

#

Since you'll eventually have to click spawn multiple times to pick a card that isn't already active

keen cedar
#

well you should only want one card.. im having it so the SPWN CARD button goers away when clicked aswell.. if they want and new game the reset button will set everything to unactive

#

if that makes sense

strange gyro
#

Ah fair enough

keen cedar
#

yee th reset bu8ttons flips them all up and resets the cards and all that jaz 🙂

#

ok weird one

#

it Kinda works?

#

Oh i know what its doing

#

id how to explain but the rest button is like not working as intended for the cards

strange gyro
#

You'd have to reset the state of ActiveCards as well and RequestSerialization

keen cedar
#

even if i click reset it toggles off all the the game ojects but if somone elese clicks spawn cards it has multilple commin up but for themn only one does

strange gyro
#

What does the reset button logic look like?

keen cedar
#

....veryy silly setip ahah

#

dont jusge me i did it myself

#

im embarresed by my graph

#

Ons and offs are for the fl;ip piceses and cards and the buttons are set the spawn cards button to come back after its been clikced already

#

... COULD i just use your other script? we did

#

and remove the random array?

strange gyro
#

Hmm this makes it a little trickier to manage the sync state because you disable the spawn button

#

The card states should probably be in their own udon behaviour

#

And the spawn button changes that instead

#

Then you could put reset logic in that other udon behaviour

#

Basically a game manager behaviour

keen cedar
#

i only do it so people do accidently click it and get a new card and go " OH MY CARD CHANGED"

#

we can disregard the button despawner as long as the spawner will one have one spawned at a time

strange gyro
#

I guess you could turn off the collider and mesh renderer instead on the spawn button to hide it and prevent it from being clickable

keen cedar
#

big brain move

strange gyro
#

So long as the game object and udon behaviour is active so OnDeserialization can fire on changes

keen cedar
#

we can not worrya bout the button despawning and just make sure the reset button works in this instance

#

wouldnt your script for the cards work?

#

just remove the random array?

#

like this ?

strange gyro
#

Rearranged stuff a bit so there isn't duplicate logic all over the place

keen cedar
#

.>
<.<

#

would this be one script for one button?

strange gyro
#

This is the Spawn button's script, then on your Reset button script you'd do Interact > SendCustomEvent with ResetCards as the eventName and a reference to the spawn button behaviour as the instance

keen cedar
#

also any chance you can send me this graph so i dont fuck it up?

strange gyro
#

For the reset button logic

keen cedar
#

right >.> ok i think i get it the reset button grah callthe the graph in the spawn button right?

strange gyro
#

Yep it'll call ResetCards in the spawn button's behaviour which resets the ActiveCards array to an empty one and syncs that to everyone

#

Then OnDeserialization in the spawn button will update the card visuals so they're all hidden using the reset active card states

keen cedar
#

with the sapwncards would the active cards need to be active? since i wan them to make a random card active?

#

no

#

no i wouldnt

strange gyro
#

Nah they would be false by default since they represent which cards are currently active which should be none

#

You probably don't even need it to be an array of booleans now that I know you only intended one card to be active

#

Just the array index of whatever the active card is would be enough if it's only meant to be a single active card

keen cedar
#

oh also there are 2 spawn buttons

#

one for each side the reset button only calls one

strange gyro
#

Do they share the same card objects?

keen cedar
#

nah each players representive cards 24 each side.. so i have the script on 2 buttons calling 24 cards

#

i can make it one button if the complicates thjngs

strange gyro
#

Nah that's fine

#

Your reset button just needs to call SendCustomEvent for both spawn buttons

keen cedar
#

how to iu make it 2 objects then?

strange gyro
#

Probably the simplest since it's only for two players

#

UdonBehaviour arrays are broken in graph so you'd have to use Component arrays instead if you want to store them as an array

keen cedar
#

AWSOME

#

now the reset button needs to reset the flips

#

i shouild bne able to do that one

#

would this work?

#

the tiles are 2 difrfrent objects one toggles off and the other on

strange gyro
#

Maybe but you'd only really want the person who clicked the reset button to fire ResetCards on the spawn buttons since they're going to sync to everyone anyway

#

Otherwise everyone is going to fight for control over the spawn buttons to change the sync state and fire it off to everyone

#

Gets kinda messy

keen cedar
#

eh fuck it fl;ip thjem yaself XD

#

ill say that

strange gyro
#

Also your flip states probably won't sync for late joiners

keen cedar
#

thats fine for now

strange token
#

people used to say not to network your game with networked methods, only to used fieldchangecallbacks on udonsynced variables, because people could somehow force-run the networked methods... was that patched out by the update VRC made that made worlds more secure recently?

strange gyro
#

A modified client could still do it but they're so rare nowadays that it's probably never gonna be an issue for the average world

#

At that point they'd be able to manipulate synced variable state as well

frozen igloo
# strange token people used to say not to network your game with networked methods, only to used...

current advice has moved away from network events but it's not entirely because of security. Standard synced variables are also susceptible to modified clients but that's not because of some security hole, it's because they're designed to allow anybody to sync with them.

That said, there are two key takeaways:

  • Syncing through synced variables is still recommended simply because it's more robust. When you rely on them for an entire project worth of syncing, network events tend to get pretty fragile and break a lot of rules
  • Persistence adds PlayerObjects, and unlike normal objects, PlayerObjects are not allowed to transfer ownership, and this is enforced on the server side. You could use them for the purpose of security to ensure you aren't getting anything messed with. That said, I don't think this method is going to be a "recommended best practice" any time soon, rather it's a technique you can use if you're in a situation where security is a high priority.
strange token
frozen igloo
#

read yes, write no

strange token
#

yeah

#

cool

#

so the "don't use networked methods at all because they can be hacked" is a lie, and a hacker could just manually call udonsynced fieldchangecallbacks in the same way, so it doesn't really matter?

frozen igloo
#

nothing is an ultimatum, but generally yeah

strange token
#

I do my best to build unhackable code but I don't want to give bad advice

#

Telling someone not to use networked methods just because is bad advice and now I will stop! xD

#

@broken rampart I apologize fren ;_;

broken rampart
#

ooo alr

frozen igloo
#

It's likely that the advice you mentioned to move away from synced variables was right after manual sync. Back when we only had continuous sync, it was pretty flimsy and so networked events were a good method to run all your networking on. Then manual sync released, and it's far more capable than either continuous or network events. So there's probably some sentiment along the lines of "network events are trash now, let's use manual sync" - that, I would generally agree with. But I would not agree with "never use network events because they can be hacked" since that's a bit of a misnomer

strange gyro
#

Network events are mainly considered useless because you can't pass arguments along with them, otherwise they'd be amazing

frozen igloo
#

Network events are the only form of networking that you can send on an object you don't own. As a result, they have their uses. They're also useful for quick and dirty implementations of something that doesn't have state. But as the networking backbone for a large system? Yeah, not recommended. They're just a bit too wasteful and slow for that

strange token
#

I probably had him overhaul his sytem in a way he really didn't need to do e.e

frozen igloo
#

I mean they are, but it depends entirely on how much you care about security

#

If this is a system where security is absolutely critical, move to the persistence beta and use synced variables on a playerobject. If you're just making something to have fun, then don't overthink it. Don't try to follow crazy advice that doesn't apply to your own situation. Just use whatever you feel comfortable with

iron burrow
#

We're planning a bigger world with persistence and such- does it go against ToS to auto moderate a user, that has been banned by us by permanently setting their persistence data to not gain levels and such? They can still walk around but will always remain lvl 1 and deal no damage and are not allowed to store items in their inventory- we're mostly worried about a client cheating unlimited items into the world and handing it out to others 💀
They'll be able to appeal on our discord as well in case they have been banned for any reason. I'm pretty sure that this will most likely only affect client users that have been caught* cheating.

tulip sphinx
#

yes

#

resetting world state (ie persistance) should bring them to nothing ever happened

frozen igloo
iron burrow
frozen igloo
iron burrow
#

Ohh that's what it means- I'm glad that its patched vrcRat

#

well time to figure out how to trust the client and that it won't try to spawn 999 items :D

stone badger
strange gyro
#

If they supported arguments and the ability to send the event to a specific target I'd only ever use synced variables for storing late joiner state

#

Even that wouldn't be necessary since the master or object owner could send the state to a late joiner when they join

#

Network events have the potential to be the most flexible way to sync data between clients

#

It's just held back by poor implementation

frozen igloo
stone badger
#

I use SendCustomNetworkEvent in two general cases. One is any time I need to have all the players play a one-shot sound. The other is on my Click Buttons which flash when pressed. Neither of these needs to be sync'd with players not already present.

blissful lark
cedar crescent
#

A couple times I tried network events for one-shot audio and animations. But ended up needing to say like play animation 3, sound 7. A separate method per combination would've been annoying to manage.

frozen igloo
strange gyro
#

I think they'd still become the defacto of syncing even if introduced now. Setting variables and waiting for serialization events that are disjointed from the event that caused the serialization is a pretty nebulous concept to grasp compared to sending a user named event along with the context data and handling that same event on the other side with the same event name and context data

#

That's why newbies to Udon still use SendCustomNetworkEvent without knowing the drawbacks of it

#

It's just more intutive by nature

strange gyro
#

Variable change events could kind of help to mitigate that if it supported data structures, you set the struct variable with your values and do stuff on the variable change event

#

At least that event can have a named association

stone badger
strange token
#

Let’s pray this feature somehow arrives with udon 2 if that’s not already confirmed 😛

finite sierra
#

i just hope Udon 2.0 will actually have parameters in networked methods. since it litterly makes zero sense. not to have it and it only makes any world creation alot harder. if udon is needed. also the extreme lack of documentation. and no real proper way to test worlds without needing alot of people to partake.

#

and also reduce the inconsistency that udon has when people load in worlds.

hoary frost
#

I agree, some networking bugs can be pretty nasty to fix, especially if they only show up with 8 or more clients in the instance

#

Having to wait 3 minutes on each build and test with multiple clients slows down workflow significantly

finite sierra
#

i have inconsistency with just 2 people. its 50/50 if it does as it should. but i noticed it happens alot more from a Cold Boot of a instance after a 10min or so. after that it happens less. but then if one more person joins so 3 people the error comes back.

#

and its specificly some things that ends up being null even through they are not.

ancient carbon
#

hi guys, I had a question, this is something I could easily do with something like cyan trigger, but im trying to make a toggle with UI, and I was curious on how I could make it synced: does anyone have an easy way to do this?

tulip sphinx
#

add component - global toggle (theres other toggles as well, its u# scripts examples), populate it with objects to toggle. Use Interact as name of custom event you use in the button.

ancient carbon
#

ill try that out now, thanks!

#

now do I add this to my toggle object, or where can I put this?

tulip sphinx
#

anywhere, it should have editable list

ancient carbon
#

Oh okay, got it

#

still under canvas tho right?

tulip sphinx
#

anywhere, you reference script in your button

ancient carbon
#

thank you!

stone badger
# finite sierra i have inconsistency with just 2 people. its 50/50 if it does as it should. but ...

Have you noticed anyone else using Udon with anywhere near the sync issues you seem to be having? Do you suspect nobody is doing the sophisticated stuff you are doing or might there be something else going on? Perhaps you could take a short survey of people with code that works half the time or that routinely fails after 10 minutes. You don't have to answer me so much as ask yourself, what could be up if nobody else reports such things as surprise null values?

finite sierra
# stone badger Have you noticed anyone else using Udon with anywhere near the sync issues you s...

i have no idea lol. But i do know there are creators who have made crazy big maps and had to work on it for a very long time to get things to work. to get around every issue they found. and its more or less because i am vocal about these issues and findings. And its more or less me observing that i run into issues that are specificly udon related. and there is little to no documentation of these problems or if its a known issue etc.

stone badger
#

There are a lot of creators and Udon developers on this channel. We all know some of them. I wouldn't attribute problems to the size of the map. I've worked on projects that have reduced 1000 lines of code to 100 lines of code. Reusing working and well-tested solutions is superior to one-up poorly tested solutions. If you spend a month digging a hole your hole is not better than the one someone dug in a day.

#

You write there is little to no documentation of these problems but have yet to identify a problem. You describe something you see but you haven't supplied any code. Lots of people do supply code and you would be surprised how many issues can be solved this way.

#

Udon has issues but it does not suck. It doesn't randomly null references that I am aware of and my world is used every day. Other world builders have dozens of instances with a combined count of hundreds of users. All of us here (I assume) use VRC on a daily basis and we aren't noticing random crashes in the worlds. When mine encounter an issue I can trace it back to the code that caused it and typically I overlooked some combination of events and handle it. This is how all software works, BTW.

#

try posting a class that causes a sync issue for you and possibly 90% of your issues will disappear.

frozen igloo
finite sierra
plush tiger
#

Would love even a single byte that I could send with an event so I can stop doing trash code like:

    public void OnDelayedEventDisplayReceipt()
    {
        SendCustomNetworkEvent(NetworkEventTarget.All, nameof(OnEventDisplayReceipt));

        if (UnityEngine.Random.Range(0.0f, 1.0f) < 0.03f)
        {
            // rare line
            int line = UnityEngine.Random.Range(0, _transactionRare.Length);
            SendCustomNetworkEvent(NetworkEventTarget.All, $"OnEventTransactionRareVoice{line}");
        }
        else
        {
            // common line
            int line = UnityEngine.Random.Range(0, _transactionPositive.Length);
            SendCustomNetworkEvent(NetworkEventTarget.All, $"OnEventTransactionVoice{line}");
        }
    }

    public void OnEventTransactionRareVoice0() { _wallVoice.PlayOneShot(_transactionRare[0]); }
    public void OnEventTransactionRareVoice1() { _wallVoice.PlayOneShot(_transactionRare[1]); }
    public void OnEventTransactionRareVoice2() { _wallVoice.PlayOneShot(_transactionRare[2]); }
    public void OnEventTransactionRareVoice3() { _wallVoice.PlayOneShot(_transactionRare[3]); }
    public void OnEventTransactionRareVoice4() { _wallVoice.PlayOneShot(_transactionRare[4]); }

    public void OnEventTransactionVoice0() { _wallVoice.PlayOneShot(_transactionPositive[0]); }
    public void OnEventTransactionVoice1() { _wallVoice.PlayOneShot(_transactionPositive[1]); }
    public void OnEventTransactionVoice2() { _wallVoice.PlayOneShot(_transactionPositive[2]); }
    public void OnEventTransactionVoice3() { _wallVoice.PlayOneShot(_transactionPositive[3]); }
    public void OnEventTransactionVoice4() { _wallVoice.PlayOneShot(_transactionPositive[4]); }
    public void OnEventTransactionVoice5() { _wallVoice.PlayOneShot(_transactionPositive[5]); }
    public void OnEventTransactionVoice6() { _wallVoice.PlayOneShot(_transactionPositive[6]); }
    public void OnEventTransactionVoice7() { _wallVoice.PlayOneShot(_transactionPositive[7]); }
    public void OnEventTransactionVoice8() { _wallVoice.PlayOneShot(_transactionPositive[8]); }
    public void OnEventTransactionVoice9() { _wallVoice.PlayOneShot(_transactionPositive[9]); }
#

Unless someone has a good way to play the same sound across all clients that doesn't involve dancing around sync timings or packing data into a single synced var

strange gyro
#

Nah, only thing I'd do to make that feel less painful to write out would be putting the logic in a common method:

    private void PlayRareVoice(int index) => _wallVoice.PlayOneShot(_transactionRare[index]);
    public void OnEventTransactionRareVoice0() => PlayRareVoice(0);
    public void OnEventTransactionRareVoice1() => PlayRareVoice(1);
    public void OnEventTransactionRareVoice2() => PlayRareVoice(2);
    public void OnEventTransactionRareVoice3() => PlayRareVoice(3);
    public void OnEventTransactionRareVoice4() => PlayRareVoice(4);
plush tiger
#

Yeah that's cleaner, but still painful

stone badger
#

People's measure of pain these days is interesting...

finite sierra
finite sierra
#
    [SerializeField]
    private AudioSource audioSource;

    [SerializeField]
    private AudioClip[] audioClips;

    [SerializeField]
    [UdonSynced, FieldChangeCallback(nameof(SyncLine))]
    private int line;

    public void OnDelayedEventDisplayReceipt()
    {
        if(!Networking.LocalPlayer.IsOwner(gameObject)) return;

        // Rare
        if (Random.Range(0.0f, 1.0f) < 0.03f)
        {
            SyncLine = Random.Range(0, 4); // lets say that the first 0 to 4 audio clips are rare.
            SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All,nameof(SyncLine));
            RequestSerialization();
            return; // Exits the method prevents the need to have an if else statement afterwards.
        }

        // Common
        SyncLine = Random.Range(5, audioClips.Length); 
// since random.range is inclusive it starts from 5 and up to the length of the audioclips array.
        SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All,nameof(SyncLine));
        RequestSerialization();

    }

    public int SyncLine
    {
        set
        {
            line = value;
            OnEventTransactionPlayVoice();
        }
        get => line;
    }

    private void OnEventTransactionPlayVoice()
    {
        Debug.Log(line);
        audioSource.PlayOneShot(audioClips[line]); 
// plays an audioclip based on what line has be synced. can be common or rare.
    }