- LocationBoard callbacks now only run on the host.

- CameraAnchor now properly syncs followed player data.
This commit is contained in:
2026-04-21 16:35:19 -04:00
parent 47eb6aae77
commit a6b3b840b2
16 changed files with 333 additions and 264 deletions
+117 -111
View File
@@ -564,22 +564,130 @@ MonoBehaviour:
Data:
- Name: $k
Entry: 1
Data: _AttachedCamera
Data: _FollowedPlayerNames
- Name: $v
Entry: 7
Data: 37|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _AttachedCamera
Data: _FollowedPlayerNames
- Name: <UserType>k__BackingField
Entry: 7
Data: 38|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.String[], mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 38
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 3
Data: 1
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 39|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 40|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _AttachedCamera
- Name: $v
Entry: 7
Data: 41|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _AttachedCamera
- Name: <UserType>k__BackingField
Entry: 7
Data: 42|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.Camera, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 42
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 43|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _FollowedPlayerNames_Cache
- Name: $v
Entry: 7
Data: 44|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _FollowedPlayerNames_Cache
- Name: <UserType>k__BackingField
Entry: 9
Data: 38
- Name: <SystemType>k__BackingField
Entry: 9
Data: 38
@@ -597,109 +705,7 @@ MonoBehaviour:
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 39|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _FollowedPlayerNames
- Name: $v
Entry: 7
Data: 40|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _FollowedPlayerNames
- Name: <UserType>k__BackingField
Entry: 7
Data: 41|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: System.String[], mscorlib
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 41
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 42|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: _FollowedPlayerNames_Cache
- Name: $v
Entry: 7
Data: 43|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _FollowedPlayerNames_Cache
- Name: <UserType>k__BackingField
Entry: 9
Data: 41
- Name: <SystemType>k__BackingField
Entry: 9
Data: 41
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 44|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
Data: 45|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
@@ -723,13 +729,13 @@ MonoBehaviour:
Data: _FollowedPlayers
- Name: $v
Entry: 7
Data: 45|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
Data: 46|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _FollowedPlayers
- Name: <UserType>k__BackingField
Entry: 7
Data: 46|System.RuntimeType, mscorlib
Data: 47|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: VRC.SDKBase.VRCPlayerApi[], VRCSDKBase
@@ -738,7 +744,7 @@ MonoBehaviour:
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 46
Data: 47
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -753,7 +759,7 @@ MonoBehaviour:
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 47|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
Data: 48|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
@@ -777,7 +783,7 @@ MonoBehaviour:
Data: _CameraFollowSpeed
- Name: $v
Entry: 7
Data: 48|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
Data: 49|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: _CameraFollowSpeed
@@ -801,7 +807,7 @@ MonoBehaviour:
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 49|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
Data: 50|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
+35 -10
View File
@@ -1,6 +1,7 @@
using CameraSystem;
using MMMaellon.LightSync;
using System.Linq;
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
@@ -36,8 +37,9 @@ public class CameraAnchor : UdonSharpBehaviour
[UdonSynced] private int _AttachedCameraIndex = -1;
[UdonSynced] private string[] _FollowedPlayerNames = new string[0];
private Camera _AttachedCamera = null;
private string[] _FollowedPlayerNames = new string[0];
private string[] _FollowedPlayerNames_Cache = new string[0];
private VRCPlayerApi[] _FollowedPlayers = new VRCPlayerApi[0];
private float _CameraFollowSpeed = 1.0f;
@@ -65,6 +67,11 @@ public class CameraAnchor : UdonSharpBehaviour
Vector3 CentroidSum = Vector3.zero;
for (int i = 0; i < _FollowedPlayers.Length; i++)
{
if (_FollowedPlayers[i] == null)
{
continue;
}
Vector3[] BonePositions = _BonesFromFollowMethod(_FollowedPlayers[i]);
Vector3 CentroidPointsAverage = Vector3.zero;
for (int j = 0; j < BonePositions.Length; j++)
@@ -92,7 +99,6 @@ public class CameraAnchor : UdonSharpBehaviour
private Vector3[] _BonesFromFollowMethod(VRCPlayerApi Player)
{
switch(FollowMethod)
{
case PossibleFollowMethods.CloseUp:
@@ -124,10 +130,10 @@ public class CameraAnchor : UdonSharpBehaviour
case PossibleFollowMethods.HipsDown:
{
Vector3[] BonesToTrack = new Vector3[4];
BonesToTrack[2] = Player.GetBonePosition(HumanBodyBones.LeftUpperLeg);
BonesToTrack[3] = Player.GetBonePosition(HumanBodyBones.RightUpperLeg);
BonesToTrack[0] = Player.GetBonePosition(HumanBodyBones.LeftFoot);
BonesToTrack[1] = Player.GetBonePosition(HumanBodyBones.RightFoot);
BonesToTrack[0] = Player.GetBonePosition(HumanBodyBones.LeftUpperLeg);
BonesToTrack[1] = Player.GetBonePosition(HumanBodyBones.RightUpperLeg);
BonesToTrack[2] = Player.GetBonePosition(HumanBodyBones.LeftFoot);
BonesToTrack[3] = Player.GetBonePosition(HumanBodyBones.RightFoot);
return BonesToTrack;
}
case PossibleFollowMethods.FullBody:
@@ -234,21 +240,40 @@ public class CameraAnchor : UdonSharpBehaviour
VRCPlayerApi[] AllPlayers = new VRCPlayerApi[VRCPlayerApi.GetPlayerCount()];
VRCPlayerApi.GetPlayers(AllPlayers);
int i = 0;
foreach (string PlayerName in _FollowedPlayerNames)
int NumValidPlayers = 0;
for (int i = 0; i < _FollowedPlayerNames.Length; i++)
{
string PlayerName = _FollowedPlayerNames[i];
Debug.Log("[CameraAnchor] Trying to find player " + PlayerName + "...");
_FollowedPlayers[i] = null;
foreach (VRCPlayerApi Player in AllPlayers)
{
if (Player.displayName == PlayerName)
{
Debug.Log("[CameraAnchor] Found player " + PlayerName);
_FollowedPlayers[i] = Player;
i++;
NumValidPlayers++;
break;
}
}
}
Debug.Log("[CameraAnchor] Anchor " + gameObject.name + " is now following " + _FollowedPlayerNames);
Debug.Log("[CameraAnchor] Found " + NumValidPlayers + " players out of a requested " + _FollowedPlayerNames.Length);
int ValidPlayerCounter = 0;
VRCPlayerApi[] ValidPlayers = new VRCPlayerApi[NumValidPlayers];
foreach (VRCPlayerApi Player in _FollowedPlayers)
{
if (Player != null)
{
ValidPlayers[ValidPlayerCounter] = Player;
ValidPlayerCounter++;
}
}
string PlayerNamesString = string.Join(", ", _FollowedPlayerNames);
Debug.Log("[CameraAnchor] Anchor " + gameObject.name + " is now following { " + PlayerNamesString + " }");
_FollowedPlayerNames_Cache = _FollowedPlayerNames;
}
@@ -219,17 +219,20 @@ public class GameManagerRound2 : GameManagerBase
_Players[1] = _Players[0];
}
HostCardRecoverTheLootInterface RecoverTheLootInterface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
RecoverTheLootInterface.SetComment(_Players[_CurrentPlayerCounter % _Players.Length] + ", you're up first.", COLOR_STANDARD);
RecoverTheLootInterface.SetLootButton(_LocationBoard.LootLocation);
RecoverTheLootInterface.SetWarrantButton(_LocationBoard.WarrantLocation);
RecoverTheLootInterface.SetCrookButton(_LocationBoard.CrookLocation);
RecoverTheLootInterface.ActivateAllPanelButtons(true, true);
for (int i = 0; i < _Landmarks.Length; i++)
if (Networking.LocalPlayer == _CaseManager.GetHostOwner())
{
RecoverTheLootInterface.AddLandmarkName(i, _Landmarks[i]);
HostCardRecoverTheLootInterface RecoverTheLootInterface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
RecoverTheLootInterface.SetComment(_Players[_CurrentPlayerCounter % _Players.Length] + ", you're up first.", COLOR_STANDARD);
RecoverTheLootInterface.SetLootButton(_LocationBoard.LootLocation);
RecoverTheLootInterface.SetWarrantButton(_LocationBoard.WarrantLocation);
RecoverTheLootInterface.SetCrookButton(_LocationBoard.CrookLocation);
RecoverTheLootInterface.ActivateAllPanelButtons(true, true);
for (int i = 0; i < _Landmarks.Length; i++)
{
RecoverTheLootInterface.AddLandmarkName(i, _Landmarks[i]);
}
}
_JailPlayer.VideoIndex = (int)_CaseManager.GetCrook();
@@ -242,6 +245,8 @@ public class GameManagerRound2 : GameManagerBase
public void OnTheRightTrack()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
Interface.SetComment("On the right track. You get a free turn.", COLOR_GREEN);
@@ -251,6 +256,8 @@ public class GameManagerRound2 : GameManagerBase
public void AlmostThere()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
Interface.SetComment("Almost got it. Another free turn.", COLOR_YELLOW);
@@ -260,6 +267,8 @@ public class GameManagerRound2 : GameManagerBase
public void OutOfOrder(PanelType Type)
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
@@ -286,6 +295,8 @@ public class GameManagerRound2 : GameManagerBase
// all inputs to prevent messing up the game state.
public void NothingThere()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
Interface.SetComment("Nothing there.", COLOR_STANDARD);
@@ -297,6 +308,8 @@ public class GameManagerRound2 : GameManagerBase
public void AlreadyTried()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
Interface.SetComment("Already tried that one.", COLOR_STANDARD);
@@ -308,6 +321,8 @@ public class GameManagerRound2 : GameManagerBase
public void NiceStrategy()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
HostCardRecoverTheLootInterface Interface =
(HostCardRecoverTheLootInterface)GetHostCardInterface(RoundSegmentType.RecoverTheLoot);
Interface.SetComment("Nice strategy.", COLOR_GREEN);
@@ -321,6 +336,8 @@ public class GameManagerRound2 : GameManagerBase
// and should also enable victory animations.
public void YoureWinner()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
_RoundIsOver = true;
int WinningPlayerNumber = _CurrentPlayerCounter % _Players.Length;
string[] Winner = new string[1];
@@ -343,7 +360,7 @@ public class GameManagerRound2 : GameManagerBase
}
public void YoureWinnerDelayedFunctions()
{
_PlayerConfettiCannons[_CurrentPlayerCounter % _Players.Length].Play();
SendCustomNetworkEvent(NetworkEventTarget.All, nameof(YoureWinnerConfettiPlayer));
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "StopMusic");
SendCustomEventDelayedSeconds(nameof(YoureWinnerDelayedFunctions2), 1.0f);
@@ -352,6 +369,11 @@ public class GameManagerRound2 : GameManagerBase
{
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "PlayMusic", MusicEventType.YoureWinner);
}
[NetworkCallable]
public void YoureWinnerConfettiPlayer()
{
_PlayerConfettiCannons[_CurrentPlayerCounter % _Players.Length].Play();
}
private void RoundWinner()
@@ -432,24 +454,32 @@ public class GameManagerRound2 : GameManagerBase
public void FoundTheLoot()
{
_AudioManager.PlaySFX(SFXEventType.TheLoot);
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "PlaySFX", SFXEventType.TheLoot);
SendCustomEventDelayedSeconds(nameof(ActivateAllPanelButtonsExceptTargets_DelayFunction), 1.5f);
}
public void FoundTheWarrant()
{
_AudioManager.PlaySFX(SFXEventType.TheWarrant);
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "PlaySFX", SFXEventType.TheWarrant);
SendCustomEventDelayedSeconds(nameof(ActivateAllPanelButtonsExceptTargets_DelayFunction), 1.5f);
}
public void FoundTheCrook()
{
_AudioManager.PlayCrookTheme(_CaseManager.GetCrook());
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
_AudioManager.SendCustomNetworkEvent(NetworkEventTarget.All, "PlayCrookTheme", _CaseManager.GetCrook());
SendCustomEventDelayedSeconds(nameof(ActivateAllPanelButtonsExceptTargets_DelayFunction), 1.5f);
}
public void ActivateAllPanelButtonsExceptTargets_DelayFunction()
{
if (Networking.LocalPlayer != _CaseManager.GetHostOwner()) return;
if (!_RoundIsOver)
{
HostCardRecoverTheLootInterface Interface =
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: BoneFollower
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: ccbda9bf23e2f714c9226283c77a92e5,
serializedUdonProgramAsset: {fileID: 11400000, guid: 52ecc8a73071e8e40928c3609699fcf4,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: InteractToggle
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 405e38d3dfb2f514daeed0e28fbb4864,
serializedUdonProgramAsset: {fileID: 11400000, guid: 873dfce61b1514e429c92e0d2fded7de,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: PlayerModSetter
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: f938e6c4ff027a74da405a1f9353fd2b,
serializedUdonProgramAsset: {fileID: 11400000, guid: e81558796a212ab4d88e305e2010f24b,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: GlobalToggleObject
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: c49c9265a3ef24642a6a4465d0a78872,
serializedUdonProgramAsset: {fileID: 11400000, guid: 2fe8ced6184000f49bca526cd2c5891c,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: MasterToggleObject
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 04024a76ab1924042ba521e11cb76d91,
serializedUdonProgramAsset: {fileID: 11400000, guid: a2d01d9f36ac6df49831be249e48ecc4,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: TrackingDataFollower
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 17f8fbbe6cc186d4f8dbb057b01a4ec2,
serializedUdonProgramAsset: {fileID: 11400000, guid: 1b89d4552983c0448a7389decec3b555,
type: 2}
udonAssembly:
assemblyError:
@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: WorldAudioSettings
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 128d924a3066b7546b2d1c73e61006ab,
serializedUdonProgramAsset: {fileID: 11400000, guid: 994b559b0f158b4499f8937980ed8694,
type: 2}
udonAssembly:
assemblyError: