The deeper I get into udon, the more I realize that it's just as broken as the trigger system + animation states + UIButton hackery of the old SDK, but in new and exciting ways. For wooden poker, I've given up on using the native udon "syncrhonize position" to sync all 136 tiles reliably. Even if the shuffle "works", eventually some tiles will randomly explode on somebody's client, and there's no way to reconcile it.

So, I've been trying to do physics syncing through the other mechanisms exposed to udon. I first tried putting an synced Vector3/Quaternion on every single tile, and having some events locally to periodically check and reconcile the individual tiles according to their owner's transform. However, udon balks at syncing 136 of those; There's some lower-level "Death run detected" in the networking code that prevents a client from spamming the network with those events. 136 synced udon objects is too much for it. Even the mere presence of that many synced variables chokes it.

So, I've been trying to pack in the variables to a few synced strings instead. I got it to work for a few tiles with naive encoding (toString essentially), but due to this limitation, you can only sync 64ish characters in a single string:

https://vrchat.canny.io/vrchat-udon-closed-alpha-bugs/p/synced-strings-over-a-certain-length-will-cause-an-argumentoutofrangeexception

So assuming a fancier byte-packing serializer and deserializer. WIth full float precision, that's 136 * (3 position floats * 3 rotation floats) * 4 bytes/float = 3264 bytes, or about 51 synced strings. That _may_ be under some "death run" detection limit, but it's still a lot. Might need further compression or limited tile locations like "in player N's hand, in discard N, etc etc".