#udon-networking

1 messages · Page 10 of 1

cold laurel
#

in this case it could be something like:
who we hit, how much, with what

#
int[] targetID;
float[] targetDamage;
int[] weaponType;
crimson matrix
#

Forgive me, I'm a bit of a noob when it comes to Udon networking, so I have no idea how I'd set up an event buffer.

#

I'm using CyanPlayerObjectPool, to give you an idea of what I'm working with.

heavy sleet
#

does anyone know how to make a whitelist only door toggle? for like clubs with age verify.

wintry bear
heavy sleet
crimson matrix
#

I still need help with this... How would I implement this? Is there a package that would enable this without having to reinvent the wheel?

vapid pagoda
crimson matrix
#

Oh, thank you! That's exactly the kind of package I've been looking for to do this, but never came up in my search results.

violet mist
#

somewhat of a silly question / sanity check: what exactly happens when RequestSerialization() is called from someone who is not the owner of the object it's called on? my initial assumption was that it would either do nothing, or ask the owner of that object for the most up-to-date values of its variables, but i'd like to confirm for sure what it's doing

like, say for example one player is the owner, and one player is not (ofc), and the object is synced manually. both players run a method that increments a synced integer by 1, and calls RequestSerialization() (first the owner, then the non-owner after the network settles). assuming the integer starts at 0, my initial assumption was that the integer would only increment by 1 for everyone (thus now equaling 1) since the owner is the only one who actually sends out the new data, but would that be incorrect? or would that second player then increment it to 2 and sync that new value? or?

tulip sphinx
#

its doing nothing

stone badger
#

Also the value doesn't "increment by 1". The value is set and the value is "copied".

violet mist
stone badger
jovial parrot
#

Why is this failing? i don't know how to fix this

#

oh my god, im dumb

#

i see it

humble girder
sand portal
#

Does anyone know if " SendCustomEvent" broken?

cold laurel
sand portal
#

I have a script here wanna use a collider to fire an animation on a mesh
The same script worked on the last version but not the current one

#

The animator script is working fine but it doesn't fire an event to the other one like it should on the previous version of the world

#

Animation works just not the event sending to the script like the old one did

cold laurel
#

Also, this is unrelated to the current issue, but it sending the exact same event for enter and exit is just begging for this to end up desynced.

sand portal
sand portal
cold laurel
#

You should have an event for entering the trigger and a separate one for exiting.

#

This way you can guarantee that it will be open when you're in the trigger

cold laurel
#

These enter and exit events are not very reliable, and oftentimes just don't fire

#

So you can end up with it closing when someone enters

#

With your current system

cold laurel
sand portal
#

curtainOpen

cold laurel
#

Correct

#

That is a problem

sand portal
cold laurel
sand portal
#

vrcCatThink that is the problem... hmm idk Q_Q

cold laurel
cold laurel
sand portal
cold laurel
#

Like, there are so many things that could cause it

sand portal
cold laurel
#

?

#

"The mesh"

#

Can you elaborate

sand portal
#

I... I m confused, it worked again. All I did is just created a new Udon script, pasted it to the new file

fresh stump
tired bone
#

Super random technical question, but, does anyone know if it's possible to override where a non-local player is displayed on a local client? As in, setting a position of a player, but not actually moving them there, it's just to display on the local client.

tired bone
#

Related to above post but also there's more details involved when talking about it;

Hey @cold laurel I've seen your worlds and your github code and you seem to be very close to what I'm trying to do, and extremely knowledgeable on it, is there any chance I could talk to you about a project I'm working on, and get your advice on what approach I should take? I can dm you or talk here, totally your call. I hope to get some advice from someone as much of an expert as you!

cold laurel
tired bone
# cold laurel I would prefer having the discussion here so it can benefit others too.

Totally! So, I'm making a world with a driveable bus that's meant to simply be a social driving world, and I want to make it so players can walk around in the bus like normal and have no problems even while the bus is in motion. I have two things I need to fix, and the solution to one seems to slightly get in the way of another.

  1. I want players to be able to move around the inside of the bus without any problems, and still move with the bus as it moves.
  2. I need to be able to display players in positions they are not, so that I avoid the problem of everyone lagging behind the bus because of network latency if they are standing up. I want to avoid the problem of locally you're the only one standing up on the bus and everyone else is trailing behind.

I'm aware of using stations with immobile only set on remote clients, that's a possible solution for #2, but #1 my original solution uses teleporting to match the moving platform's motion and unfortunately teleporting a player un-seats them from any station they are in, regardless if they are allowed to be mobile.

I could use a station to solve both problems; ie, have a fake player controller inside the bus that's parented to the bus, and then network it's position however I please, and therefore allows them to have no problems moving around, but as of right now, players using a fake player controller (via a station they are forced into) makes their walking animations not play, and desktop has some neck turning problems, I'm wondering if there's any solutions that don't disable walking animations?

strange token
#

I’m not sure what it looks like to watch a remote player interact with this script, though, I’ve never actually seen it in play

tired bone
cold laurel
#

One for physics, and another for visuals

#

Here is an example of me playing around with this concept last month

#

I wanted to be able to walk around inside my spaceship while people were piloting it

#

Your use-case is a bit simpler as I assume you only have one bus to worry about

#

So you won't need to desync player locations via stations

tired bone
#

People will be able to walk around outside the bus, ideally

cold laurel
#

will the bus be moving while that is the case?

#

I mean, it's totally doable

tired bone
#

Yeah, I think I know what you mean though, you mean that you have the actual physics going on, and then all the visual models are separate and relative to what's your current visual position, and you can offset players by using the immobile-only-on-remote trick, which keeps animations?

cold laurel
#

Yep

#

Basically, when you enter the bus you put the visual part of the bus at 0,0,0 with no rotation

#

then display the rest of the world in the bus physics object's local space

#

when you exit the bus, just undo all of this

tired bone
#

Oof... I know that's possible but dang that's a big programming task, haha

cold laurel
#

a few hours

tired bone
#

Maybe if you have existing expertise, haha, but I think I know what you mean. Problem is that it means you can't have any static objects and the like I'm assuming?

cold laurel
#

correct, absolutely no static batching

#

and the overhead of moving the whole world every frame

#

And it makes everything else in the world harder to do. Like, if you have other rigidbodies or particle effects that rely on collision

tired bone
#

Oof...

#

it might be better to just have walk animations not work when only inside the bus, and then maybe wait for vrchat to add the ability to fix some other aspect that makes all this even necessary to work around. I totally appreciate the way you think about it though!

#

because the performance overhead is kindof a dealbreaker sadly

#

if it was performant on larger more complex worlds I'd be totally down to try it, but ideally I'd like to have significant detail in my world

cold laurel
#

Hopefully we get the ability to parent the player to objects without stations sometime

tired bone
#

yeah that would be good, or to be able to set animation parameters, because all we'd have to do is tell the player's animator that they're not in a station

#

we CAN set custom animation controllers for players on stations, but obviously one walk cycle isn't going to work for all avatars, so it wouldn't quite work the way one would expect.

#

thank you for your insight, and hopefully vrchat continues to improve giving us access to more great worlds like your space ship world!

strange token
#

@cold laurel are you able to manually trigger VRChat animations from a world interaction in the same way NUSS writes into custom animations to save content?

cold laurel
#

The thing is, that requires the player be in a mobile station or not a station at all

strange token
#

🤔 I thought it literally called something that triggered an animation on the avatar if the name exists

#

I’m gonna DM him about this, if I’m completely wrong, I have been wrong this whole time and not known lmao

cold laurel
#

I might be wrong too

#

So it will be nice to find out

tired bone
#

Weirdly enough some stations can trigger the avatar to think it's not in a station for one frame when you open up the larger static menus, which is why gogoloco can make a player stand up weirdly on some stations sometimes, but I think it's only a glitch on vrchat's side and we can't set that up to reproduce ourselves, sadly.

signal trellis
#

Little question.
I couldnt properly find any documentation con confirm what i'm looking for atm, but when working with UdonSharp, when using a String Array, does UdonSynced work on that too? I found a list of variables it would work on, but it never said anything if it worked on arrays.

cold laurel
signal trellis
#

alright, thanks

#

I'll see if make my thing work with this information

lusty pagoda
#

how will networking work when after changing variables and requesting serialization i instantly change owner to someone else

frozen igloo
sturdy hornet
#

so im trying to make this only work for the player that enters the area like local but the problem im having is it does it for everyone

#

so if someone else leaves the area it also updates for everyone

#

i want it to just be one person that this effects

#

i turned of synchronization and turned it to none

#

and i thought that would work but it doesnt

#

how do i do this

strange crane
#

I have never touched graph. Is there like some networked event to turn the gameobject on/off?

sturdy hornet
#

i thought it was all local without like asking it too but i guess what i was doing was automaticly?

#

but i got this and i hevent test it yet but gimme a min

#

how do i run to people at th same time in the editor agian?

strange crane
# sturdy hornet i guess

Yeah, you don't want to use SendCustomNetworkEvent unless your wanting to send that to everybody.

#

I'm not to sure if this is what you created after I sent my message or before.

sturdy hornet
#

so how do i make it just do it for one person?

sturdy hornet
#

but i hevent tested it yet so one min

sturdy hornet
cedar crescent
strange crane
#

But I assumed it was local by default but would make a lot of sense.

sturdy hornet
#

is it like checking if its that local player that did it and if it is it does true?

cedar crescent
#

yeah!

sturdy hornet
#

you a real one

tired bone
#

SendCustomEvent is not networked, SendCustomNetworkedEvent is networked

lusty pagoda
#

if player spams serializations in some object how to properly assign owner as master so player wont override anything with serialization spam

sand portal
#

Hello, I have asked kapa ai about Udon, I wanna attached a gameobject to players like those game world did.
however the script it provided is not complete/broken. Does anyone else here know the fixes?

    [SerializeField]
    private GameObject objectToAttachPrefab; // The prefab for the object to attach

    private Dictionary<VRCPlayerApi, GameObject> playerObjects = new Dictionary<VRCPlayerApi, GameObject>();

    private void Start()
    {
        int playerCount = VRCPlayerApi.GetPlayerCount();

        for (int i = 0; i < playerCount; i++)
        {
            VRCPlayerApi player = VRCPlayerApi.GetPlayerById(i);
            playerObjects[player] = CreateGameObjectForPlayer(player);
        }
    }

    private void Update()
    {
        foreach (var playerObject in playerObjects)
        {
            if (playerObject.Key != null && playerObject.Value != null)
            {
                VRCPlayerApi.TrackingData headData = playerObject.Key.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);
                playerObject.Value.transform.position = headData.position + Vector3.up; // Position the GameObject above the player's head
            }
        }
    }

    public override void OnPlayerJoined(VRCPlayerApi player)
    {
        playerObjects[player] = CreateGameObjectForPlayer(player);
    }

    public override void OnPlayerLeft(VRCPlayerApi player)
    {
        Destroy(playerObjects[player]);
        playerObjects.Remove(player);
    }
    private GameObject CreateGameObjectForPlayer(VRCPlayerApi player)
    {
        GameObject gameObject = VRCInstantiate(objectToAttachPrefab);
        gameObject.transform.SetParent(transform);
        gameObject.name = $"{player.displayName}'s GameObject";

        return gameObject;
    }
}
cold laurel
#

You might not even need a player object pool for this

sand portal
#

I will give it a try now

#

ty

cold laurel
sly hawk
#

sometimes i really hate udon

lusty pagoda
#

id array

cold laurel
tired heron
#

does ondeserialization get called automatically when you join?

tired heron
#

any idea why this isnt being synced properly in OnDeserialization?

#

this is the length of the arrays from the late joiner client

#

and this is from the first client that set the values, which should be synced but aren't for some reason

tired heron
#

nevermind I'm stupid, I forgot you need to do array = array.Add() with UdonArrayExtensions instead of just being able to do array.Add()

tired bone
#

we can serialize some arrays? Oooh interesting, guessing not arrays of gameobjects?

meager briar
#

For a late joiner, do they automatically request serialization data for a behavior if the behavior uses manual sync, or do I need to override onplayerjoined and request it?

tulip sphinx
#

auto

tired bone
#

that's good to know actually

tulip sphinx
strange token
meager briar
#

If an owner of an object changes a synced variable, but does not request serialization, does that new value still get serialized when a new player joins?

Trying to handle the case of the object owner leaving, but still needing to set some synced variables

stone badger
meager briar
#

What I mean is when a new player joins, they get serialized data. But I wonder if that's cached or not.
If it's not then I can just set it locally for all players, then the new player will get that data serialized

stone badger
#

They get data but whatever "everyone" already has.

#

The data has to be sync'd that's the key.

#

It always works the same. Take ownership of the object, set the sync'd values, call RequestSerialization.

meager briar
#

Ah nuts
I'm trying to handle releasing a 'station' (not a VRC station) when a player leaves, but I'm unsure of the way to go
I imagine if a player ungracefully disconnects, OnPlayerLeave is called while they still own it, and I'd imagine at that point that client cannot call RequestSerialization

#

I was thinking of doing in OnPlayerLeft some kind of ownership transfer to master, but then what happens if the master leaves

stone badger
#

What I do (someone was holding/owning one of my objects when they left) is have the master player check if the player that left owns anything and cleans up the object.

#

When the master leaves all objects transfer to the new master.

#

There is always a master until the last player leaves.

meager briar
#

For that I wonder if it happens before or after the Left callback

#

If it happens before then I can just transfer ownership to the master in OnPlayerLeft

#
    public override void OnPlayerLeft(VRCPlayerApi player)
    {
        if(HasPlayer() && Networking.LocalPlayer.isMaster)
        {
            BootPlayer();
        }
    }

    public void BootPlayer()
    {
        havePlayer = false; // synced
        interactedPlayerId = 0; // synced
        HandlePlayerLeave(); // sets up UI stuff, gets called on Deserialize when havePlayer = false
        RequestSerialization();
    }
stone badger
#

I think you can count on all the "internal stuff" happens before we are notified. So transfers have occurred and then when the system is stable you are told the player left.

meager briar
#

In that case this should work then 🤞

harsh pebble
#

Does anyone happen to know if vrcobjectsync transfers impulse values when a synced object collides? Would it trigger OnCollision for remote players? Making a script that lights up an object based on its collision impulse magnitude

tulip sphinx
#

@harsh pebble no, only the owner runs physics on the object, for everyone else those components are disabled and they just get transform

harsh pebble
strange token
#

Did phasedragon ever post a completed version of the networking presentation other than the linked one here? I wanna come back to it

tulip sphinx
#

dont think so

violet mist
#

hey, does anyone know if "OnPlayerJoined(), that joining player obtains ownership of every object in the instance" is a bug that vrc is working on fixing atm ? it's a bit game-breaking .-. unless that behavior is intentional for some reason ? in which case, is there some easy way I can circumvent it for objects that rely on keeping the owner I assign to them, without also preventing ownership transfer OnPlayerLeft() ?

frozen igloo
#

I feel like I would've heard of that happening by now. When did it start? Is it only under certain conditions? Is it permanent, or only for a brief moment?

violet mist
# frozen igloo I feel like I would've heard of that happening by now. When did it start? Is it ...

i'm not 100% sure exactly when it started, but the first time my community reported it to me was 3/24 (they just reported things "unlocking randomly" but after looking at the logs, my best guess is that's what's happening)

I only have hard proof of the game setting ME (the creator of the world) as owner once I join, but iirc i've seen a log where it happened to someone else in the community as well

i've attached a screenshot of what happens when I join the world. a script reports that I'm the owner of its corresponding object, despite the fact that i've JUST joined, and below you can see the username of the previous owner (that should still have ownership)

i'm not sure exactly how "permanent" it is, but i do know the ownership transfer remains in effect for at least a couple minutes, so i'm inclined to believe it is permanent

#

it could always just be my fault somehow, in which case I apologize if that ends up being the case, but i've been stuck on this issue for weeks and i've read the codebase through countless times, and i can't imagine any part of my code that would cause this

#

i just read through another community member's log that actually didn't have this issue. could it be that it only sets the world creator as owner upon joining ? also, could it possibly have something to do with that recently-implemented "dynamic master switching" ? or does that not touch object ownership

heavy spindle
# violet mist i just read through another community member's log that actually didn't have thi...

The "dynamic master switching" you speak of is when the current master times out or leaves, all Objects not given explicit ownership through Networking.SetOwner will have their owner set to a player VRChat deems to have the best system and networking capabilities. This is in pretty stark contrast to the traditional FIFO system that was in place before. The timeline you describe lines up pretty decently, but the previous master has to "time out" or leave for it to trigger. For "timing out" for quest users, it's when they have their headset taken off for some amount of time I cannot think of atm.

violet mist
#

but in any case, i don't expect the new system to be the issue per se, but i was rather implying/suggesting that perhaps while modifying the code to implement that change, maybe some ownership-handling code was messed up accidentally in the process, or that there was some edge case that wasn't accounted for, etc.

frozen igloo
violet mist
dark bane
#

I'm not too sure if this would be considered an udon question but I'm guessing it does have to do with networking.
I was thinking about how a video player works and how it connects to YouTube to be used in vrchats system. I'm not talking about preloaded videos directly from YouTube. I am talking about having direct access to YouTube and being able to search up videos while in the world on the video player and all the videos you want are added into a playlist/watching next list. There's no tutorials on how this works though. How would one make set something up like that?

stone badger
solar crescent
#

Some stuff is local, some is global. So stuff is usually happening the person that casts an event or to all. But what if I want to happen to everyone BUT the caster. If the caster uses a spell on anyone but themself or even catch a specific person that is not the caster of an event. Anyone knows how to achieve that?

violet mist
coarse sentinel
#

Hello, I need some help, I have a script where I change an Integer triggered by OnPlayerTriggerEnter (Integer + 1) and OnPlayerTriggerExit (Integer - 1).
I am using Manual Sync ("[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]") to sync my Integer ("[UdonSynced] public int syncedIntegerValue;").
I set the owner ("Networking.SetOwner(Networking.LocalPlayer, gameObject);"), modify my value (+1 or -1) and RequestSerialization.
I then set the states of my local player as well as through OnDeserialization (based on my synced variable).

When I test this (using build and test) with 2 players where I have one player enter the trigger and shortly after exiting again while the other one is watching, I get the following sequence (Note: I added a bunch of Debug.Log messages to debug the issue.):

#

The player entering and exiting the trigger sees the following (Note: A trigger execution starts with the debug message "Synced"):

#

This is all fine and works as it is supposed to.

#

The player watching sees this:

#

Here, the "OnDeserialization" method is called twice, even though I "RequestSerialization" once.
Beyond that the values seem all wrong as well.
What it should display is this on enter:

#

And this on exit:

#

Since I cant find anything wrong on the coding end, I have a theory why this is happening, but I would like to confirm this with someone who knows better.
Since I am using Build and Test, I essentially have myself twice and once it detects that the player is entering (player 1 walking into the trigger) it shortly after detects that the player has exited (player 2 watching). I assume this is just some limitation of build and test, since I dont have anyone else right know to test this with in game. Please let me know what you think.

coarse sentinel
#

Update: Tested it with a friend and the issue still remains. Now I have no clue what I am doing wrong. 😅

coarse sentinel
#

Update: The issue was caused by having one script for enter trigger and one script for exit trigger on the same gameobject.

sour trout
#

Best way to calculate latency? currently in my game world i have an UdonSynced START_TIME. This start time is set to the users system clock + a buffer. Players are reporting timers in games say like -60 minutes and stuff. So I'm assuming trusting system clocks is a bad idea lol.

I was thinking instead to use the Networking.GetServerTimeInSeconds() instead and then use Networking.CalculateServerDeltaTime() to find the latency?

heavy spindle
#

That'd be sound logic. Never try to compare two clocks' times since NTP exists for a reason. I need to replace my CMOS battery since my time always keeps going off by quite a bit.

sour trout
strange token
#

If I put an udonsynced child under each object, could I set the child to owner in order to change variables related to that object without it affecting the parent?

#

I noticed today that syncing an "active" networked bool for an object makes its position sync when I move it, but I want only to sync the variable and not the entire object yet...

#

I want to be able to flag objects as active so another user won't use that instance, but it shouldn't be networked position-wise until an actual grab

stone badger
#

I'd like to chat a bit about the video players I have it working but there are still some issues I run into. Most notably I'm receiving "player error" sometimes. I don't know what causes them so I don't quite know what I should do in response. I can try reloading (might be worthwhile to try). And once a person gets that error the video player no longer works. Even when I respawn the world it will not work. I have to restart the VRC app and that fixes things. Very curious behavior indeed.

heavy spindle
#

ytdlp probably caches responses or results from URLs for a specific amount of time or possibly indefinitely which would make sense for the lifetime of the child process

#

Unless all urls are broken

frozen igloo
# sour trout Best way to calculate latency? currently in my game world i have an `UdonSynced`...

In ondeserialization, it gives you a deserializationesult with sendTime. sendTime is a timestamp that is formatted into the context of the receiver's time.realtimesincestartup, so everyone will have a different number. But if you sync an offset like, say, 10 seconds in the future and then sync it, everybody can then add 10 seconds onto the sendTime and then they know exactly when it should happen, in their own time context.

stone badger
# heavy spindle ytdlp probably caches responses or results from URLs for a specific amount of ti...

I don't know what causes the failure on only some connections. And then it can affect them all. If something is cached that would help explain why creating a new instance would have no effect as the instance of the VRC app is the same. Do we know of a "reset" option on the player? Perhaps forcing a blank or known URL would work. I don't see anything like it in other VRC video worlds which makes me think it is due at least in part to my particular set up.

heavy spindle
#

I do know of one world at least that goes back to a default playlist once a track finishes, but idk. Ytdlp / any other extractor VRC may use is pretty abstracted away

#

If the binary hasn't been updated in a while, could try replacing it with a newer version after backing up the old one ofc

#

YouTube did kinda recently do some stuff that broke a few extractors I know of

stone badger
stone badger
#

I'm working on the idea that it is time-out condition and I've added a retry attempt. I will see if it makes a difference but I don't like shooting wildly into the darkness.

stone badger
#

I also wonder if it could be due to the throttling that VRC has on various services.

heavy spindle
stone badger
dawn kestrel
#

Im trying to make a button that when clicked by anyone tells every client to run a function. It works just fine in play mode but in a build it does nothing for every client including the owner. For what ever reason, the SendCustomNetworkEvent wont fire, but other code will. Perhaps im misunderstanding how it works?

tulip sphinx
#

uuuuh i suspect that destroying smth that supposed to send network event might not be a good idea

dawn kestrel
#

It was just to test to see if it works, everything i've put into that second function wont get triggered. Even the client that pressed the button wont have the object be destroyed

dawn kestrel
#

I found out the issue has something to do with Instantiating the button. Placing the button in the scene manually will cause the event to fire. I'd rather not have to do anything like object pooling or preplacing a bunch of the buttons. Hoping I can still use Instantiate and somehow get the networking stuff to work on it.

wind surge
#

Could someone possibly guide me in the correct direction as of what the best way to do this would be. I'm going to be syncing quite a lot of bools and shorts. Around 15 bools and maybe around 4-5 shorts. What i'm planning to do is have all the bools packed together and request serialization whenever one of the bools are updated and the same thing would apply to the floats. Or would it be better to have them be sent separately in different scripts instead of being packed together. I'm just wondering if it's better to send all the data together at once regardless if it needs to be updated or send the data seperately only when it needs to be updated

#

I'm just trying to figure out the do's and don'ts of networking xP

cold laurel
wind surge
cold laurel
wind surge
#

That’s what my idea was for doing that. I’ve done a similar thing before on smaller projects

cold laurel
#
  • Networking.SetOwner(_localPlayer, gameObject);
  • Change the value.
  • RequestSerialization();
wind surge
#

Well yee. I know how to do that. I’m just wondering if it’s better to send the data all at once in a single script or send it individually across multiple scripts

cold laurel
#

Each serialization is expensive

#

Optimally you'd want to have as few of them as possible

#

How often do these values change?

cold laurel
wind surge
#

So it wouldn’t matter then since again it would be sent the same number of times when a variable changes. These variables for the bools would be updated probably at max every few seconds but on average once every 5 minutes

cold laurel
#

just put it all in one script then

wind surge
wind surge
cold laurel
#

Unless you specifically handle that.

#

Or, you could just use VRChat's networking how it's intended and let VRC handle all of that for you.

wind surge
#

If you’re talking about continues I can’t do that as it’s too slow xP

cold laurel
#

???

#

I'm not talking about the Continous sync mode.

wind surge
#

Oh okay, then what are you talking about exactly?

cold laurel
#

If you only sync what you think has changed then the synced variables don't represent the whole state.

#

So a late joiner will only receive part of the data.

wind surge
#

Okay I see what you mean

cold laurel
#

When someone joins the game VRC will automatically send them the latest version of the synced variables.

wind surge
#

Mhm yes

wind surge
heavy spindle
#

but point taken

vernal arch
vernal arch
strange token
#

I’m trying to set up an object pooler by placing one instance of an object in each user’s spawner, so a user needs to flag that they’ve grabbed an instance and sync that they have it, but I don’t want to sync the actual positions until it’s picked up from its spawner

#

So I need some sort of synced variable stating that an instance is active without actually syncing the entire object, so it doesn’t sync it actually moving to the spawner

strange token
vernal arch
#

So can I interpret it this way ? : You have several objects, that can be spawned ("position teleport") to a spawner and you want the position to be synced only when it is spawned

#

If I remember correctly, VRCObject Pool do take care the activeness of every object in the pool, so if they are inactive, they won't be synced, and when they are spawned, the object will be activated, and VRCObjectSync Script on that object will be active and thus syncing the position when it is spawned

cold laurel
strange token
vernal arch
vernal arch
minor flicker
#

following a tutorial, I made an udon script that teleports players to a designated position when they enter a set trigger
is there a way to make it also toggle objects as well? I have a separate script for toggling objects but it's for buttons rather than walking into a trigger

#

I want to have it change the world's background music to another locally when you teleport to the second area

heavy spindle
vernal arch
#

Keep in mind : while using OnPlayerTriggerEnter, make sure to make a branch to ensure that it is the local Player who is entring the collider OoO/

vernal arch
wispy arrow
#

So I'm a little confused with what the best way to do this is

I want to make a card game where the cards are loaded in from an external source via string loading, to save me having to manually reupload the world to add cards, so I'm wondering what I do when it comes to making sure every player has the same cards, so I was thinking of the following method:

  • Instance master creates instance and joins
  • My code loads all of the card info and parses it into two UdonSynced arrays (for the different card types)
  • When new players join, instead of them loading from the API, they wait for all cards to be synced over the network (which could take a bit of time as more are added)
  • Boom, everyone has the same card

But VRChat syncing limits seem rather limiting if my game has too many cards

#

Would this work and be the "recommended method"?

obtuse echo
wispy arrow
obtuse echo
#

There are different ways to do it with different amounts of complexity.

wispy arrow
# obtuse echo Okay, I'm having trouble explaining this properly without writing a wall of text...
  • GitHub stores two files that contain a list of cards (a file for each type of card)

  • I want to use that, instead of a textasset or array built into the world to make it easier to update

  • I was planning to separate those two into arrays of strings (one of which will also have a number associated with it, but for our purpose right now, not required)

  • When a player played a card, I would sync an integer that referred to the index of the selected card in the array, as opposed to syncing the whole string

  • If I updated the cards and a player joined after that, the array would be larger, and playing a newly added card would cause an "Index was outside the bounds of the array" error

cold laurel
wispy arrow
# cold laurel You could include a version number in the data you download. Make sure the owner...

seems useful, or if i wanted to be weirder, i could store the previous update's cards in an alternative branch in the same repo, and if the owners' cards are out of date, (will 100% of the time only ever be one update behind, vrc instances don't last that long), then load them from the legacy branch instead, and warn the player that the lobby is out of date and doesn't have the latest cards

#

not sure which is better ux-wise

cold laurel
wispy arrow
#

i assume the faulty assumption is only ever assuming the version is one behind

cold laurel
#

Yep

obtuse echo
obtuse echo
wispy arrow
#

yeah but the branch url could be hardcoded, like, replacing main with legacy in a new vrcurl variable

wispy arrow
#

wouldn't be too hard and prevents unnecessary "this instance is outdated" stuff

#

and refreshes should take less than 30 seconds (accounting for latency between telling clients to refresh, and them all reporting they're updated), so

obtuse echo
#

Just to make it clear: I'm differentiating card type ids that get downloaded and are used to generate cards vs cards that have a card type id that gets synced so other clients know what a card is displaying.

wispy arrow
#

So like, CAH style is what format I'm using for my cards, where there's black and white cards, the format differs between the two because black cards have an identifier at the end that signals how many white cards it takes to satisfy the black card

So like, the black card format is

Some prompt, _____, and a text file.|1
_____ + _____ = _____.|3

Whereas the white card format is just, strings separated by newlines, like

Unity.
VRChat.

And there will be a 3rd VRCUrl that points to a version file that will just read something like

0.0.3-alpha
#

What I want to do is:

Every player loads the latest cards from the text files, and also loads the version into another string when they join

Every 30 minutes, the instance master queries that version file and if the version is not the currently loaded version, send a network event to all clients to let them know they need to refresh, and each client (including master) redownloads the black and white cards again, and non-masters copy the version number from the master (to save having to make a 3rd request)

Network events make more sense, since they don't need to be done for late joiners, late joiners will always have the latest version by design

#

Obviously in practice there's more to it (like waiting until a round is over before commencing with the refresh, to prevent some potential edge cases where the game could possibly break)

obtuse echo
# wispy arrow So like, CAH style is what format I'm using for my cards, where there's black an...

Ahh, I was definitely thinking about different types of card games.
However, I'd honestly still do it in a similar way I described before. I would not try to manage version as I don't think there is much need for that. Nor would I try to sync ALL the prompts for new joiners either. I would make it simple for myself and rely on a cyclical string download that would only add to the current pool of prompts. If I receive an id that's higher than my pool count, I simply redownload the prompts to display them.

#

Btw, pro tip: VRCJson is really fast for reading text files, if they get a bit bigger in your case.

wispy arrow
obtuse echo
#

If it's too much data, you could just make a separate url that tells you whether there was an update in your main json or not

wispy arrow
wispy arrow
obtuse echo
#

Either way, it's just ideas. I'm sure there are various ways to do it.

wispy arrow
#

and i'll test around and see what works

#

thank you for the advice! you've been very helpful :)

stone badger
wispy arrow
obtuse echo
obtuse echo
wispy arrow
#

yeah, i would not like to have to lock players in a box that says

"TURN ON ALLOW UNTRUSTED URLS, THIS GAME DOES NOT WORK WITHOUT IT"

would be pretty shit

#

though they really need to rework the untrusted urls system
a prompting system would be so much better, like:

worlds have to ask for permission to access a list of hosts (or all hosts), and the player gets a popup that says

"Allow [world name] to access [url1], [url2], [url3]?"
"Allowing this world to access untrusted domains could be a privacy risk! Please make sure you trust the creator of this world before allowing access."

with like, a 5 second timer before you can press Allow

stone badger
#

Do whatever makes sense to you but URLs are very common and most people have it turned on (I think) or are willing to. How many people do you see in the video playing worlds? And yes you can get the version number but necessarily in the direct method you displayed. Generally speaking nobody is going to know what version number to type in.

#

I hear all the chat so what privacy risks do you think I am open to that you aren't?

wispy arrow
#

eh, vrchat has the untrusted urls system in the first place

#

fuck knows why it exists, worst case scenario someone gets my ip address (big deal, right? (not))

stone badger
#

Because someone does something in the name of security doesn't make it a case for security. Nobody know where you live only the IP address of the "server" that issued you one.

wispy arrow
#

meanwhile other platforms like roblox (despite only allowing requests on the server) allows you the freedom to make POST and GET requests as you please, without the limitations imposed by VRChat

stone badger
#

It can be two cities away from where you live and it doesn't pinpoint your house.

wispy arrow
#

vrchat has a lot of dumb security features, imho, they need to review it all

hoary frost
obtuse echo
hoary frost
#

Since loading is I assume client sided

obtuse echo
obtuse echo
hoary frost
hoary frost
#

So far ive got 2.5mb per song without using a player without compromising too much on quality.
My world being quest compatible itll add up really quickly

obtuse echo
# hoary frost Pressing buttons to play specific music, with a big library, but id rather not h...

There are video player implementations that offer playlists. I'm probably the wrong person to ask since I rarely use them, but I chose this one last time: https://github.com/vrctxl/VideoTXL
There is also this which seems nice but I have yet to try it: https://architechvr.gumroad.com/l/protv

GitHub

Sync and local video players for VRChat with design consideration for events. - vrctxl/VideoTXL

faint rock
hoary frost
hoary frost
sudden raven
#

Anyone have any idea what this is?

#

Second row

mossy ruin
#

is there a way to update a sync value as often as the player bones update? Example I want to sync the VRCPlayerAPI.TrackingData of the players hands and head, but i want it to be updated in time with when the players bones are update, such that the position of where they should be is correct in relation to the avatar
I found I cant use a continuous sync because with what im doing it overloads the network, so it needs to be controlled manual, which i found syncing ever 0.2 seconds seems faster then the player updates (most of the time)

heavy spindle
#

I do this with a CyanPlayerObjectPool most of the time

#

If you wanted to get super in sync for some reason and not possibly waste CPU cycles, the bones are updated in FixedUpdate iirc because that's how FinalIK is. You should probably fact check me. To update after this, use a SendCustomEvent within a FixedUpdate to essentially act as a "LateFixedUpdate". Or VRChat may push Udon script execution after FinalIK making this unnecessary.

obtuse echo
heavy spindle
#

Ah. Well if that's the case perhaps I got myself mixed up in the terminology 👍

#

Err no. LateUpdate is called after Update not FixedUpdate

#

FixedUpdate is based off Time.fixedDeltaTime

obtuse echo
#

Also, it sounds like they want faster sync of positions than what VRChat is doing by default? I'm not sure if that is a realistic goal, since they might throttle even manual sync with more players and scripts syncing in an instance.

heavy spindle
#

What they're syncing doesn't need to be synced though

heavy spindle
#

PostLateUpdate is called after LateUpdate lol

#

It's all on the Update cycle

obtuse echo
heavy spindle
#

I just use Update personally so it's whatever, yes

#

I don't mind potentially wasted CPU cycles in this case. If I did, I'd make my own timer with SendCustomEventDelayedSeconds

obtuse echo
heavy spindle
#

Object ownership goes as fast as it can afaik

#

Even Udon manual syncing has a refresh rate

#

I wouldn't try to reinvent the wheel. At that case, I'd just suggest to VRChat to change the network spec if time is being wasted

#

Though I don't think VRChat is being developed to prioritize potentially trivial things like that as not every world is as time sensitive

mossy ruin
tulip sphinx
#

if it needs to follow the bones, then it obviously can be interpolated, remote player is never faster than 10hz

heavy spindle
mossy ruin
#

i can, but i wont have a solution for desktop

obtuse echo
mossy ruin
#

for vr its fine for the most part. The only thing that seems off it if im holding an vrcpickup it doesnt fallow the bone

obtuse echo
mossy ruin
obtuse echo
#

There is a great asset someone made for that

#

Don't remember the name and I'm on my phone, give me a sec

mossy ruin
#

i origonally was making them fallow and offest to to the bone, but they keep moving around

#

was it MMMaellon's smart object sync?

obtuse echo
#

Yep

heavy spindle
#

What's the use case for this

mossy ruin
#

I have manually synced objects that i need their positions relitive to the hand synced, also i require a position that works for both desktop and vr for an object to fallow the hand

#

or "hand"

#

said object could be somthing like a blast or flamethrower effect for magic or what not

#

i hesitate to just look through this because i don't wanna just copy someone's work

heavy spindle
#

Cant you just like store an offset transform relative to the pickup to spawn the effects at and make effects a child of the pickup if you need it to simulate in local space?

obtuse echo
mossy ruin
mossy ruin
#

least not an optimal one

heavy spindle
#

Yes. You misunderstand what I said. They can still be children of the pickup.

obtuse echo
heavy spindle
#

The VRCPickup?

mossy ruin
#

ah for the items, right the issue there is making an offset of the bone keeps changing

#

so it become inaccurate unless you keep updating the offset

heavy spindle
#

Weapons have the VRCPickup. For example I have a gun and a transform which signifies the bullet exit. I can spawn effects at that offset

mossy ruin
#

however, for the temp object spawn which doesnt have a pickup, there isnt an item to fallow

#

right, the way my item is structured there is a pickup as the handler, and a spawned item to represent the item

#

the problem is its manually synced, so i need where the item is supposed to be for others

heavy spindle
#

Pickup as the handler?

mossy ruin
#

yes

heavy spindle
#

Ah so the script that's on the VRCPickup is manually synced?

#

ObjectSync wouldn't work then I see

mossy ruin
#

ya, if i made it contious i couldnt do what i wanted to do with it

#

like making it switch to fallowing items, going two handed, swaping on physics, etc

#

also itd break the networking, cuz i have a lot of them

heavy spindle
#

Cant you make the script a child of the VRCPickup and access the parent with transform.parent?

mossy ruin
#

no

#

the handler is the parent, the child contains the item script

heavy spindle
#

why not

mossy ruin
#

but this still doesnt solve syncing

#

if the parent is contious sync for vrcobject sync, i cant have a large number of them

heavy spindle
#

Cant you have one per player

#

How many players do you expect?

mossy ruin
#

no, a player might have many of them

heavy spindle
#

how many?

mossy ruin
#

like one on each hip, a shield on back, several throwing kniefs, i cant just limit them

#

or if the game is somthing different, who knows

heavy spindle
#

I understand your problem better. Okay

mossy ruin
#

ya, overall its a system that allows a item to be any item in the system, so you dont have to go theres 10 of this item, and 10 of this item, etc

#

i have a pool of 300-500 that can become whatever item

#

tis on the excessive end, but it works

tulip sphinx
heavy spindle
#

You would still have to have a pool of manually synced objects since instantiated cant have network syncing

mossy ruin
#

also, the items arnt per player, they exist in the world and can be manipulated by anyone

#

so you can pull a potion off your belt, hand it to your friend to use, that kinda thing

#

or you carry a plate with 10 slices of pizza on it to hand out and share

tulip sphinx
#

you spawn pickup when needed and show item per hand or smth

mossy ruin
#

so its in hand while holding it

#

it can also be equiped to your arm, hip, or what ever

obtuse echo
# obtuse echo https://github.com/MMMaellon/SmartObjectSync

This asset also has some "stick" functionality I haven't messed with yet.

But either way, you probably want to sync the offset to the bones when attached, do some custom syncing when held (based on tracking data), and probably let the physics handle when thrown. I'd going to need some work to handle all the weird vrchat edge cases anyways

mossy ruin
#

the vrcpickup was difficult to sync becuase i didnt want every object if someone was holding it to keep updating its postion

#

it made a lot more sence to update where it was held, and tell everyone to update its position based on that

#

less network syncing

mossy ruin
#

overall it moves around and doesnt track to the hand

#

it tracks to the desktop tracker, which if i had that i wouldnt need to update its offset to maintain accuracy

heavy spindle
#

You can at least instantiate a VRCPickup for desktop users so they get arm extending and that VRCPickup doesn't need to be synced itself

mossy ruin
#

i suppose one thing to think about is my tracker sync probly only needs to care about desktop

heavy spindle
#

Itd just be a local only pickup

mossy ruin
#

im not fallowing

heavy spindle
#

Maybe I'm confused. I'll just show myself out

obtuse echo
mossy ruin
#

hmm...i suppose somthing i can do for desktop only is somthing like...instead of syncing the postion/rotation just sync the offset of the traker to the bone

#

in that way, when somthing is trying to get the position, it will be relitive to the already syncd bone rather then a point in space that may or may not be ahead or behind the model sync

obtuse echo
vapid pagoda
#

hi @mossy ruin! ive had the same issues for my new project, i ended up discarding vrcpickups and making my own pickup system, but for desktop tracking specifically, im simply using head position and applying an offset position

(you wont be able to get the hand reaching out effect, i dont think it will be possible with instantiated pickups in general)

still WIP: (also using cyan player pool but this is a separate script)

        [NonSerialized] Vector3 desktopPosition = new Vector3(0.175f, -0.15f, 0.35f);
        [NonSerialized] Quaternion desktopRotation = new Quaternion(-0.5f, -0.5f, -0.5f, 0.5f);
        [NonSerialized] VRCPlayerApi.TrackingDataType head = VRCPlayerApi.TrackingDataType.Head;

        [NonSerialized] HumanBodyBones rightHand = HumanBodyBones.RightHand;
        [NonSerialized] HumanBodyBones leftHand = HumanBodyBones.LeftHand;

        void Start() { }

        public override void PostLateUpdate() {
            if (Owner == null) return;

            transform.parent.position = Owner.GetPosition();

            if (inVR) {
                rightHandTracker.SetPositionAndRotation(Owner.GetBonePosition(rightHand), Owner.GetBoneRotation(rightHand));
                leftHandTracker.SetPositionAndRotation(Owner.GetBonePosition(leftHand), Owner.GetBoneRotation(leftHand));
            } else {
                VRCPlayerApi.TrackingData headData = Owner.GetTrackingData(head);
                rightHandTracker.SetPositionAndRotation(
                    headData.position + (headData.rotation * desktopPosition),
                    headData.rotation * desktopRotation);
            }
        }```
mossy ruin
#

main issue with that is if the user looks straight up, their head bone does not tilt to look up enough

vapid pagoda
#

let me test that real quick

mossy ruin
#

it was the issue i was running into, when i pointed straight up it doesnt go up enough, causing a desync in where the user is aiming

vapid pagoda
#

but do you need that data?

mossy ruin
#

yes, an example i had was a temp item spawn that fallows the players "hand"

#

if i use the head data, the user can only look so high, and cant aim at things directly above them, or at least it doesnt aim high enough

#

i forget the degree of angle, but its enough to be frustrating

#

it was a solution i used within my dragudon ball z world, it made hitting people who flew above you impossible

vapid pagoda
#

i see

#

is the hit detection done on the target, rather than the person attacking?

mossy ruin
#

in the case of that system it was firing a partical to hit by the target, however its irrelivent for the current system. Currently the issue is if i wanna use the system for a magic system to let someone do a flamethrower spell

#

the spell wont spray above a certain threshold, which is not accetable

#

because then you cant direct it straight up

#

anyways, i have a solution to try, so im going to see how itll work, thanks tho

obtuse echo
mossy ruin
#

i currently for desktop am syncing the headrotation offset from the head tracker, then basing the left/right hand tracker off the head tracker

#

so when i get it, i get the tracker rotation with the offset, then get the hand positions/rotations based on their offsets from the head tracker

obtuse echo
mossy ruin
#

and turns out syncing it 5 times a second seems to be enough to look smooth enough

#

ya, what im syncing is the offsets of said tracker

#

so i already have an player object pool where everyone owns their own object which i use to send data through

#

i just added the tracker sync onto that

#

and since all i need to sync is desktop, its only activly syncing if there is a desktop user

obtuse echo
mossy ruin
#

the headbone does not rotate vertically beyond a certain point, so the head tracker even locally will be different

obtuse echo
mossy ruin
#

example of it working

obtuse echo
mossy ruin
#

why the left and right hand wouldnt be attached to the head?

#

its because thats where the players left/right hand are in desktop

#

the same usecase in vr is that it comes out the hand

obtuse echo
#

But making it go off from your head is a different feel I guess.

mossy ruin
#

so if you pickup and object, it uses the local hand track for where the item goes far as i can tell

#

i plan to test now i have a sync trackingdata position/rotation, but its to simplfy where the hands/head is

#

when picking up an object, desktop has it move around, before i was just syncing the offset based on hte bone, but i have to correct it several times

#

if i just base the offset on the tracker, i dont need to correct it and it leaves less syncing by item

#

also itll look smoother then correcting it several times

obtuse echo
#

What do you mean by correcting? If you sync the offset position and rotation of the bone, you don't need to do that afaik

mossy ruin
#

so when you pick up the object, the frame you do your hand is to your side

obtuse echo
#

From what I gather your problem is that if you attach something to the head, you can't look up fully on remote?

mossy ruin
#

so if i wanted to sync it by bone for vr and desktop, i need to correct it as the desktop hand moves to "grab" it

#

and while running around, the item continues to move around, and you cant base the offset on the bone of the head or hand because it keeps moving compared to them

#

this offset is needed to sync it for remote

#

but ya, also, if i base somthing on the head for remote sync, then you have limitations when the player looks up

#

id prefer to have no limitions and the system to work intuitivly and quickly

#

oh i should mention, i have 3 types of handlers for my item spawner

obtuse echo
mossy ruin
#

type one is what is typical of vrcpickup, with items that hold their own data and have the player take ownership. Type 2 is ment for more idle or evioronment spawned items which has a manager owned by own person which handles their data (ment for very low interaction). Then temp items, which are ment to spawn and then disapear, so they just have local data with no set ownership as they are ment to go away

#

the blizard in the gif was a temp item, so i can cast a spell and it shows the spray

#

spawns a pickup which you can grab and interact with

#

its jerking around because i still have code in there trying to correct it XD i need to work on it tomarrow to remove that and see if its still good

obtuse echo
strange token
#

Am I correct in understanding that this means a serialization request was rejected because the requester was not the owner?

vapid pagoda
strange token
#

Yeah just wanted to make sure I was able to single out the log that shows that

#

now if that disappears, and my log doesn't appear, I'll know to scream :3

#

that actually showed I wasn't receiving anything correctly, so thanks alot!

quartz crystal
#

I am making a menu with join and leave buttons to set the player list, but it seems to be out of sync, need some advice.

humble girder
#

You need to beware that you put button SetActive before you actually check for condition whether a player can joined or leave or not. This will cause the button state to change regardless of joining result, and joining by other player will not update the button state.

quartz crystal
humble girder
quartz crystal
humble girder
quartz crystal
humble girder
quartz crystal
#

I thought it would be stored on playerNames

humble girder
quartz crystal
#

for local player, yes

humble girder
quartz crystal
humble girder
elder girder
#

how can i manually update a sync var by code? i cant find anything in the docs

humble girder
elder girder
#
            {
                RequestSerialization();
            }``` would this sync all synced variables on my script?
humble girder
elder girder
#

im trying to do something where a joining player will try and sync its var with the owner's

humble girder
elder girder
#

with manual synced method selected, right?

humble girder
elder girder
humble girder
elder girder
#

ill explain what im doing in more detail. im making a day/night cycle and want to sync the time of day for all players. The owner of the script does RequestSerialization(); at the beginning of the day which works. I test it by building and testing with 2 clients, one client always joins the world later and the time of day is noticeably out of sync (i have it sped up for testing) untill the owner reaches a new day with fires RequestSerialization(); and syncs all players up.

humble girder
#

Like how you used it for syncing day/night cycle.

elder girder
#
    float dayProg = 0.25f;```

and this in update()

```        if (dayProg > 1)
        {
            if (Networking.IsOwner(gameObject))
            {
                RequestSerialization();
            }
            dayProg = 0;
        }
        dayProg += Time.deltaTime / dayLength;```
humble girder
elder girder
#

The syncing every new day part works. it updates and checks > 1 locally. syncing on join doesn't. i would work around by the owner checking for new players and firing RequestSerialization(); if someone joins

humble girder
#

You have 2 choices:

  1. Use continous sync to do realtime update on dayProg. Or
  2. Use manual sync to sync time of start of day relative to server time. Then calculate day prog from start of day time locally for every client.
elder girder
#

i tried continuous sync and it looks very laggy. ill try my work around.

#

is there a OnPlayerJoin method?

humble girder
humble girder
elder girder
humble girder
elder girder
#

it would tell everyone including the new player to sync to the owner's time

humble girder
elder girder
#

ill test it, thanks for explaining this

stone badger
# elder girder ill test it, thanks for explaining this

A couple of items worthy of note... if @humble girder offers concerns about reliability it warrants concern. Also there is almost (like 99.99% of the time) no need to be tricky with code. The best code is straightforward and obvious and as a side-effect it works. If one has some odd behavior it is surely due to a mistaken understanding of how things work. I wouldn't (for instance) update a property marked with UdonSynced and not actually sync it. You are asking for weird unexplainable behavior and then you add more code to counter the weird code. And then repeat 🙂

lusty pagoda
#

does requestserialization sends it at the very moment or at the end of frame

random parrot
#

I believe it's at end of frame

#

or at some point after udon is done executing

random parrot
#

should probably have pinged that.. @lusty pagoda

lusty pagoda
#

so if i spam multiple times at the same frame it doesnt change anything with networking

#

or run it and still running my own code in same frame

#

it will wait for me to finish

random parrot
lusty pagoda
#

no i meant multiple requestserializations

random parrot
#

ah, doesn't matter it just does it once at the end of the udon execution

#

no matter how many times you call it

#

it just requests serialization, it doesn't do serialization

dawn kestrel
#

Im having issues with a delay in synced variables. An example would be:
button clicked -> send event to owner -> owner modifies synced variables -> send event to all clients -> clients then used modified synced variables
Im using a continuous sync method on the object that the variables are stored on. Would changing it to manual be quicker, or are there methods I could use to reliably wait till the synced variables have been sent to the clients to then trigger the events?

frozen igloo
# random parrot I believe it's at end of frame

@lusty pagoda not end of frame, but rather at the next network tick, which is 20 times per second. The rest is correct though, multiple requestserializations will only ever trigger one serialization

random parrot
#

didn't know that part, that's also really good to know

cold laurel
#

So don't call it every frame.

random parrot
#

sorta related to this, but what's the timing with networked events and variable deserialization?

lusty pagoda
#

not connected

lone zealot
random parrot
#

soo.. never rely on data being synced with networked events, but you can rely on other data being being synced on deserialize?

lusty pagoda
#

i found out best way of networking is performing deserialization on sender

#

so everybody runs exact same function

lone zealot
dawn scaffold
#

does setting too many as continuous cause stuff to stop working?

#

or go slower?

humble girder
dawn scaffold
#

so for local buttons what do you recommend?

humble girder
dawn scaffold
humble girder
dawn scaffold
#

what about objects that are only locally seen but have a global effect?

humble girder
dawn scaffold
#

gotcha gotcha thanks!

dawn scaffold
humble girder
dawn scaffold
#

gotcha gotcha

#

yeah because ill have like a lot of people in the world and that starts making a few things start slowing down and stop working

compact valley
#

Anyone know why the sdk throws errors when importing new network id's?
Also throws id error on build. Both pc and quest scenes are identical. Using separate projects both on unity 2022.3.22f1, latest sdk version.

compact valley
#

Pls ping me if you might know why

maiden tinsel
#

hello, does anyone has an example of how to request ownership of an object using udonsharp? i do Networking.SetOwner(Networking.LocalPlayer, gameObject); but OnOwnershipRequest is not being triggered

#

oh thanks!

#

comment dissapeared

tulip sphinx
#

nah i think i wrong

heavy spindle
#

OnOwnershipRequest is used to potentially block the transfer. If you just wanted an event for when it's actually transferred, OnOwnershipTransferred

#

The OnOwnershipRequest is only run on the owner's side

maiden tinsel
#

does ownership transfering is something that i can test in the simulator inside unity?

#

i tried deleting OnOwnershipRequest and OnOwnershipTransfer is not being triggered either

#

so i have no idea what am i missing

heavy spindle
#

ClientSim should be able to do that. You'd spawn another player.
OnOwnershipTransferred(VRCPlayerApi player)

#

Not OnOwnershipTransfer

#

Also keep in mind that the event is run on this Object which had its ownership changed. You can't do something like a blanket global listener

maiden tinsel
#

this is my code

#

i dont get the 2nd debug.log triggered

heavy spindle
#

You can entirely remove the OnOwnershipRequest since you always return true

maiden tinsel
#

tried doing that and also OnOwnershipTransfered is not being triggered either

#

so im not sure if im missing something

heavy spindle
#

Then it's likely you'll need to run two instances of the client to fully simulate the network just to be safe and sane

maiden tinsel
#

being sane sounds good uwu, thanks for the help, let me try it

#

it is working in the standalone clients, thanks

maiden tinsel
#

OH i think that the problem is that the master of the instance already owns the object, so onOwnershipRequest is not being called, casue i already own the object

#

Is there a way in the vrc simulator to switch places with a spawned player?

#

Like, control the remote player insie unity

flat shoal
#

hey guys could i have a little help, im trying to create an object for each player that joins and given them ownership of it so i tried doing this but it deson't work, could i get help with what im missing thanks!

tulip sphinx
rough grove
#

So I'm just dipping into udon networking for the first time and I'm trying to make sure I'm on the right track:

If you're dealing with logic for a game on a single object, the correct way to update the game state is by having each player take temporary ownership of that centralized object whenever they want to request serialization for their contribution (e.g. updating score), right?

My original intuition was to have that object under the exclusive ownership of a single "game master", and have players send custom network events to them so that they can update all the logic and request serialization in a centralized way - but I'm guessing that's not the practical solution, right?

tulip sphinx
#

cant you just have objects per player?

#

overall yes ownership and serialization is better for important and long lasting data

rough grove
#

objects per player is interesting, I hadn't considered how to structure it that way yet - I'll have to consider how to refactor it that way and see where that leads me, thanks

tulip sphinx
#

i mean just everyone updates their score when needed and when its time to format a table it just locally reads data per player. but ig it depends on what it looks like, im thinking of prison escape lobby

strange token
#

Yeah you can technically write things from a “peer to peer” perspective since each player can own their own object with a set of synced variables for their personal values, then people can just use data from the selected player/players when needed

rough grove
#

I see, yeah that makes a lot more sense than what I was trying to reason out, appreciate you both

strange token
#

I should take my own advice and decouple/detangle some of my own master stuff at some point lol

#

Late joiners kill running games in my game atm 😂 I think everyone runs stuff master should be managing because I gave players too much ownership over the start-game handling

#

Note: make sure you don’t end up telling every player in your game to try and start the game for every other player when you click the start game button 👌

#

That’s gonna take me hours to figure out for sure 😭

tender echo
#

I could’ve sworn I’ve been to a world a that culled remote players outside of a specific room. Is this still possible from the world creator end? If so, can someone point me in the direction of creating that sort of logic for a player occlusion zone. 🙏🏻

#

Goal: I’d like to be able to hide players sitting at spawn so that players loading in can watch an in-game “cutscene”/ animation without others clipping into it lol

humble girder
tender echo
tired quail
#

will a OnDeserialization trigger when you load into the world if the synced property hasnt changed from the default starting variable, or does it always triger on load into a world?

#

After a quick little test it appears that is the case

tulip sphinx
#

request serialization exist just for that, it would never sync itself

lone zealot
maiden tinsel
maiden tinsel
#

i just finished a small board game with udon, but i dont know how to handle player disconections at mid game to properly reset the table, i see "OnPlayerLeave" in udonsharp, but i dont know what can i do with it, in my mind, only the owner can modify the object, so onplayerleave means the owner already left, so i dont know what to do to reset the owned objects back to the initial state

proper coral
#

Can someone recommend me a getting started with networking guide that isnt by vrc? I couldn't follow that one well

stone badger
stone badger
stone badger
maiden tinsel
#

I dont want to be rude but your answers are not helping anyone =3

stone badger
restive cliff
# maiden tinsel i just finished a small board game with udon, but i dont know how to handle play...

Probably more of an architectural thing than networking. Adding on to what Tom said about the ownership being transferred, you could re-run what you used to set the board game up after the ownership has transferred OnOwnershipTransferred(VRCPlayerApi player).
I read that you don't have such a function to reset, a good step would be to store the initial board state as variables to reference later like in this situation. For example, their positions on the board.
I know nothing about your setup and implementation so try starting here

maiden tinsel
restive cliff
#

built & test with 2 clients

heavy spindle
timber ferry
#

so, i'm making a system where: on start, a timer will begin counting down, and when it reaches zero a duck from an object pool spawns. i want the selected duck that spawns in to be the same for every player, and i want the same for the timer. how can i do that? this is my current script:

[Header("- Variables -")]
[SerializeField] private VRCObjectPool ducksPool;
[SerializeField] private Transform duckSpawnLocation;
[Header("- Options -")]
[SerializeField] private float duckDelay = 120f;
private bool timerActive, poolFull;
private double targetTime = 0f;

private void Start()
{
    SetTimer();
}

public void SetTimer()
{
    Debug.Log($"<color=purple><b>{this.name}</b></color> <b>Timer was set</b>");

    if (timerActive) return;
    timerActive = true;

    targetTime = Time.time + duckDelay;

    RunTimer();
}

public void RunTimer()
{
    float timeLeft = (float)(targetTime - Time.time);
    timerActive = timeLeft < 0;

    if (timerActive)
    {
        SpawnDuck();
        timerActive = false;
        SetTimer();
    }
    else
    {
        if (poolFull) return;

        SendCustomEventDelayedSeconds(nameof(RunTimer), timeLeft % 1);
        Debug.Log($"<color=purple><b>{this.name}</b></color> <color=white><i>There are {timeLeft} seconds until duck</i></color>");
    }
}

public void SpawnDuck()
{
    ducksPool.Shuffle();

    GameObject duck = ducksPool.TryToSpawn();
    if (Utilities.IsValid(duck))
    {
        duck.transform.position = duckSpawnLocation.position;
    }

    Debug.Log($"<color=purple><b>{this.name}</b></color> <color=green>Duck spawned!</color>");
}
#

also, i have "poolFull" created for when every object in the pool has become active. i haven't set that up yet though, cause i'm not sure how i'd check if all object pool objects are active or not

#

(each duck object also has a VRC_ObjectSync)

#

(don’t think that relates but might as well mention it)

stone badger
# timber ferry (don’t think that relates but might as well mention it)

I don't see any networking code which is likely going to cause you issues. My first thought is that I wouldn't have every client set a timer and act when the time has elapsed. Might it not be easier and more accurate for one player to manage the timer and then have that person post an event that all players can just react to?

#

I don't know what you want to occur when a late joiner arrives but note that they would start their own timer using that code and as a result wouldn't display the duck at the same time. They would if they were present and an event was used.

timber ferry
#

i was thinking that i would have only the owner of the object control the timer. i just haven’t added any networking yet because i needed some pointers first, as this is different from other things i’ve networked, since it has a timer that controls an event

stone badger
#

I thought about it a bit more and there are issues you will need to solve. It will almost certainly require a synced variable indicating which element the players should spawn. You can't shuffle them on each client and expect the same results in each client. You (seemingly) don't need a pool but it depends upon the effect you are looking for.

timber ferry
#

what i’m looking for is to have the owner control the whole thing, so that one person runs the timer and spawns a random duck. and i want the time that it spawns to be synced, and the chosen duck to be synced, preferably for late-joiners aswell which is why i have an ObjectPool, because “the objects are enabled or disabled for late-joiners where appropriate”

stone badger
#

Ah that makes sense. I think you are going to need some network code to prevent every player from running Start() on this class.

timber ferry
#

would a simple if (!Networking.LocalPlayer.isOwner) return: line work?

stone badger
#

That should work. I have a suggestion since you seem intent on using elaborate log statements.

#
Debug.Log($"<color=purple><b>{this.name}</b></color> <b>Timer was set</b>");
#

Create a static class (name it Logger or something close) and add static methods to it that accept some message text "Timer was set" in this example and have that method customize the layout and call Debug.Log. You would pass both the "name" and the message in the example above. You can create lots of variant methods if you want some green, red or whatever. You can even create methods for Bold() and such. Typing all the html directly into the "app" is way too much work and can obscure the purpose of the code. You really don't want to be debugging mismatched HTML markup. 🙂

timber ferry
#

that’s an amazing idea

#

i just like the colored text, and it separates my different logs more too

stone badger
#

I understand the purpose. I use colored messages as well. I have methods that handle the coloring and I don't specify "purple" for example but rather use const strings that indicate severity. So debugcolor, infoColor, etc. You can expand on that. I simply Logger.Trace something and would get the trace color and the message in trace format.

#
Logger.Info($"{_nameofClass}.{nameof(Start)}");
#

That will have the Info color and if I want date/time or some tag that identifies my app-centric log messages it is all handled in the Logger class.

strange token
#

I’ve always been afraid to ask this question because I feel like an idiot because I think I’ve asked it like a bunch, but I never wrapped around in my head correctly. Are we able to just make a class static and then reference it from other classes, and that works? Years ago I tried making a static class and it didn’t work and then I remember hearing that we were supposed to be getting support for it and thinking that it was part of Udon 2?

#

@stone badger Specifically off of your conversation above ^

#

Sometimes when I see people say that in here, I wonder if they mean something that people call static but it’s a workaround, and I’m not actually sure if they’re just mean a real static class

stone badger
# strange token I’ve always been afraid to ask this question because I feel like an idiot becaus...

You should think of it more like clarification than "idiot" 🙂 Sometimes taking information in a different form (or repeated) works. A static class has a definition in languages that support them (like C# for instance). The class just exists. You don't instantiate one.as you would a regular class. There are some design considerations as when to use a static class but we don't have dependency injection (for instance) in VRC/Udon so a static Logger works well. Best thing (I think) you can do is to create one in a project you are working on and just try it.

heavy spindle
#

Also, Udon# for U1 does support static classes kinda. It more or less just appends the methods used to the bytecode of the programs that use it. This implementation isn't ideal, but it works™️

strange token
#

Gonna have to get into the headspace of statics because I worked myself out of those when I learned they wouldn’t work here

stone badger
faint rock
#

So I have an object that does something to the player on grab. When the player drops it, it undoes those changes. But the issue I'm running into is how to handle the item being stolen, because the way I grab the "current grabber" is by checking the owner, but if the item is stolen then the deactivation will end up firing on the stealer as it'll run, the owner will now be the person that stole it and obviously that's not going to work. Can anyone think of a good way to handle a deactivation on something like that?

obtuse echo
faint rock
#

I have already disabled stealing apparently, so the issue I assumed was due to stealing was not. So... one less problem, one more problem, lol. But yeah, storing properly makes sense.

lusty pagoda
#

i can autosuggest any link even dynamic one right

lusty pagoda
#

id like to user paste in any link and after confirmation edit it out and display another prompt with modified link

#

can i do that

wintry condor
lusty pagoda
#

ofc i know that

#

im saying autosuggesting entire url

#

for player to just press ok

strange token
#

@lusty pagoda is your question about building suggestions off of partially inserted text or inserting the selected suggestion into the url field? Those are two different things happening to solve your question

#

(The middle step of comparing the retrieved text to an array/database and returning a related suggestion is definitely doable on udon)

wintry condor
#

maybe you can use one of these events to get when the player finished typing, then comparing the input field url text with the suggestions you defined at editor time. if one of them match, you just have to swap the url at the input field

wintry condor
#

also im not sure if this question should be at udon-networking...

strange token
#

Good point lol

lusty pagoda
#

whats the time limit for string loading

timber ferry
#

the only thing i need networked now is the progress bar, because of course, it only updates for the owner

#

should i try and sync the slider's value from that script, because it's what controls the value, or could i make something and attatch it to the slider itself to network the value?

lusty pagoda
#

i managed open it up but no idea about autosuggestion

#

inputfield.text inaccessible and inputfield.textComponent.text does nothing

lusty pagoda
humble girder
#

Is it that bad if I recognized that link?

lusty pagoda
#

yes

lusty pagoda
#

ah i see

#

seturl is for suggesting link

#

but then its useless because i already have vrcurl in that case

#

i thought suggesting can be done without player input

#

well whatever i can make server handle that as well

rugged dock
#

I have observed that for some reason, the play audio part of this udon graph is synced between players, but the rest of it isn't what's wrong with it?

jade lance
#

Hi

faint rock
faint rock
humble girder
#

I recognized it by dQw

lusty pagoda
#

whats the limit of udonsynced variable size

#

and can i load just variables i want not all variables

cedar crescent
#

I sometimes see this code in prefabs.

if (!Networking.LocalPlayer.IsOwner(gameObject))
{
    Networking.SetOwner(Networking.LocalPlayer, gameObject);
}

Is there a reason to do that instead of this?

Networking.SetOwner(Networking.LocalPlayer, gameObject);

Does SetOwner not check if the player already owns that object?

frozen igloo
frozen igloo
cedar crescent
lusty pagoda
#

aw not even a megabyte

#

can i abort loading of string

timber ferry
#

Is this properly synced? it looks like it to me, but i just tested in-game and it didn't work

[UdonSynced, FieldChangeCallback(nameof(RNDNum))] private int rndNum;
[SerializeField] private float frequency = 10f;
private ParticleSystem particles;

void Start()
{
    particles = this.GetComponent<ParticleSystem>();
}

private void OnEnable()
{
    if (!Networking.IsOwner(Networking.LocalPlayer, this.gameObject)) return;

    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), 0.5f);
}

public void RandomlyPlay()
{
    RNDNum = Random.Range(0, 20);
    if (rndNum == 10 && particles.isStopped)
    {
        particles.Play();
        Debug.Log($"<color=lightblue>{this.name}:</color> <color=green><b>Playing!</b></color>");
    }

    Debug.Log($"<color=lightblue>{this.name}:</color> RNG was {rndNum}");
    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), frequency);
}

public int RNDNum
{
    set
    {
        rndNum = value;
    }
    get { return rndNum; }
}
restive cliff
strange gyro
#

You don't RequestSerialization after setting RNDNum so it won't sync the new value

timber ferry
#

i didn't think i had to though, since i used the equivalent of OnVarChanged

timber ferry
strange gyro
#

Do you have some other script that reads RNDNum and plays the particles for other clients? The script you posted will only play particles for the player syncing RNDNum since non-owners never run the RandomlyPlay loop

#

Seems like you'd want to do something like:

[UdonSynced, FieldChangeCallback(nameof(RNDNum))] private int rndNum;
[SerializeField] private float frequency = 10f;
private ParticleSystem particles;

void Start()
{
    particles = this.GetComponent<ParticleSystem>();
}

private void OnEnable()
{
    if (!Networking.IsOwner(Networking.LocalPlayer, this.gameObject)) return;

    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), 0.5f);
}

public void RandomlyPlay()
{
    RNDNum = Random.Range(0, 20);
    RequestSerialization();
    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), frequency);
}

public void UpdateParticles()
{
    if (rndNum == 10 && particles.isStopped)
    {
        particles.Play();
        Debug.Log($"<color=lightblue>{this.name}:</color> <color=green><b>Playing!</b></color>");
    }

    Debug.Log($"<color=lightblue>{this.name}:</color> RNG was {rndNum}");
}

public int RNDNum
{
    set
    {
        rndNum = value;
        UpdateParticles(); // Plays particles for owner when updating sync state and non-owners when sync update is received
    }
    get { return rndNum; }
}
#

Also keep in mind that if the object owner leaves, your state will stop syncing since nobody will be running the RandomlyPlay loop

#

You'd probably want some extra logic to handle the owner leaving in OnPlayerLeft

timber ferry
#

and thanks for updating the script to make it work, i’ll try it later

stone badger
# timber ferry and thanks for updating the script to make it work, i’ll try it later

There seems to be a bit of ambiguous behavior from what I can see. You essentially have a Boolean condition (not an integer). I see the random number but aren't you only acting when the number is equal to 10? That is a Boolean condition and updating the number repeatedly may not be necessary. Is it that you want a 1 in 20 chance of the particles playing?

strange gyro
#

If you're using VRCObjectSync for the pickup I doubt it will take ownership of the child gameobjects automatically, haven't tested it myself though so you'd have to confirm that

#

But if your child object is disabled and reenabled every time you pick up the parent object that part should at least handle rechecking the owner, just gotta check that is owner is who you are expecting it to be

#

You could always called Networking.SetOwner on the child object in the parent's OnPickup event to make sure it passes

timber ferry
#

that’s all i want the system to do really. when the object is enabled, start sending events every “frequency” seconds, and if a 1 in 20 chance happens, play the particles

(and for the particles to be synced when playing)

timber ferry
#

actually, now that i think about it, i can just use a network event…

it isn’t something that needs to be synced over-time, it’s just a short burst-like effect

stone badger
# timber ferry yes exactly. i want a 1 in 20 chance for the particles to play every “frequency”...

Then I believe you have made it too complex. There is seemingly no reason every player needs to know about the failure values. The owner can handle the logic and simply instruct other players to "play" not to think about playing. I don't know what you mean my synced particles exactly. They will all play at the same time but at the particle by particle level. And any networking must take into account what happens when a late joiner appears.

timber ferry
strange gyro
# timber ferry for a different system, how would i do this? i have a different script in the wo...

Something like this should work, thinking about it more OnOwnershipTransfer would cover more cases than OnPlayerLeft:

private bool IsEventActive;

private void BeginEventLoop(float frequency)
{
    if(IsEventActive) return;

    IsEventActive = true;
    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), frequency);
}

private void OnEnable()
{
    if(!Networking.IsOwner(Networking.LocalPlayer, gameObject)) return;
    BeginEventLoop(0.5f);
}

public void RandomlyPlay()
{
    // Stop looping if ownership is lost
    if(!Networking.IsOwner(Networking.LocalPlayer, gameObject))
    {
        IsEventActive = false;
        return;
    }

    RNDNum = Random.Range(0, 20);
    RequestSerialization();

    // Keep looping
    IsEventActive = true;
    SendCustomEventDelayedSeconds(nameof(RandomlyPlay), frequency);
}

public override void OnOwnershipTransferred(VRCPlayerApi player)
{
    // Start looping for new object owner
    if(player == Networking.LocalPlayer) BeginEventLoop(frequency);
}
graceful socket
#

anyone here know how to do some vrchat network diggin for clients using something like wireshark or similar? looking to figure out who drew something using pens, externally

meager meadow
graceful socket
#

🤮

strange token
#

I just did a local test & confirmed a new player loading in didn't kill an existing game w/ 10 frames of delay, but is this realistic? Should I just make it a few seconds just in case and put up a wall like people always talk about, or is it alright to stick with a tiny delay like this?

#

(my issue is that IsPlaying is serialized so no delay kills all the swords lol)

tired quail
#

Is there still a way to get the instance creator? (not the master)

heavy spindle
#

And each player increments the ID

#

Or well. The instance creator doesn't always have to join the world and can join the world later, but getting the instance creator isn't available afaik

#

You cannot access user data unless they're in the world

tired quail
#

I dont need their info while they're outside the world, just if they create it but dont join first (IE drop a portal and herd a few people through and then follow)

heavy spindle
#

Then you can't get that info

#

The closest thing is just incremental ID tracking

harsh pebble
tired quail
#

Although I have a feeling the instance owner behaves differently when its a group instance, ill have to double check that

harsh pebble
#

A quick question of my own, hopefully an easy one- I'm making a vending machine. last time I tried to instantiate a prefab with udon on it during runtime, it wouldn't sync properly. Has this changed? Or might I be better off with a bunch of disabled objects in a pool and enable and disable one by one instead of instantiate and destroy

tulip sphinx
#

vrc object pool exists exactly for that. you cannot and probably never will be able to instantiate networked objects, each of them must be present at the scene during the build

harsh pebble
tulip sphinx
#

yes

harsh pebble
#

Awesome, thank you!

lusty pagoda
#

is ownership gets transfered always exactly on deserialization

cosmic shell
#

Can an object be owned by a player not in the instance? How does this affect synchronization, if at all?

humble girder
cosmic shell
#

Is it the case that a world must therefore revert to its default state if all players leave?

#

As an aside, is Networking.InstanceOwner not functional?

tulip sphinx
#

instance is destroyed when its empty

heavy spindle
#

Instances actually stay alive for quite some time after the last person leaves. Some instances can stay up for up to 2 weeks since the last person left iirc

#

But a player always owns objects unless the instance is in such a state. When a player leaves, all objects they owned are returned to the master or the instance itself to be allocated to the next person who joins assuming the role of master.

#

But trying to think in terms of ownership while the instance, and by extension script execution, is paused is illogical

stone badger
# heavy spindle Instances actually stay alive for quite some time after the last person leaves. ...

re: instances remaining active... I'd like to get some idea where that info came from because it sounds incorrect. VRChat worlds are Photon instances on Photon servers right? And they have server regions and scope. So what would the purpose be of having say an instance of a world on one regional server? Not saying it couldn't happen but I don't see why any attempt to keep the instance alive would benefit anyone.

humble girder
# cosmic shell What makes it *illogical*? Is it because data are not saved in the world, and ca...

An instance is not ephemeral which mean data of an instance doesn't get saved on server. Object being owned by anyone is illogical because otherwise everyone can own an object even there hasn't been in an instance.

Networking.InstanceOwner function doesn't exist. There is only Networking.IsInstanceOwner. But InstanceOwner doesn't indicate default object owner for networking purpose, other than a person who created an instance.

cosmic shell
humble girder
heavy spindle
# stone badger re: instances remaining active... I'd like to get some idea where that info came...

A while ago, they announced something regarding people being able to make instances for events and links would remain active for a certain amount of time (2 weeks iirc), meaning that instance was reserved for that amount of time.

I'm also able to rejoin instances I've been in before through VRCX even if they have 0 players, but this may just be VRCX re-creating the instance. The first bit of info I know is true though

#

If network synced Objects retain positions and such and the instance stays in a half active state, I'm not sure or if it's just reservation of ID.

#

either way, I consider that staying active

stone badger
meager meadow
#

My understanding is that persistence is in closed beta right now, so that is coming, but it's not something most of us have access to yet.

frozen igloo
# heavy spindle Instances actually stay alive for quite some time after the last person leaves. ...

this confusion is because there are multiple places where an instance can be alive. In the API, it's true that they can live for a while - you can tell if you access an instance by the shortcode and it recalls all the other details like world and instance type. That's because the instance was still alive in the vrchat API. However, the synced data of objects within that instance are handled by the realtime networking servers, called photon. As far as photon is concerned, the instance and all it's data are gone the moment there are 0 people. You can rejoin the same instance a week later and it will have the same external properties (managed by the API) but all the synced data (managed by photon) will be lost.

As you might imagine, persistence works by making a bridge so that the data managed by photon can be stored more permanently on the API.

heavy spindle
#

The fact that it's alive in the API is what I was observing and was drawing conclusions from. It is good to know that the runtime of the instance itself is ephemeral which was the assumption and I guess a very real observation seeing how games and the likes cannot pick up where you left off though this usually happens across instances and why I'm looking forward to persistence

lone zealot
strange token
#

Oh yeah is that accessible in U#? I’d love to try to make instance owner be in control of rules if possible, and just fall back to master

stone badger
# strange token Oh yeah is that accessible in U#? I’d love to try to make instance owner be in c...

These are the sorts of discussions that I wish we could have in this group (from time-to-time) practical solutions to system-type issues (not always why isn't my variable changing). It is important that be part of a strategy but remember the instance owner may never be in the world. I define an "admin" that I tend to code against that gets set according to some conditions. Initial world setup falls to the master however as they are the first person in the world and they are the default owner.

strange token
#

I havent attempted it yet but I'm thinking a simple "If owner is instance master" check in the OnOwnershipAssigned of the CyanPlayerPooled object, which will enable an udonsynced variable on my UI manager, so when people click the buttons and it makes requests to my gameManager, the UI manager can check to see if the instance owner is in the world before setting the "ownership" flags for the master

#

And a callback that reverts ownership flags for the master when instance owner gets assigned*

strange token
stone badger
jaunty fjord
#

Hi I'm running into a strange issue that I'm struggling to understand.
I basically have a script on a pickup that plays a random sound when the use button is pressed
However when the pickup object is changing owners (i.e. going from Player A -> Player B) the object briefly lags back to a previous position
This wouldn't be a problem but for some reason this causes Player A to hear the random sound 2 times
I'm unsure if this is an issue with my code, but I'll include it in case it is, any help would be appreciated

{
    public Animator teddyAnimator;
    public AudioSource teddyAudio;
    public AudioClip teddySqueak1;
    public AudioClip teddySqueak2;
    public AudioClip tomAndJerryScream;
    [UdonSynced, FieldChangeCallback(nameof(AudioRNG))] int audioRNG = 0;

    public GameObject teddyBear;
    public TextMeshProUGUI teddyBearRngDebug;

    public override void OnPickupUseDown()
    {
        AudioRNG = Random.Range(1, 201);
        RequestSerialization();
    }

    public void PlayTeddyBearAudio()
    {
        if (audioRNG < 100)
        {
            teddyAudio.clip = teddySqueak1;
        }
        else if (audioRNG >= 100 && audioRNG < 200)
        {
            teddyAudio.clip = teddySqueak2;
        }
        else
        {
            teddyAudio.clip = tomAndJerryScream;
        }

        teddyBearRngDebug.text = audioRNG.ToString();

        teddyAudio.Play();
    }

    public int AudioRNG
    {
        set
        {
            audioRNG = value;
            PlayTeddyBearAudio();
        }
        get 
        { 
            return AudioRNG; 
        }
    }
}```
stone badger
# jaunty fjord Hi I'm running into a strange issue that I'm struggling to understand. I basical...

You're presented a very interesting example. One that is likely far more complex than seems to be warranted. One must always claim ownership of the gameobject before setting a property and calling RequestSerialization. I wouldn't have written it quite this way so determining why it plays twice may not be worth the effort. Consider this alternative. You're not expecting a late-joiner to hear the last sound right? But anything based upon sync'd variables will unless code exists to prevent it. So this is good example of where you could call SendCstuomNetworkEvent. No FieldChangeCallBack, no UdonSynced property and no RequestSerialization.

#

With the AudioClip properties set (you could use an array in place of 3 explicitly named properties) you don't need to set the AudioSource clip but could play them via teddyAudio.PlayOneShot(<clip>, volume).

#

You seemingly are trying for a random value in one of 3 ranges but You should be able to simply get a random value between 0 and 2 and using PlayOneShto reference the element of the AudioClip array (if you place them in an array instead).

#

See if that works for you.

vivid trout
#

I have a few issues with some scripts I'm working on

jaunty fjord
# stone badger You're presented a very interesting example. One that is likely far more complex...

Hi Tom thanks for the message. I had originally tried to use the SendCustomNetworkEvent method but I was struggling with getting both players to play the same AudioClip. If the RNG code was only on the OnPickupUseDown method, it would only run for the player holding it, which makes sense. If I put the RNG code into a networked event, then both players would generate their own number and would often play different audio clips from eachother.
Ideally I only want the RNG to be run once, and then have that number synced to each player. But with this approach each player gets their own unique number.
Here is my updated code that has that problem but also has some of the improvements you suggested.

{
    public AudioSource teddyAudio;
    public AudioClip[] teddyClips;
    public TextMeshProUGUI teddyBearRngDebug;

    private int audioRNG;

    public override void OnPickupUseDown()
    {
        SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "PlayTeddyBearAudio");
    }

    public void PlayTeddyBearAudio()
    {
        audioRNG = Random.Range(0, 3);
        teddyAudio.PlayOneShot(teddyClips[audioRNG]);

        teddyBearRngDebug.text = audioRNG.ToString();
    }
}```
#

I have also tried to use the UdonSynced property on my audioRNG int, which at first seems to work, but after a couple of uses the number permanently is one sync behind on the second player's side.

vivid trout
#

i have a few code snippets i need help with

jaunty fjord
#

Would you not be able to post them in this channel?

vivid trout
#

why does it only work in the editor, but not in vr chat?

jaunty fjord
#

Have you set the turntable to the correct layer?

vivid trout
#

yes

#

ive double checked like fifty times

#

like in the editor, i test it, drop the disk on the turntable, and it works. i do a test build, it doesnt. i upload it, and it doesnt work there either

jaunty fjord
#

Are there any warnings or errors that might give us a clue?

vivid trout
#

nope

#

debug registers the collision

#

the script recognises the turntable

#

the disk just wont snap to point or spin

humble girder
vivid trout
#

oh

#

welp

#

thanks

vivid trout
hollow orbit
#

need help with worlds i can no longer update any world and i get a error when trying to make test builds,
it only happen if i add a network sync if i remove the sync it works again,
but im doing synced objects so kinda need them to make my world tick

jaunty fjord
# hollow orbit

Have you tried using the Network ID Utility? You can find it under VRChat SDK > Utilities > Network ID Import and Export Utility

#

I think I was having an issue like this before with the Network ID's, I think I just made a fresh install of my project

hollow orbit
#

Found a solution

#

if you get that error just go to the vrc network,

Then Clear the scene IDs
and do not regenerate new ones leave it empty, pres upload and you should be in the clear

stone badger
jaunty fjord
#

I tried that earlier today and it was working perfectly 😄
It's not as 'programmatic' as I'd like but it works without any flaws

stone badger
#
public void TeddySqueak1() => _audioSource.PlayOneShot(teddyClips[1], 0.7f);
public void TeddySqueak1Network() => SendCustomNetworkEvent(NetworkEventTarget.All, nameof(TeddySqueak1));

public void TeddySqueak2() => _audioSource.PlayOneShot(_teddyClips[2], 0.7f);
public void TeddySqueak2Network() => SendCustomNetworkEvent(NetworkEventTarget.All, nameof(TeddySqueak2));
jaunty fjord
#

Thank you for your help

faint rock
#

If you ever change anything on an object that has network sync in future, you'll need to go back into it and click "Select" on all the objects that changed to reassign them... to themselves (no idea why that bit isn't automatic).

wheat carbon
#

Hey everyone.
Hey. Anyone has any Idea? Since I Updated my Project to the latest SDK and the 22f1 Unity The VRC Network ID Utility stoped working for me. Whenever I try to import my IDs from my PC World to my Quest World it correctly shows the window with "Select All/Ignore All". After clicking one of those, it throws errors for each ID it tries to load in and shows me an Empty IDUtility Window.:

Obect reference not set to an instance of an object VRCNetworkIDUtility.<DetectConflicts>g__DoTypesMatch|29_5 (VRCNetworkIDUtility+NetworkObjectRef scene, VRCNetworkIDUtility+NetworkObjectRef loaded) (at ./Packages/com.vrchat.base/Editor/VRCSDK/Dependencies/VRChat/VRCNetworkIDUtility.cs:541) VRCNetworkIDUtility.DetectConflicts (System.Collections.Generic.Dictionary2[TKey,TValue] loadedRefs, System.Collections.Generic.List1[T] conflictList) (at ./Packages/com.vrchat.base/Editor/VRCSDK/Dependencies/VRChat/VRCNetworkIDUtility.cs:511) VRCNetworkIDUtility.OnGUI () (at ./Packages/com.vrchat.base/Editor/VRCSDK/Dependencies/VRChat/VRCNetworkIDUtility.cs:305) UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at <80a8ce1980c648dca8e68f0d8aa3b930>:0) UnityEditor.DockArea.DrawView (UnityEngine.Rect dockAreaRect) (at <80a8ce1980c648dca8e68f0d8aa3b930>:0) UnityEditor.DockArea.OldOnGUI () (at <80a8ce1980c648dca8e68f0d8aa3b930>:0) etc.

Whats going on there? I allready tried reimporting the SDK. Same error. Can’t keep my PC and Quest Network IDs in Sync anymore.

I can’t even do them Manually anymore since update? Where is the ID Section gone? ^^

timber ferry
#

my "ducksUnlocked" variable isn't being updated for every player, i'm not sure why. this is my method i use to update it, and this method is only ran by a different script, which that one is only run by the owner of the object.

[UdonSynced] private int ducksUnlocked = 2;

public void TallyDucks()
{
    Logger.ColorLog(this.name, "Tallying unlocked ducks...", "lightblue", false, true);

    ducksUnlocked = 2;
    foreach (var obj in foundObjs)
    {
        if (obj.activeSelf) ducksUnlocked += 1;
    }
    duckAmountText.text = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", ducksUnlocked + 1, totalDuckAmount);
    RequestSerialization();

    Logger.ColorLog(this.name, $"Unlocked ducks = {ducksUnlocked}, duckAmountText = {duckAmountText.text}", "white", true, true);
}
rigid temple
timber ferry
#

i don't think so, i have other variables in my project which are synced, but private

rigid temple
#

ah no you're right I'm thinking of methods 🤦‍♂️

timber ferry
#

yeah, plus, i already tried with it being [UdonSynced, HideInInspector] public and it still didn't work

rigid temple
#

have you tried doing " Networking.SetOwner(Networking.LocalPlayer, gameObject);
"
Before requesting serialization?

timber ferry
#

well, i have a different script that runs TallyDucks(), and that script is only ran by the owner of the object

#

so i figured TallyDucks() would only be getting ran by the same owner

rigid temple
#

I think it's on a per-script ownership basis, I might be wrong but it's worth a shot if you're willing to try it

#

It's been a few months since I did any big networking things so I might be totally wrong

timber ferry
#

yeah i'll try setting the owner of the TallyDucks() script as the same owner of the other one

rigid temple
#

I hope that works or that's the third thing I've said to you that's wrong in a row

timber ferry
#

it probably is per-script/per-object

#

well unfortunately it doesn't update for everyone still

rigid temple
timber ferry
#

actually it's probably cause i don't have any OnDeserialization method set-up

#

i don't really know what to do with that though

#

actually

#

nevermind i'll just try and set one up

#

i think this is all i need

public void TallyDucks()
{
    Logger.ColorLog(this.name, "Tallying unlocked ducks...", "lightblue", false, true);

    VRCPlayerApi spawnerOwner = Networking.GetOwner(duckSpawner);
    Networking.SetOwner(spawnerOwner, this.gameObject);

    ducksUnlocked = 2;
    foreach (var obj in foundObjs)
    {
        if (obj.activeSelf) ducksUnlocked += 1;
    }
    duckAmountText.text = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", ducksUnlocked + 1, totalDuckAmount);
    RequestSerialization();

    Logger.ColorLog(this.name, $"Unlocked ducks = {ducksUnlocked}, duckAmountText = {duckAmountText.text}", "white", true, true);
}

public override void OnDeserialization()
{
    duckAmountText.text = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", ducksUnlocked + 1, totalDuckAmount);
}
rigid temple
#

I'm no compiler but it looks good to me

#

I've used it myself and it's really easy to set up

timber ferry
#

would it sync stuff for late-joiners too?

rigid temple
#

I don't think it does, it's just for calling functions with parameters to save having to sync the parameters and then call the function on deserialize

timber ferry
#

yeah i'll probably keep syncing stuff manually then. i always have stuff synced for latejoiners

#

i love having synced stuff in worlds, its just hard to make sometimes

rigid temple
#

understandable yeah

timber ferry
rigid temple
#

If you put "Debug.Log(ducksUnlocked)" does it have the right value?

#

in OnDeserialization*

timber ferry
#

i don’t think it would runOnDeserialization when testing in unity, cause it only runs for remote clients

rigid temple
#

I thought you were testing with 2 clients, otherwise how would you know the script doesn't update the ducksUnlocked?

timber ferry
#

well yeah but i don’t have the console in-game

rigid temple
#

you can turn it on by doing right shift + ` + 3

#

oh you also need to put --enable-debug-gui in your launch settings

timber ferry
#

i never get the log on the second client

#

so, on the object owner's side i get all these logs, but on the other client i don't get the "SetText, Unlocked Ducks = X" at all

#

it just seems like RequestSerialization isn't working, or OnDeserialization isn't working

#

cause it seems that it never gets run

strange crane
#

I've encountered an issue like this before. I am unsure how I resolved it but another thing did you set the Sync Mode to manual?

timber ferry
#

i did not, i forgot you have do that

#

what exactly is the critera for using manual sync mode? is it whenever you use Request or OnDeserialization?

rigid temple
#

Pretty much, also a note from the docs "Manual synchronization is intended for data that changes infrequently and where intermediary values matter; like the positions of pieces on a chess board. Users should not expect high speed updates with manual serialization."

dark bane
#

i wanted to make a script where instead of having 1 thing turn on/off when holding an object and pressing it like a flashlight it will have mutiple objects turn on/off. I combined 2 scripts but it turns on the objects when I have the main object in my hands. How do I fix this?

timber ferry
dark bane
#

cause I have a script where it does that but for 1 object

timber ferry
#

Interact is the wrong event to use then. Interact is when you point at an object, an outline appears, and you click it

#

also, setting isActive seems to do nothing in that graph, because you don't use the isActive bool for anything

#

otherwise, simply plug in the OnPickupUseDown into the For node, and it should work as intended

dark bane
#

ok!

#

let me test it

timber ferry
#

every single log shows up, and all the variables update correctly for the object owner however

#

it's just remote players who don't see the changes, update the text, or recieve the logs

timber ferry
#

is your pickup set to Autohold: Yes

strange crane
timber ferry
#

i’m not actually, i made my own static class cause i like to make logs a specific way

#

all it does too, is take some variables and put them into my specific format in a Debug.Log, so i know it works fine

#

cause i also use it for everything else, and i see my custom logs on the non-owner client from other scripts

strange crane
#

Does the game object with the script get disabled at any point?

dark bane
timber ferry
timber ferry
# dark bane yes!

hmm. show the graph again in its current state so i can check it out

timber ferry
#

you aren’t getting the length of anything, and you aren’t getting the GameObject out of anything. you need to plug your Targets variable into the Get Length and GameObject Get

dark bane
timber ferry
#

well you want to toggle an array of objects right? multiple objects?

dark bane
#

Im using the one with the square at the end instead

#

cause that one seems to plug in

timber ferry
#

yeah, that’s an array. a container for multiple objects, as many as you want

dark bane
#

oh!

timber ferry
#

and make sure it’s a public variable, so you can add objects to it from the inspector

dark bane
#

i put that in get length

#

if Im wrong please correct me!

timber ferry
#

now just test and it should work. as long as you add things to the array from the inspector

dark bane
#

ok let me test it!

#

it works!!!

timber ferry
dark bane
#

it works!

timber ferry
#

alright

strange crane
#

It should be on a gameobject that is not disabled.

timber ferry
#

now people can see how many ducks have been unlocked :)

strange crane
#

I had this issue in the past and that was my issue lol.

timber ferry
#

networking is so annoying sometimes, but networked mechanics are always better

timber ferry
#

how is this not synced? i copied my other script which is synced, but just removed some stuff i don't need for this other project

#

i don't know if i removed too much or what, but it's basically the same, yet the ducks don't spawn for both clients when i test

humble girder
timber ferry
#

it’s only the non-owner that sees nothing

humble girder
timber ferry
#

well the object pool owner should be the same one as the script object’s owner while i test, because it’s the only player in the instance before i click go on the second client

#

and i would assume each object from the pool is owned by the same client aswell, because i believe ownership of objects automatically goes to the ayer who has been in the instance the longest

humble girder
timber ferry
#

it does

humble girder
timber ferry
#

yes, they all do

humble girder
timber ferry
#

yes, the master sees it spawn, and in-position. other players don’t see anything happen at all

strange crane
#

Is the GameObject with the pool disabled?

#

Your code seems to be fine. Although, can you show me your VRCObjectPool setup?

timber ferry
#

i can show it later

strange crane
#

alright.

#

that is very weird.

timber ferry
#

i mean, i’m putting this system into a pre-made world, so could there possibly be some other function or something from a different system that would affect mine?

#

i don’t know how it would if it’s all separate objects in the hierarchy though

strange crane
#

Im not to sure. I can't really give a full view until I see what your code is doing.

timber ferry
strange crane
#

It could be that maybe. I mean im not 100% sure but your code looks fine. The object state should be syncing meaning its something happening outside of the code.

timber ferry
#

guess i'll try disabling my cull trigger

#

nope, still broken. i don't know what's wrong about this

#

if it transfers ownership to the player who it wasn't working for, it then works for them, but it gues that just makes sense

#

but i really don't understand why it won't spawn the ducks for everyone

#

i just noticed something

#

when it tries to spawn a duck, for the client that isn't the owner, it shows for a split second but then disappears

#

so something is disabling it again maybe?

#

but i don't know what would possibly do that, cause i haven't made anything that disables then besides a button that has to be pressed

#

it may have been my respawn triggers, which call Respawn on them if they enter the trigger area, so maybe when they spawned they somehow hit it and go somewhere else, but only for the non-owner??

#

i don't know but i changed how it works and i'll test

#

nope, that wasn't the issue

#

but at least i see what's happening now

#

they all appear in-place for a half-second, and then disable or go invisible again

#

(for the owner, they see all the ducks where they should be all the time)

#

@strange crane does this clip help with diagnosing my issue at all?

strange crane
#

I can't really see what is happening in unity and whats triggering.

timber ferry
#

yeah just a moment, i'm gonna look at a different system for a minute

strange crane
#

Alright! Just DM me in a min if you still need help

tulip sphinx
#

Before i make mistakes, short/int16/uint16 are properly working with networking and will result in halving the amount of data on continuous sync?

vapid pagoda
tulip sphinx
#

oh byte is even better ye thanks

lone zealot
tulip sphinx
#

ye, i know. also udon doesnt allow to set -1 as a default value for short. Also this, every time you copy these two, they mix up nodes😡

bitter path
#

does OnOwnershipTransferred ever get called?

#

transfering ownership of the handler to whoever it will work with, console says ownership transfer occured, but OnOwnershipTransferred has never been called

vapid pagoda
bitter path
#

manual, spawning object out of the pool and assigning it to the player right away