[1431]Udon that are inactive when the world is loaded are not synchronized when they become active
complete
みみー/Mimy
Udons that are inactive at the time of world loading will not be synchronized when they become active
I first looked at the state immediately after Join.
- build the world by deactivating the Udon with one int type Udonsync variable
- the owner (playerID = 1) activates the synchronization object and counts the variable +1
- nothing happens under non-owner player2 (playerID = 2)
- player2 activates the synchronization object and then the owner sets the count of the variable to 2.
- the value is synchronized for the first time to the synchronization object of player 2 and the count is set to 2.
Then we examined the state of the object once it was activated.
- the synchronization object of player 2 is deactivated.
- the owner sets the variable count +1 twice.
- nothing happens under player 2.
- when player 2 activates the synchronization object, the synchronization events during the period of inactivity are executed consecutively and the count goes to 3 and then to 4.
Finally, the state of the later-joiner is examined.
- In player 3's client, nothing happens immediately after Join because the Udon object is inactive.
- nothing happens when player 3 activates the object.
- when the owner sets the count of a variable to 5, the value of 5 is suddenly synced to player 3.
If the Udon is active at the time of loading the world, the later-joiner will also be synchronized with the latest values immediately after the join. The owner does not need to do anything at this time.
Translated with www.DeepL.com/Translator (free version)
Test code:
using System;
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using TMPro;
using VRC.Udon.Common;
public class LaterJoinerTest : UdonSharpBehaviour
{
[SerializeField]
TextMeshProUGUI log;
[UdonSynced, FieldChangeCallback(nameof(TestValue))]
int _testValue = 0;
public int TestValue
{
get => _testValue;
set
{
log.text += DateTime.Now.ToLongTimeString() + " OnValueChanged: new value = " + value.ToString() + ", old value = " + _testValue.ToString() + "\n";
_testValue = value;
}
}
void Start()
{
log.text += DateTime.Now.ToLongTimeString() + " Start: playerID = " + Networking.LocalPlayer.playerId.ToString() + " value = " + TestValue.ToString() + "\n";
}
private void OnEnable()
{
log.text += DateTime.Now.ToLongTimeString() + " OnEnable: value = " + TestValue.ToString() + "\n";
}
private void OnDisable()
{
log.text += DateTime.Now.ToLongTimeString() + " OnDisable: value = " + TestValue.ToString() + "\n";
}
public override void OnPreSerialization()
{
log.text += DateTime.Now.ToLongTimeString() + " OnPreSerializaton: value = " + TestValue.ToString() + "\n";
}
public override void OnPostSerialization(SerializationResult result)
{
log.text += DateTime.Now.ToLongTimeString() + " OnPostSerializaton: value = " + TestValue.ToString() + "\n";
}
public override void OnDeserialization()
{
log.text += DateTime.Now.ToLongTimeString() + " OnDeserializaton: value = " + TestValue.ToString() + "\n";
}
public override void OnOwnershipTransferred(VRCPlayerApi player)
{
log.text += DateTime.Now.ToLongTimeString() + " OnOwnershipTransferred: playerID = " + player.playerId.ToString() + " value = " + TestValue.ToString() + "\n";
}
public override void OnPlayerJoined(VRCPlayerApi player)
{
log.text += DateTime.Now.ToLongTimeString() + " OnPlayerJoined: playerID = " + player.playerId.ToString() + " value = " + TestValue.ToString() + "\n";
}
public override void Interact()
{
if (!Networking.IsOwner(this.gameObject)) { Networking.SetOwner(Networking.LocalPlayer, this.gameObject); }
TestValue++;
RequestSerialization();
log.text += DateTime.Now.ToLongTimeString() + " Interact & RequestSerialization: value = " + TestValue.ToString() + "\n";
}
}
Log In
StormRel
complete
This post was marked as
available in future release
_
_tau_
Do you have a world ID where this behaviour can be reproduced?
みみー/Mimy
_tau_ I have confirmed this behavior on my test world.
I have also prepared a world specifically for this test.
The left one loads with disable, the right one loads with enable.
_
_tau_
みみー/Mimy: Does this behave differently on the current live version of VRChat, build 1407?
みみー/Mimy
_tau_ I have tested reproducing this with the client set to LIVE (1407).
The non-owner player updates the synchronization variables upon activation, but FieldChangeCallback (OnValueChanged in SS) is called earlier than OnEnable/Start. After it is activated for the first time, it is called in the expected order.
Honestly, this was known information. https://feedback.vrchat.com/udon/p/1259-synced-variables-can-be-changed-from-owners-requestserialization-before-lat
StormRel
tracked
みみー/Mimy
Incidentally, objects registered in the VRCObjectPool behave the same as inactive objects at the time of world loading, whether they remain active on the Hierarchy or have already been spawned.