#udon-networking
1 messages · Page 4 of 1
No, you need to move the graph you have on the pickup to a child object
so the manual behaviour, move to a child object
and what will this new continuous udon behaviour do? will the graph be empty?
Yeah, the sync mode has to be the same as the object sync
But we won't be using any synced variables
On that specific graph
All this graph should contain is a reference to the child graph, and the OnPickup and OnDrop events.
The OnPickup and OnDrop events will only be called for udon behaviors that are on the same object as the vrcPickup
So we need to inform the "real" script that the events have happened.
Does that make sense?
so with the main graph, on pickup it has to call the actions of the other graph?
What do you mean with "main graph"
the parent graph with continuous sync
Yes
You need to forward that information to the child graph with all your actual logic inside
so basically I have on pickup on the continuous graph, it goes to the circled area which will just be a "go here" node or something, probably an event?
SendCustomEvent but to the child graph
You plug in a reference to the child graph in the instance
so basically on the main continuous graph, on pickup, sendcustom event "runpickup" with reference to the child graph, so it goes into the child graph to here
Yep
ok i'll try that, thank you
Hope it works!
hey how did you respawn objects locally?
almost done, how do you reference the child graph, what node do I use to plug into instance
None, objectsync cannot be local. If you want a kind of local respawn, turn off the object, move it to where it was originally, turn it back on.
so I guess you have to animate it in some way
Create a variable that you can access in the inspector like you did with the gameObjects earlier but use the type UdonBehavior iirc
I don't need to animate it at all.
thank you so much it works exactly as intended, sorry for all the pings haha but again thanks a bunch
im not sure how to do that
what happens if i move or disable an object locally that has VRC Object Sync? Will everyone see the changes because of it?
uhhh if I remember no, only local player sees this change (that's for disabling/enabling object)
for moving it may depend? not sure though (because I haven't tested if moving synced object via code locally updates object position for everyone)
but if you would grab this object and move somewhere it will be visible for everyone
ok horrible solution: continuous script that deserialize new location when player interact with it?
if the movement isn't constant (like for example with every button press it changes object pos to loc A, loc B etc then if will be good [kind of]), but if it would change location all the time then it could have some delay for other users? idk since i got into networking in vrc i just look at the delay of objects wayyy different and even smallest delay that wouldn't probably be visible outside of test build gets my attention
it really depends if you care about other users seeing new location with a little bit of delay
Hi there! I don't know if this is the right channel to ask this but on the world i currently work on i made an elevator that goes down when a button gets toggled and its synced for everyone, also for late joiners. Everything works fine BUT:
When the elevator moves down the movement of the elevator itself looks really smooth but the players that stand inside jump by themselfs. Feels like the refreshrate of the animation is faster than the players get refreshed in the lobby which makes them jump. (The elevator moves pretty slow)
Does anyone know how to fix this issue?
the vrchat player controller is just not equipped to handle moving surfaces, sorry
Pretty weird since i saw multiple maps where moving objects are carrying people up and down and it seems like the players are moving perfectly synced with the object.
Maybe there is some way to attach players like on a seat when they stand inside of a collider like a parent
up and down is really the only movement you can reliably do, but even that will have the problem you're seeing. Anything beyond that is doing some advanced trickery, such as using stations to manually desync and move players around however they want
I would just move them up and down. Actually when people get moved up it works pretty fine. Its just when the elevator goes down. Maybe i can set the gravity pretty high in that area so people get "forced" onto the surface they stand on
Sorry for the bad english tho 
I'll emphasize that this is not a supported feature and is doing a lot of hacky things to pull this off, but if you really really need this and don't care if it breaks later, then there is this prefab https://github.com/Superbstingray/UdonPlayerPlatformHook
Now a more complicated question 
The elevator that i am currently building should be able to get triggered up and down (basically first floor and basement).
When the elevator takes the people up nothing else should happen. But when the elevator gets toggled to go down there should be a collider that has a teleport script on it so people get teleported on collide. I did set it up and everything works. There is just one problem.
I made the elevator synced for everyone so when it gets toggled up or down everyone can see it synced. But because of that as soon as one person collides with the teleportation collider everyone in the lobby gets teleported. I want that the elevator itself is synced for everyone BUT that only people that stand inside that collider get teleported.
Since i need to sync the animation that toggles the teleportation collider on and off too it might cause the same issue that everyone gets teleported since the collider is attached to the synced udon script.
Is it even possible to sync a toggled object but to only teleport people that trigger a teleport through a collider?
Sorry for the wall of text
On the teleport script, indicate that this is a local player, and not for everyone.
But when someone else toggles the object that contains a collider and its teleport script on, will the toggle be global then. So it toggles it on for everyone but teleports the people locally?
No, whoever touches the collider will teleport.
Or so
I will try that out, thanks. My goal was that someone else can trigger the rotation globally so people that stand inside of the collider getting teleported locally
Even this option will work as you need, but with checks it is more reliable.
Alright so i try to make the button toggle script network synced and the teleport seperate as local like you showed
Thanks for the help regardless
if i use it like the both screenshots shown above it toggles the teleport colliders but the teleport itself wont work
if i use it like the last screenshot it teleports but i have to test if its actually local
All options work there.
Put a cube, put any of the options on it, test it with several clients.
i changed the animation so the collider activates itself with the animation where the elevator goes down
the blue thing that blinks for a split of a sec is the collider with the udon graph shown on the right
wait i try that one too
And your trigger collider must be on the same object as udon.
thats the second version
when i connect the onplayertrigger enter node with the teleportto and the events vrcplayerapi with instance from teleportto it works
like the third screenshot
but when i use the first two it don't teleport the player
it now teleports the player, thank you! i gonna try it out with some of my friends if the animation of the elevator interferes with the teleport or not
but thanks for your help a ton"
anyone knows how to fix this?
This most likely means that you added the game object variable, but did not add the object itself to it.
i followed a video and he dragged the obejct into the graph
But nevertheless, not everything can be dragged there.
Also check if it appeared in the variables in the inspector of the udon script.
im sorry im very new to all this udon stuff, so its hard to understand what u mean 😅
When you add a variable and make it public, it always appears in the inspector.
That's where you need to add all sorts of objects, components. And so on.
Start by creating all the variables yourself, and when you get used to it a little and understand what and how it works, you will already be pulling objects immediately onto the graph.
okay i'll try later, thanks!
What's the recommended architecture for a client sending data to the room where it's identifiable who sent it?
EX: Player needs to tell everyone they have died, so that the Master can update a game state. I believe you can't query the player who sent a NetworkEvent so it's a bit puzzling.
Is it creating several proxy GameObjects and forcing ownership for clients in the game, then using those to send messages and receive them for the Master? This feels strange so thought I'd see if I'm overlooking something in the docs.
you can use https://github.com/CyanLaser/CyanPlayerObjectPool to easy manage per-player objects, then send custom events through them, you can detect an Owner of the object from which that event sended. or use synced variables, like death counter, when it's changed - everyone reveive that change and do something on callback, like locally updating their ui-panels or etc
Hello, I'm currently trying to figure out how udon(sharp) networking works and how I should structure my code. Unfortunately I can't seem to find much documentation on it. I'm not used to this amount of limitation in C# and trying to make the code clean is challenging. There are so many ways to the handle networking and I'm trying to find the best way to keep it optimized and maintainable. Does anyone have an open source project I can take a look at?
@sweet wolf That is just a list of methods, I'd recommend this https://creators.vrchat.com/worlds/udon/networking/
Multiplayer experiences are the heart of VRChat, so creating a world that reacts to players and synchronizes the data between them is key.
If you're looking for a project to poke, cyan player object pool is well-commented https://github.com/CyanLaser/CyanPlayerObjectPool/blob/main/com.cyan.playerobjectpool/UdonSharp/CyanPlayerObjectPool.cs
Thank you! This will help a lot :)
Does pause/play status not sync to late joiners or is it just a problem with every video player everyone uses because man
It's up to the udonbehaviour to sync it so it certainly might be missed, but as far as I've seen they manage to sync it fine
Appreciate the link, will check it out!
I'm having a lot of trouble setting up teleports via buttons even though I have a program for it already via Cyan Triggers and following a tutorial from Feb. 2022. Did anything change or are there more recent tutorial videos I can follow?
I don't think anything's changed with teleports since then. What's the problem you're having?
I think the Cyan Trigger Program Source is the issue for some reason. I'm just making the program source myself to see if that's the main issue. Cyan Trigger part doesn't show the interaction tab at all under the Udon Behavior
do you have any errors in the console?
A couple, but I believe not related! HOWEVER, it does turn out I had to make the teleport system myself even though it was literally set up the same way as Cyan's Program Source. It's my first time tackling world making stuff, so I wanted to make things as QoL as possible for myself, but apparently won't be the case for teleports!
oh, you figured it out?
Thankfully, yes. I just can't rely on the Cyan Triggers unfortunately is the lesson!
hm, that doesn't sound right
I'm not too familiar with cyan triggers but I always hear good things and that it's reliable. I would guess the issue you ran into can be fixed easily, but I'm not quite sure what you mean
oh yeah you're just not supposed to use it that way
isn't there like a cyan trigger component or something?
are you sure that's even cyan trigger? It looks like an udon graph program
in case you're not aware, graph, cyantrigger, and udonsharp are all just different compilers that can create the same end result - udon code. They're just different interfaces to make the same thing. But during creation, they're very different, and you can't for example edit a graph program in the cyan trigger editor. You need to make a cyan trigger to begin with
Oh. You are right. I don't know how to use Cyan at all then at the moment.
Yes it does! The UI alone is intimidating, but don't think I will look into it anything soon since I'm only setting up teleports and already made a source on my end. Maybe in the near future if I want to make more complex systems
I just pushed a Beta version of my networking prefab to github! https://github.com/Miner28/NetworkedEventCaller/tree/ByteBuffer
If anyone's working with some Evented networking in VRChat and using U# I'd recommend checking it out! 🙂 No proper release as of right now as I am still getting feedback and fixing any bugs before full release. but it works pretty well without issues already.
this is not in #udon-showoff because "Networking" and also not release yet
I have a skybox toggle that will not scync for late joiners no matter what i do. Is it possible that im doing something wrong or is something like this unable to be scynced like that
this is the logic that I have
https://creators.vrchat.com/worlds/udon/networking/#using-variables For simple manual synchronization, the SetOwner - SetVariable - RequestSerialization - OnVariableChanged construct is enough
Multiplayer experiences are the heart of VRChat, so creating a world that reacts to players and synchronizes the data between them is key.
Hey,
im trying to create a world and I am working on the sync for late joiners. my world relies on a 2 dimensional array. however I am not sure how to sync this or the best way to approach it, as I am getting a message saying it cannot be synced
the line in question:
[UdonSynced] public int[][] SudokuGrid = new int[9][];
the error im getting is attached as a picture
looking at the VRC documentation, it shows that I should be able to sync a array. https://creators.vrchat.com/worlds/udon/networking/#requestserialization
could I have some help with what is going wrong please?
Multiplayer experiences are the heart of VRChat, so creating a world that reacts to players and synchronizes the data between them is key.
It can sync an "array of int", but not "array of array of int"
If you need a nested array, you could use a DataList containing DataLists instead. It's a little wasteful because you'll have to serialize it to/from JSON and then sync the string, but it will give you the functionality you need
Ty for the help. It gives me a good starting point to figure it out
Have a graph that turns on a gameobject and another off at the same time. It is scyned for late joiners but I have an issue. For the instance owner the toggle works normally, but for anyone who joined after them anytime the button is pressed it initiates the event twice.
You're doing both sendcustomnetworkevent and requestserialization, that's unnecessary. Both of those two things will sync, you only need one. I would recommend keeping the synced variables and requestserialization
the way it's supposed to work is that the person who wants to change something does setowner > set variable > requestserialization, and then everybody else received OnDeserialization with the updated variable
you're also just toggling the objects based on their current state, which means people could get out of sync. You should have this backed by a synced bool and the interact would toggle it, then all the objects are just driven by whatever that is at that time
╥_╥ thank you
Hi there! I tried to make a system that once someone presses a button to get teleported locally it should send a networked event to everyone that 1 object gets activated and another gets deactivated.
Is it actually possible to make something like that? That one part of the events are local while the other part is networked?
when i toggle the button the way its shown above vrchat crashes xD
don't merge two flow lines into one node like that. After TeleportTo, just do SendCustomNetworkEvent to TeleportR2
also you're causing an infinite loop because TeleportR2 immediately calls itself
tried it like that but i try it the way you meant
@frozen igloo you meant like that?
you are a LEGEND! I am so thankful for your help! Someone give him a raise please
ok, that will technically work but I do want to point out - do you want this to work with late joiners?
network events are not buffered and resent or anything
nope, it should only work for the master, since the person that toggles the button (teleport) sends the signal to those 2 objects that in theory should be changing for everyone, but in order to see those two objects you need to enter a password. And with another button the state can be reset to its original state.
So even if a person late joins they can reset that if this gets toggled, the 2 objects should be in/active after the event has been called
sorry for any bad grammar 
Hey everyone, got this weird UdonSharp compile error for the following code snippet:
public override void Interact()
{
if(Networking.LocalPlayer.isMaster)
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
IsDriving = false;
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "StopDrivingAnimation", 3f);
}
RequestSerialization();
}
U# Compile Error:
Assets/main_UdonProgramSources/CubeTestScript.cs(21,111): Method is not exposed to Udon: 'SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, "StartDrivingAnimation", 3f)'
My class:
public class CubeTestScript : UdonSharpBehaviour
I saw other people using it the same way like I did in my Code snippet. I cant find any proper U# documenation for this function besides for Udon Graph where they also just used it without any specific setup:
Any ideas? 🤷♂️
SendCustomNetworkEvent doesn't take a float parameter at the end there, it's just the target and the string
Then I am confused which function it takes?
I'm not sure how that's possible, did you modify UdonSharpBehaviour?
Not manually. Is it possible that an imported package could've caused this?
uhhh maybe?
that's really weird
sendcustomnetworkevent should only be target and eventname
it looks like somebody tried to modify it thinking that they could add an optional parameter. That is not supported
These are the "only" warnings I get.
those are just usharpvideo
this is, what is linked. maybe i just change it back to the original if its changed?
oh, true. i'll try that now 👍
I wonder, when using the VRChat Creator Companion, just pressing on the "-" and then on the "+" again is enough? Or do I need to start and close the project in between deleting and installing?
yeah
What would be the most responsive for activating synced traps, custom network events or sync vars?
manual sync is faster than network events
what if you do sendcustomevent using manual sync? or do you need to use requestserialization
sendcustomevent is local so that wouldn't do anything. If you are referring to SendCustomNetworkEvent, it is not recommended to combine that with manual sync because they may have two different latencies and the network event could arrive before the variables
most of the time, on average, manual sync is faster than network events. That's why it's recommended for low-latency situations. But the difference between the two is not guaranteed, and in high traffic situations, network event tends to arrive first. That's why it's not recommended to do network event with variables by requesting serialization at the same time
So, I'm currently trying to think my way through a player manager and setup system for a game world, in U#.
Every player is going to need a scripted object that operates certain mechanics in the game, and every player also needs to run logic locally on OTHER players' scripted objects, too. But occasionally, players will need to fire off networked information, so each of these objects needs an owner, even if a lot of the game's logic is locally calculated.
To this end, I'm trying to make a player manager script that is responsible for 1) keeping track of all the players in the game, 2) knowing when players join and leave, 3) dolling out these scripted objects to players consistently in a networked fashion, and 4) being able to change owners fluidly if the instance master leaves, so that the game state isn't obliterated in such an unlucky event.
Are there any examples of best practices for this kind of system? Surely this has been done before.
I'm particularly concerned about 1) making sure that, wherever this object is, it consistently registers the arrival and departure of players to keep the current list of players accurate, 2) making sure it can change owners if the master leaves, and 3) synchronizing what player owns which scripted object (where the majority of the mechanics of the game take place)
Cyan player object pool is one such system that automatically assigns unique objects to each player https://github.com/CyanLaser/CyanPlayerObjectPool
Hmm. I'll dig into it and see what I can learn, thanks.
You should use it as is tbh.
I might, reading into it. I'm always just leery of grabbing things and plopping them in my project without knowing what all they do.
It has a lot of example scripts and templates
This seems pretty cut and dry though
it really is
It does one thing and appears to do it quite well
Cyan is incredibly good at what they do
Oh, I'm sure. The risk is I'm stupid 🙂
... or I guess, being less facetious. If a system does too much and is too opaque and dense and optimized to understand, it can be harmful to use because it just elevates the complexity of the project.
I don't think that's the case here, fortunately.
I promise, it is way harder to make one from scratch.
Yes, for sure x'D
@frozen igloo i assume if i use Manual but not using RequestSerialization, and using SendCustomNetworkEvent is fine? since i am only doing it to prevent it from contiounesly updating. unless i misunderstand their way of doing cont, or manual etc
if you don't want it continuously updating, then yeah setting it to manual is fine. Using sendcustomnetworkevent is completely detached from that though
ikr i know. i just wanted to make sure that since what i am doing does not really require any sync whats so ever unless i do it manually.
if you don't have any synced variables, continuous sync won't do anything anyway
i do have a few of them
so then when you want to sync those, do requestserialization
anyone knows how long it takes to transfer ownership of a object?
It's instantly for a person who set the ownership. But for full transfer verification and rejection it'd take both person latency times 2.
hmm. so taking control over say 20 objects is gonna take on average what 100 ms? per object?
It should send out in batch if all requested in the same frame.
hmm. either i am doing something wrong or something is not working as it should. calling both OnOwnershipRequest & OnOwnershipTransferred but i am never seeing it happen. unless it does not work in ehm Test mode
It doesn't work in client sim because it doesn't emulate networking.
no i mean as in test world. using the build test
What did you mean by calling the both function? Did you actually call the function yourself?
as in overriding them. to add in methods to call when it happens etc
That's implementing the methods. Both should work that way.
i know. there is not a thing you need to call right? like when you RequestSerialization.
i just call SetOwner() which should trigger it right?
It should
hmm. odd. i have a feeling its getting stuck somewhere then uh. i need to enable udon loggin to see why
hmm okay now it does work for some reason
I can't remember but the networked object owner for manual sync DOES NOT run OnDeserialization() right?
It doesn't run for the requester.
OK great! Thank you
Is there still a performance difference between a script without synced variables set to Continuous and one set to None?
(has there ever been one? or am I just insane? 😆)
Hmm. This is actually turning out to be less straight-forward to implement than I thought. There's enormous gaps in information and differences between the readme setup instructions and the actual example scenes...
The documentation is lacking a few specifics but by just using the provided example and template scripts, it seems to be working just fine. Just sliiiiightly irked that I have to take a leap of faith rather than fully understanding all the nuts and bolts of the system.
Hi guys
I’m creating some new and exciting anime’s. Moreover, on demand as well…
Let me know if anyone’s interested
What "anime's"?
Is it something has to do with udon networking? This channel is for consulting topic related to udon networking.
This works but its just not syncing.
Master can execute it all and it syncs to other players.
Other players cant return the objects to the objectpools
Audio just dosnt sync at all.
like to explain it. you enter the your local head collider in a object pool object. and it starts. then it gets the audiosource from the object and plays it. then it should return the object to the object pool after the timer has run out (timer is bottom part)
soo... what am i missing?
Are you placing a trigger directly on the player?
You can't change the owner like that, because it's already part of the avatar.
Therefore, only the first one works - the master.
Do everything locally, and synchronization on another object is already inside the world.
So I'm assuming these objects are pickups that resemble foods you can consume?
And that the script in question is on the same object as the local head collider?
I think most of your issues stem from having one script manage all the different foods.
You should instead make foods themselves do the logic.
So, what needs to happen is:
- Food enters a trigger collider
- Is the trigger the correct one?
- Play the food's sound
- Return the food to it's pool after the sound has played
To figure out if the trigger we entered (from the food's perspective) is the correct one, we can check if the name of the other's game object matches the one we are using for the head.
Alternatively, we could do GetComponent or similar to check if the other has a specific script component on it which we use as a label. This is probably safer as it prevents an edge case where a different trigger collider has the same name, but it's probably way overkill for this.
To play the sound is super simple as there is only one to worry about. No switching between types is required because the food only cares about itself and what sound it has assigned to it.
The timer isn't required, we can just use SendCustomEventDelaySeconds with the delay being the Audio Clip's length.
Returning the food is also much simpler now as we again don't need to switch between any types. We just return ourselves to the pool we are assigned.
The reason the audio doesn't sync to other players is because OnTriggerEnter is only called for the local player that uses the food.
I'd just use SendCustomNetworkEvent to call the event to play the sound for everyone.
That makes way more since than what I did actually. Probably more optimized too since less intense code needed to be run haha
Wonderful response. Ty
No problem! Have a wonderful day ^-^
Hello,
Does "Get LocalPlayer" always affect yourself? If so, how can I get the player who is activating the button, for example?
I had an issue where players would hit a teleport and it would teleport ME to the location everytime
I'll screenshot the code when I can but the world is halfway done baking lights at the moment. Just curious if this is a common error, as I'm a beginner to Udon
LocalPlayer can be applied to both an event and an action.
Unless explicitly stated for which player, or type of players, it applies to all.
So here's the code, I kind of mashed together two tutorials which I think is causing the issue.
The concept is that a player touches an object to activate the code. Once the player touches the object, I want another game object to appear for everyone and for the player who touched the object to be teleported to that object.
In practice I've had two major issues:
- This code above always teleports myself to the object, no matter who touches the original object
- With a similar code, players would enter the world and immediately teleport and constantly fall in one of the teleport locations. This would be fixed when they would rejoin the world.
In the original code, the SendCustomEvent Delayed was just SendCustomEvent. I just changed it and haven't tested it
It should work.
Well, maybe tweak it a bit to suit your needs.
I really appreciate you taking the time to rework it for me, thank you!
Any chance you can give a short explanation of what may have gone wrong or why you made the changes? Still learning Udon
The trigger fires, the player who entered there teleports, the variable changes at the same time.
Through Variable change, the value of the variable is checked, and if it changes, it is applied to the object.
Got it, it looks like mine was just attempting to do too much
But so every time a player enters the trigger, the object will then turn off, the next time the player enters, it will turn on.
I don't know how it was planned.
Well the concept is that it's a prank. A player enters a room and the floor doesn't have a collider so they fall through it. The teleporter plane is below the floor.
The concept is that if someone hits the plane, it makes a "jail box" appear over the main room and I want the person teleported inside. If the "jail box" exists, I don't want it to dissapear though. Inside the jailbox is a button that turns it off so the players fall out
Yes, I kinda understand.
But I'm talking about this, it will be on\off every time the trigger is triggered. If you need a more stable state, then you will need to redo it a little.
I see, I'm not certain what the best practice is then for thiss
Then it's possible.
And call the event either from the button by pressing it, or add a timer.
See what's more convenient.
Just to be clear, what is the Custom Event you have there?
Any write, does not matter.
But as you understand, it should be the same in both the custom event and the send custom event.
Apologies I'm a bit confused. What do you mean by any write?
And Im not sure I understand as I don't see sendCustomEvent
sendCustomEvent can be launched from a button on click, from another script or object, and even from animation on other objects too.
Where it will be only depends on your imagination.
For example UI button.
Option with a timer, after 2 minutes the object will turn itself off for everyone.
Thank you very much this is all extremely helpful.
My plan is for this to trigger when a player collides with a mesh
Add then probably just a button to disable the object.
Good luck to you.
Thank you!
If I'm doing this similar process but with a button, would I put Event Interact in the Custom Event slot and where TriggerEnter is too?
Actually same question for the mesh. Im just uncertain what to do with the custom event for my use
Yes. I've posted a screenshot of how it can be applied.
The mesh has nothing to do with the custom event. The trigger collider catches the player's touch and teleports them.
Ok, and that trigger collider is also setting the gameobject to active? Im going through it now. Thank you!
Basically Im just not sure what it's for if the mesh does all of the work, and theres another button in that gameObject to turn it off
Yes, trigger teleports the player and includes the object for everyone globally.
But in order to turn it off, you need either a timer or a button. Via custom event.
Understood, that makes sense. Thank you.
Also, did you get the variable Change node by alt dragging in?
Im trying to do so but it won't let me
Grab the variable, hold alt, and release it on the graph where you want to place it.
I've tested this out with the button, but unfortunately the gameObject isnt activating. The Teleport works though
Hopefully didnt mess it up but tried to copy yours directly
Set the sync variable on the bool, and set the manual sync mode on the object itself in the inspector.
And you changed the event to interactive, why?
I'm already completely confused.
Apologies, where can I find the manual sync mode on the gameobject?
Sorry for the confusion. This one is for a very similar system, except rather than colliding with a mesh it activates when a button is pressed. The code is on the button. The event interact is what I usually use when activating a button.
For what it's worth im extremely new
on the udon script itself. on the gameobject
ty Idk how I missed that. Ill test that out as well as fixing the "send value change" checkbox
Thank you. I did all of the above and still no luck.
It works now! Thank you so much for your help this was driving me nuts
Bizarre, all I did was put the code on the other button to reverse the process, and now it suddenly doesnt work again
Unity is something
Check that you have added all the objects, both the teleport and the object itself.
Do you have both buttons and start and off on the UI both?
If yes, then remove the interactive, do the same as a custom event.
Well, the same thing again, this is either an old image, or they forgot to activate it again.
send changes. must be active on both.
I misunderstood, I thought you wanted me to uncheck the bottom one as it suddenly worked then
but it works again, thank you for your help and patience
Sorry last thing, the platform I spawn and teleport to does not despawn when I put the same code on it (under a new name). Changed all the settings to be the same. Am I missing something to switch?
Will it turn off by pressing the button or by timer?
You can always add a log node and monitor hits via the console in the unity.
No it won't in either case
I'm not sure, but maybe it's because of the variable names.
Change the bool variable in the second script to a different name.
Or don't make it public anywhere.
ok ill try that
Try turning off the public on it, on both scripts.
And test.
got it
how would i stop a SendCustomEventDelayedSeconds from another event before the delay time is over?
You could do a branch at the beginning of the event you've called and check if a condition is still valid when it runs.
does synced array syncs every entry separately or all at once
all at once
well i meant
if i have array of bools one for each player
each separately selects if ready for something
then host starts when all bools are true
do i need make like 80 separate variables each for each player or can i just array
Sounds like what you want is a player object pool
The main problem with doing that would be that two players cannot send synced data for the same object at the exact same time. They could conflict and overwrite each other. If they were even a second apart it would work fine though.
Whether you use 80 separate variables or a single array is irrelevant, the whole object syncs at once together. An array would be more usable for you, that's all
A player object pool solves that problem by giving a unique object to each player individually so they can sync their things without worrying about someone else stomping on it
i can try object pool but i wonder if when editing array can you send just one value of it to others
without touching the rest
You can't
so arrays are synced whole at once
You have to sync the whole object.
The problem isn't what variables you send though. The problem is taking ownership and overwriting someone else
^
It's not something specific about arrays, it's the whole object
yeah but if each person would edit their unique variable there wouldnt be issue with it anyway
but when each player edits unique entry in array
if whole array is synced at once
That's just not how it works
In order to edit synced variables, you need to take ownership.
Only one person can have ownership of an object at once
yes but it wont matter when you edit something noone else ever touches
you can take ownership in middle of somebody elses syncing variables and it will still work
No you can't
well i never had issue with it then
Like I said, it only causes problems if they happen at the exact same time. If they're even a second apart it's fine
Which can be a problem for a backend system that is doing stuff and doesn't know to retry.
but if it's a player pressing a button and they do something then immediately see it reverted, their first instinct is to try it again
Trying again is also a good enough strategy if these variables aren't being changed too often
well no im making it auto sync because its just to register if player saw the event and not lagged out
I followed this tutorial to try and get an admin list from pastebin, but it doesn't seem to be drawing the data: https://www.youtube.com/watch?v=IxWnYm8f7AA
The code works as the object is hidden for me, but that means it's not seeing that I'm on the admin list. Has anything changed in the last few months that would cause this?
to properly give turns to someone else
Used the graph
Post what you have
I have a feeling I know what you did wrong
Is your link a RAW link? https://pastebin.com/raw/
yes
hm
sure one second
Oh that tutorial is doing manual string split. You could use JSON parsing instead, and then you don't even need to for loop through it, just check list.contains
Keep in mind Im using the graph part of it, the second half of the tut
Yes
Oh, you don't have the string[] get connected to the string equals
okay sooo...
audio sync, perfect.
master can retun the food/GO to the objectpool but others cant
food/GO drops on colliders that dosnt have the "FaceEatCollider" name too (like you randomly walk through any other collider and it drops the object instantly)
works, ty
Only the owner of the object pool can spawn/return props
thats one issue solved then. ty
now with it dropping the object on any random collider?
Because you're setting owner ontriggerenter
Everyone gets ontriggerenter so everyone is taking ownership
Ah, yeah, probably only want to do that if the local player is currently holding the pickup and other's name was the correct one
It's already set ownership before that
oh so it drops on ownership change?
Yeah if someone steals it from you
Sorry, but if I wanted this code to have the opposite effect where an object wont spawn only for admins, what parameters do I change? ive tried a few things with no luck
You would set the active state of your object to the unary negation of the whitelisted bool.
So just add a unary negation node to the final part?
Yup
I put it in after the for loop, but it doesn't seem to be working
in the same code just to try and save space
so how id work with player object pool
is it just assigner of scripted object to players?
nope, its just not doing the reverse
as in it works for the normal objects its supposed to show, but not getting rid of objects it should
however its set as a string with only one object, could that be the issue?
array*
the array only has one element?
Yes
do you have more than one name in the list?
it should be fine
thats what I assumed
So you're saying nonAdminObjects are not being set active, even when you are not whitelisted?
while the normal AdminObjects are being set disabled?
So when I'm whitelisted, the normal objects will appear for me as intended
However, when Im whitelisted I also want the nonAdminObjects to dissapear for me, but not for non whitelisted users
The latter is not occuring
that's strange
yep, ill look into it later it's not a huge deal
are there any tutorials on how to do networked data for every player with udonsharp? like for example if i wanted to have a list of all the players, and each player has a few variables like health, strength, etc
wait i just saw Cyan Player Object Pool, does that do what I'm looking for?
This could be done with a player object pool.
A really good system to work with for this is Cyan's:
https://github.com/CyanLaser/CyanPlayerObjectPool
I have no idea if there are any tutorials on this :/
You'll likely have to read what documentation is available
and reverse engineer other people's work to figure out the rest.
oh yeah
you beat me to it
ill check it out : )
Good luck!
how come this doesnt work? it's fine if there are players already in the server, but deserialization doesn't seem to work properly so late joiners can break it again
oh nevermind, guess the tutorial was wrong, i do need to call RequestSerialization when it's set to manual
looks like you figured it out, but also you should not mix synced variables with network events. You've got a weird combo going on here. You should have everything driven by the synced variable
isn't continuous for non-important stuff though, so it might not work sometimes? the tutorial said that for the variable to sync for late joiners you have to annotate it as UdonSynced
continuous may skip some in-between messages but it will always be eventually consistent
so if it doesnt get that the object is broken right when the user joins, it'll get it a few seconds later?
yes
and yes, in order to sync with late joiners you need to mark it as synced. But if you rely on a network event, it won't sync because network events are not buffered or replayed for late joiners
doesnt ondeserialization work though?
late joiners will receive ondeserialization when they receive the latest synced data on join
yeah i used that instead of the network event because i don't want the sound to play again for them, since it was already broken before they joined
it's good practice to use synced variables and ondeserialization entirely because you don't have to account for late joiners in a special way - you just receive ondeserialization and you apply the synced variables and that's it
if that's the case then I would recommend having a Time.TimeSinceLevelLoad check in ondeserialization, if it's less than 10 then don't play the sounds
When syncing a state machine, is it a good idea to send the whole history of states? I just realized I had some issues which come from switching states too fast. I don't know if that's smart though, curious if anyone ever had to do something like that.
that depends a lot on what your state machine is doing and if states have side effects that you care about and/or are not controlled by other states
like if it goes A-B-C and at state B it fires some particles but then immediately moves on to state C, then yes it would be important to sync in-between states. I wouldn't recommend syncing the whole history, but maybe a rolling buffer of the last 5 states and the times you transitioned
It's a game manager that does a decent amount at this point. And I ended up needing an instant switch that was skipping state B the way you are describing. That caused something not to reset the way it should've. It just feels difficult to know beforehand when that happens, so for me this is about how to make my life less of a pain in the future.
And yeah, I was thinking about something similar. Maybe I could collect all states and then use pre serialization (whatever the name is) to only send the new states.
It sounds like the underlying issue is that you have too much relying on something else happening in the correct order.
I would try to separate out the behavior from the things that didn't reset right and make sure they work independently from everything else.
oh I just remembered, a better way to do this may be to compare the deserializationresult sendtime vs receivetime. That's a much better indicator of whether or not a message is stale, and you could trigger sounds and particles on a fresh message even if it was sent within 10 seconds of joining the instance
fun fact - sendtime is normalized to your own local time since startup, so if a serialization was sent before you even launched the client, you'll get sendtime negative
Well, it's a game manager with phases that have to go in a certain order, so yes.
I'm not sure if I can really separate the resetting. I think what I simply need to do, is reset right before the phase that requires it to be reset. However, because people have delay with updating their values, it might need more time than just right before the phase.
It's just difficult to know when to do what, at a certain complexity. Networking makes everything a lot less clear too.
Might also want to just separate some of the logic into a separate state machine or something, since the issue came from me hijacking the current logic to add a different mode. But then I have to handle switching between two of them, which is a bit difficult to do without breaking up a lot of things.
Wish there were more examples for me to learn from, but I can't even find much for regular Unity that shows the best practices.
You should handle resetting everything to it's appropriate values etc. In the state transition that happens locally. Instead of having to network all of it independently and hope it arrives in the correct order.
Only network the state if possible, anything else that needs to be reset should be handled locally if it's detected you are switching to that state.
My advice is limited in that I have no idea what type of game this is, or what your code looks like.
I know what you mean. In this case, it's about a player choosing something like a card, and syncing the choice (using id) on their own object. This happens in one phase, in another, the czar decides to choose one of those ids. So I either have to reset it at the beginning of players phase or after the czar's phase. I don't think I can really isolate it to one state/phase in this example.
To sync a variable on all connected clients, are the only steps required:
- have
[UdonBehaviourSyncMode(BehaviourSyncMode.Manual/Continuous)] - mark variable with
[UdonSynced] - when changing it, make sure the owner of the object is doing it
- call
RequestSerialisation()after change to sync it from owner to all other clients
is this the case or is there a setting somewhere to change or something because a variable seems to just not be syncing
The project has an example of synchronization on udon.
GlobalToggleObject.cs
Was writing udon netcode and testing it this whole time with multiple clients+quick launcher without building the unity project itself, now everything works as expected
You also need to take ownership and then make sure you implement OnDeserialization, as that's the event that fires when a remote user receives synced variables
basicly how to get info like numbers form one to a other udon script
you can share variables between scripts as much as you want using SetProgramVariable, or if you're in udonsharp just set it directly
well thx for the pointing the way because now i can start seeing how to work things
thats what i needed
but now the question how to actived when it bin called?
like a event
you could either SendCustomEvent or you could react automatically with OnVariableChanged, which you can get by holding alt and dragging the variable into the graph
okay
just like this right because networking i m kinda bad in but i got hole script working but now checking if there no players left
oh, if it's an array it won't trigger change unless you completely swap it out for another array, which is not recommended
change will be triggered when the value itself changes. So anything that stores the value directly will work, yes. Arrays don't work as expected because usually you're changing stuff inside the array, rather than the array itself
i m checking for players in side the bool[] so i can go frow 100 and see witch active so that how i kinda working the script it a player random mizer and it works now only the part that tell how long the time is and now checking for players removed or leaving
it gonna be a tag system
somethings break again dont know where it went wrong
code broke
i m leaving it for now
next day there is a nother try
You know what scrap that I m gonna do collision checkin what the randomizer is
switch
basicly idk how to get the switch to work over networking and still work for people who jsut joined at later time
Any idea on why this function is marked as not existing in U#?
you might be looking for the non-network version
what to add to script to update state of animation for late joiners?
basically with a press of a button, it will play an animation of platforms going down, but late joiners see the platforms still up in the default position
cant you use a float for the animation position, then use some math and time.delta time to get the new float at each update but still being able to send the updated value to the late joiners?
Clarification needed re: VRObjectSync. I've added the component to a "wand" GO with a VRC Pickup on it. That takes care of syncing position, etc. I added a manual syncing script as well but that gave me a warning. Is the solution to add a do-nothing GO to my wand and to add my script to it instead?
yeah
Most excellent, gracias 👍
There are some pretty big problems with that approach.
A better way to do it is to utilize receiveTime and sendTime provided by DeserializationResult in OnDeserialization to determine how long it's been since the animation was started.
On Start, cache the length of the animation clip.
OnDeserialization clamp the time since the animation was started the length of the animation clip such that it can never be greater. We'll save this in a variable called "TimeSinceAnimationStart"
To figure out the float to give the animator that represents how far into the animation we want it to start, all we need to do is divide "TimeSinceAnimationStart" by the length of the animation clip.
dos anyone know where I could get or how to make a Network object toggle.
When using SendCustomNetworkEvent - how do you send data along with it? I'm using U#
No data...
SendCustomNetworkEvent
Inputs: instance - UdonBehaviour, target - NetworkEventTarget, eventName - String Runs the event 'eventName' on the target UdonBehaviour - either on the Owner of the target if 'Owner' is selected as the target, or on Everyone in the instance if 'all' is selected.
You can't, you would have to create your own custom solution which is pretty complicated.
Synced toggles are back! Now we've got them set up using a Synced Bool, which is a way more efficient way then the Send Custom Network Event we had previously, as well as making full use of Ownership transfer and Manual sync!
All assets are available on my Patreon if you'd like to have access to anything I made during or before the video.
Full ...
alr soooo
Networking in Udon is a bit different
how should i teleport them?
The easiest way is to use SendCustomNetworkEvent();
how exactly do i use this?
Like this:
You declare if you want to send it to all players (including the local player) or just the owner. Then, you pass the name of the method you wish to call.
oh i cant just take all the players from the array?
no
Every player needs a reference to themselves (the local player) and then call the teleport method locally.
For example
uh, i dont understand how am i suppose to only teleport the players i want and not all of them
oh wait
i think i know how i can do it
You can store the player IDs of the players that are supposed to be teleported.
thats what i thought
Then sync that int[]
Now, instead of using a network event. You should be using OnDeserialization() and manual sync
?
Do not, mix, synced variables, and network events.
They arrive at wildly different times
im using [UdonSync]
That is for synced variables, yes.
You should declare [UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] above your class.
alr i did it
The int[] needs to be initialized in Start() or else it won't sync.
i already got that
from the previous thing
After updating your synced variables you can mark the GameObject for serialization by calling RequestSerialization();
umm wdym?
This means the next time VRC comes around to sync stuff it will sync your object.
oh so after this it updates for everyone
right?
After some time, yes
So I change the value of my synced array and stuff, and then I call RequestSerialization();
oh wait nvm
how do i exactly get every player and teleport them when i have all their id's in the array now?
nvm i think i got it
Something like this
also isnt this better?
It's basically the same lol. Except you should cache the player ID before the loop instead of getting it every single time.
alr
VRC will call OnDeserialization on your script after it has updated all your networked variables.
You should put anything that relies on the updated variables inside there.
Do not mix network events and variable sync
so should i just change my update to this?
oh wait
i have my get player count now in a different spot
i have it when a player joins or leaves
I don't really know what code you ran
public void TeleportKiller()
{
if(Networking.LocalPlayer.playerId == killerId)
{
Networking.LocalPlayer.TeleportTo(killerPlatform.position, killerPlatform.rotation);
}
}
public void TeleportKillerSpawn()
{
if(Networking.LocalPlayer.playerId == killerId)
{
Networking.LocalPlayer.TeleportTo(spawn.position, spawn.rotation);
}
}
public void TelportInGamePlayers()
{
int locId = Networking.LocalPlayer.playerId;
foreach(int id in currentlyInGameIds)
{
if(locId == id)
{
Networking.LocalPlayer.TeleportTo(playerPlatform.position, playerPlatform.rotation);
break;
}
}
}
void StartGame()
{
randomPlayer = Random.Range(0, playerCount - 1);
killer = players[randomPlayer];
killerId = killer.playerId;
currentlyInGame = new VRCPlayerApi[playerCount - 1];
int currentIndex = 0;
currentlyInGamePlayerCount = playerCount - 1;
foreach (VRCPlayerApi player in players)
{
if (player != killer)
{
currentlyInGame[currentIndex++] = player;
}
}
foreach (VRCPlayerApi player in currentlyInGame)
{
i++;
currentlyInGameIds[i] = player.playerId;
}
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(TelportInGamePlayers));
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(TeleportKiller));
RequestSerialization();
}
void Update()
{
if (playerCount >= 3 && killer == null)
{
StartGame();
}
if (currentlyInGamePlayerCount <= 0 && killer != null)
{
StopGame();
}
}
Random.Range is maximally exclusive with integers. You don't need to subtract 1 from the playerCount.
my bad
do not do this
You should do the teleportation in OnDeserialization
That is right after the variables have been synced
alr well i got a problem wit this line: killerId = killer.playerId;
int = VRCPlayerApi.playerId
?
you need to make sure you are only selecting a random player from an array that contains actual references to players in all it's slots
I'm guessing you are randomly assigning a player from your 32 size VRCPlayerApi[]
yea\
oh right, well how the hell do i do it then, thats why i prefer lists
if you use a list and add when they join, remove when they leave, all the slots will always be valid
vrchat has datalists
i know but they suck
void getRandomPlayer()
{
while (true)
{
randomPlayer = Random.Range(0, playerCount);
if (players[randomPlayer] != null)
{
killer = players[randomPlayer];
killerId = killer.playerId;
break;
}
}
}
i did this
use Utilities.IsValid instead of != null
also if you're dead set on an array, then perhaps instead of re-picking a random number over and over, you could pick a random number between 1 and the number of players in the instance, then iterate through the array until you find that number of valid players, and go with that one?
oh right
yeah but the problem hereis
that
its actually doing that
playerCount is always updating to be the count of the actual players in the instance
so how the hell is it null?
what are you doing to populate the array?
void ResizeAndAddPlayer(ref VRCPlayerApi[] array, VRCPlayerApi player)
{
int newSize = array.Length + 1;
VRCPlayerApi[] newArray = new VRCPlayerApi[newSize];
for (int i = 0; i < array.Length; i++)
{
newArray[i] = array[i];
}
newArray[newSize - 1] = player;
array = newArray;
}
and what about when someone leaves?
void RemovePlayer(ref VRCPlayerApi[] array, VRCPlayerApi player)
{
int newSize = array.Length - 1;
VRCPlayerApi[] newArray = new VRCPlayerApi[newSize];
int currentIndex = 0;
for (int i = 0; i < array.Length; i++)
{
if (array[i] != player)
{
newArray[currentIndex++] = array[i];
}
}
array = newArray;
}
I think that would shift everything down, not just the ones after the player you're trying to remove
wait actually it would shift them.. up?
you know what, i think ill just give up for now
just use a datalist 
it really does not look attracting
why not
well that's an example that uses strings
datalists and dictionaries store datatokens, datatokens can store anything
yeah like wtf are thoose
XD
you need ```
using VRC.SDK3.Data;```
a DataList is like a list
a DataDictionary is like a dictionary
this is how you'd do it
private DataList _players = new DataList();
public override void OnPlayerJoined(VRCPlayerApi player)
{
_players.Add(new DataToken(_players));
}
public override void OnPlayerLeft(VRCPlayerApi player)
{
_players.Remove(new DataToken(player));
}
public VRCPlayerApi GetRandomPlayer()
{
return (VRCPlayerApi)_players[Random.Range(0, _players.Count - 1)].Reference;
}
ah
in most cases you don't need new DataToken() btw, it's only in cases where they can't auto-cast because they come from system.object
Why are you subtracting one from the player count? Isn't Unity's Random.Range maximally exclusive with ints?
so how would i get all the player id's into one of thoose?
On start you add them all to the list
no, start is too early to interact with players
Then the code Phase posted should handle the rest
ah, my bad
No but like i want to add them there at a certain point
this example I posted is already storing the players directly, are you sure you need the playerids in addition?
yeah
so i can teleport them
wuh
but not all of them
that.. doesn't sound related
That is an entirely separate array.
yeah but shouldnt i also change that into a datalist?
you don't really need to add an additional list to store playerids because you already have the players right there
if you want a player's id you just get it from the player in the list
yes but now how do i get the player out of this datalist cause i cant do this:
I told them to use a synced int[] containing the players that should be teleported. Then OnDeserialization they check if the local id matches one in the array.
{
var player = (VRCPlayerApi)_players[i].Reference;
}```
right, that's what you need to do to store the array of players to be teleported, it doesn't mean you need a list of all the ids of all the players regardless
all you care about is whether or not the array contains your player id
you can't do foreach loops on datalists, sorry
all the answers are right here
what, if i cant foreach then i have no idea how to remake the resst of my code to work with this
a normal for loop?
-_-
but again, you don't need to change currentlyInGame to be a datalist
wait, ill write one for you @tacit drum
if it's supposed to sync you'd have to serialize it with json anyway
though if you did want to use a datalist for currentlyInGame, the one advantage of it would be that you wouldn't even need a for loop, you could just do .Contains
changed it like this
is currentlyInGame synced?
yeah
public void TeleportCommand()
{
SendCustomNetworkEvent(VRC.Udon.Common.Interfaces.NetworkEventTarget.All, nameof(TeleportPlayer);
}
public void TeleportPlayer()
{
if (isInGame)
{
Networking.LocalPlayer.TeleportTo(position, rotation);
}
}
datalists can't sync on their own
i already have this
then you just need to sync the bool isInGame
actually no, it can be local for each players
yeah so just this
cause now its local for each player
Assets/Scripts/GameControllerU.cs(21,20): 'currentlyInGame' type 'VRC.SDK3.Data.DataList' is not supported by Udon sync
ut says that its not supported by udon sync
that's what I've been trying to tell you
ah
currentlyInGame is perfectly fine as an array
Please don't mix network events and synced variables
Attempted to access DataList token as Reference
you tried to put a datalist inside a datalist then?
oh, then this can be called by another script on continuous sync
huh?
The what
"Attempted to access DataList token as Reference" is an error that means you tried to access a reference but it wasn't a reference, it was a datalist
if you can't mix manual sync and continuous sync so just separate scripts for both
so you need to make sure that what you're adding to the datalist is a playerapi, not another datalist or something
i did
killer = GetRandomPlayer();
and the killer is this
public VRCPlayerApi killer;
You shouldn't use continous sync for any of this. I wasn't talking about continous sync. I was saying you should not rely on network events and synced variables arriving in the correct order.
oh yea network racing conditions, I forgot about that
You should use OnDeserialization to do what you need with the updated synced variables
you're gonna have to be more clear what you're referring to when you posted this error then
i told you im refering to this
yes
and I told you
that error means your players list contains other datalists
so check the location where you're adding to that players list
i think i found it
alr no problems
but
this happends
becuse i can see the debug
but it does not teleport anyone
where does killer get assigned?
i cant see any errors so he must be
I'm not asking "if" I'm asking "where"
because without knowing I have no idea how to help you with this question
wait you're just adding all players to currentlyInGame regardless?
and again, if it's supposed to sync that won't work
except the killer
ah
its not since the killer id is synced
i dont have to sync theese datalists
it looks like startgame would run separately on all clients and everybody would assign their own killer
you should probably have an owner check before trying to start/end game
how would i make one?
if (!Networking.IsOwner(gameObject)) return;
in update
ondeserialization should only deal with killerid, not killer. Because killer is not synced
so even after adding this it still does not do anything
yeah, you need to fix up ondeserialization
ah
also ondeserialization doesn't run on the owner after you do RequestSerialization
You shouldn't be getting the playerCount in update
so should i change so teleport players and killer would be in StartGame?
it didint update when i put it anywhere else
I'd probably recommend having StartGame and OnDeserialization both call some common method which then handles teleporting players and doesn't care whether you're the owner or not
uhhuuu common method, what do you mean by that?
an event
so SendCustomNetworkEvent?
no
just a normal private void
and call that after StartGame
and during OnDeserialization
so that everyone runs it
YourMethod();
another thing is that you should probably not have ondeserialization re-check the start conditions. Maybe have a synced bool indicating whether or not the game is running, and when you get a serialization that changes it from false to true, that's how you know the game has started
i still dont understand how would i go about doing this
I got teleporting the killer to work
but the players still wont
annndd the killer is always the owner
if the killer is null, try to teleport everyone and the killer? That makes no sense
how the hell is he null
because it's not synced?
but it is
if i take everything out of the OnDesarialization
then the owner always teleports
to the killers spot
so the owner is always killer
no cause this checks if a game has ended and if it has, start next game
'
you shouldn't base whether or not the game has ended based on that because it will only work for the owner
add a synced bool that indicates whether or not the game is running and use that instead
You should be syncing a game state instead
use an enum
an enum for 2 different states?
if there's more than 2 states, yeah
I was assuming you would want more than 2
may want to have a setup stage or a countdown
so now when you start the game, set it to true
and when you stop the game, set it to false
i did
and then in handleserialization, you use that to determine what to do
instead of killer == null
oh you're trying to serialize the datalist to the inspector
im not
im just trying to do htis
just have datalists private
^
Probably not
well show us startgame and handleserialization
shouldn't it be the opposite? Teleport people if game is running?
just if (gameRunning) { TelportInGamePlayers(); TeleportKiller(); }
alr
again only the owner is the killer and the other people didint teleport
but the killer did
so what does teleportingameplayers do
currentlyInGame is not synced
but also if you're just adding everybody to the currentlyInGame list then I'm not sure what it's point is at all anyway
yeah but its adding everyome except the killer
oh
and it's also unnecessary
I guess they want to differentiate between players that were in the instance before the game started and those who joined late
wouldnt this do it
yeah
and i dont want the killer to be in there too
if that's the case then you need to change currentlyInGame back to an array
like it was before
😩
synced int[] my beloved
which I kept telling you to do
which is what I suggested in the first place
You don't need access to anything else from the VRCPlayerApis anyways
you don't need to handle onplayerleft removing them from currentlyInGame because playerids are never reused
just remove all of that
you will want to clear the array when the game is over though
alr
noooo
wait
i cant delte it
wa
??
wait a sec
i wanted to handle ending the game this way: a player respawns and gets delete from the currentlyInGame then if it reaches 0 the game ends
when the owner runs StopGame, they should set gameRunning to false and then ondeserialization everybody sees that and goes back to spawn room, they shouldn't care what currentlyInGame says
ok that's valid - if you really want to use a datalist for this, you could, but you'll have to serialize/deserialize it with json and sync the string
usually the hassle of doing that is not worth it for such a small simple list like this, it's great for huge nested structures though
Do you want it to end if any of them leave? or just the killer?
i want it to end if the currentlyInGame reaches 0 or if the killer leaves
okay, so just check if the killer ID matches the ID of the player that left
if you want to use a datalist for the conveniences of an easy count check, this is how you sync it:
Add a synced string called syncedCurrentlyInGame
in OnPreserialization (which runs before the owner sends synced data:
VRCJson.TrySerializeToJson(currentlyInGame, JsonExportType.Minify, out DataToken result);
syncedCurrentlyInGame = result.String;
In OnDeserialization:
VRCJson.TryDeserializeFromJson(syncedCurrentlyInGame, out DataToken result);
currentlyInGame = result.DataList;```
[UdonSharp] Assets/Scripts/GameControllerU.cs(119,57): Udon runtime exception detected!
An exception occurred during EXTERN to 'VRCSDK3DataDataList.__Add__VRCSDK3DataDataToken__SystemVoid'.
Parameter Addresses: 0x00000009, 0x00000048
Object reference not set to an instance of an object
this happend
after 3 players joined
so the datalist wasn't initialized
oh right i forgot
that's why you need to do thisprivate DataList currentlyInGame = new DataList();
ok now it its
i know sorry'
I feel like I have memories of not being able to initialize arrays and such in the class definition?
Am I hallucinating
nah it's fine
so the owner only got teleported although they werent the killer this time so they went on that dark tower except to the room on the bottom right
show the latest code
for teleporting?
oh, I thought currentlyInGame was a datalist of playerids?
damn i did this from the back
if you want to sync it, it can't contain playerapis
wait it isnt?
uhh you tell me
oh shit it isnt
yeah no it's not
it should be though
also if you're gonna use a datalist for currentlyInGame you don't need to for loop through it just to know whether or not you're in it. Just do .Contains(locid)
it is now
alr i messed up
[UdonSharp] Assets/Scripts/GameControllerU.cs(170,49): Udon runtime exception detected!
An exception occurred during EXTERN to 'VRCSDK3DataDataToken.__get_Reference__SystemObject'.
Parameter Addresses: 0x0000006D, 0x0000006E
Attempted to access Int token as Reference
you only changed some of them
make sure you change all of the places where currentlyInGame is used to use playerid instead of playerapi
yeah
but this reference thing isnt working
because a reference is not an int
oh right, also when serialized with json, ints turn into doubles 
💀
just get currentlyInGame[i].Number
and round it to int or something
Mathf.RoundToInt(currentlyInGame[i].Number)
ok, when you receive it with OnDeserialization, just loop through and round everything to int
and then you can use int everywhere
Mathf.RoundToInt((float)currentlyInGame[i].Number)
yes
VRCJson.TryDeserializeFromJson(syncedCurrentlyInGame, out DataToken result);
currentlyInGame = result.DataList;
for (int i = 0; i < currentlyInGame.Count; i++)
{
currentlyInGame[i] = Mathf.RoundToInt((float)currentlyInGame[i].Number);
}```
exactly what i did just now XD
again only the owner teleported
now in this, use currentlyInGame[i].int instead of .Reference
and again as a player not a killer
show the teleport function?
right, change that to int
why not
it's capital Int
a
I thought you changed this to .Contains a while ago
now that you're changing everything to ints in ondeserialization that should work
did you... actually fix it
no
show me the teleport function
its the same as before
then why did you test it again
why test it
ok, do the other players at least get "Not local player" logged?
i can only see one log with Local Player
show me ondeserialization
on the non-owners?
cant see anything for them
you're not assigning it back after rounding it
Mathf.RoundToInt just returns the rounded int, it doesn't magically do something to it
so you need to assign it
currentlyInGame[i] = Mathf.RoundToInt((float)currentlyInGame[i].Number);```
right, again sorry its like 3 am rn
and for good measure, in the for loop in teleport players, add a log to print what everything is
Maybe you should go sleep and pick this up later.
Debug.Log(currentlyInGame[i]); at the start of the for loop
yeah but then you guys wont be online
XD
we are all terminally online
don't worry
alr
idk
owner now spawned as a killer while the other players didintspawn
what do the other player's logs say
but i can see 2 logs called not local player
th killer teleport function does not have a debug
but it works
did you print the contents of currentlyInGame
yes and i can see the id of player 2 and player 3
so it just printed 2 & 3
(i have them collapsed)
ok, did they not get teleported anywhere or by any chance did they get shoved against a wall
they didint get teleported anywhere like in the picture
they are in the little transparent box (aka lobby )
You'll probably at some point run into this problem - might as well handle it now. Doing a teleport from ondeserialization doesn't usually work. They get stuck on walls. Instead of calling teleport directly you'll need to do sendcustomeventdelayed

the what
why
Because ondeserialization happens at a weird point in the frame where the player controller doesn't expect to be moved
a
how do i use this
i did this
but i know its wrong
SendCustomEventDelayedFrames(nameof(TelportInGamePlayers), 0);
it takes a string which is why we use nameof
oh also, I just noticed... you need to run HandleSerialization after all the json stuff
If that still doesn't work then add more logs. Log the local id, log the result of comparing local to the item in the list, log the result of list.contains, etc
did you move handleserialization after the json stuff
yeah
wait wait wait
omg
when you say other players, do you mean remote players spawned in client sim
