From 1252933ca40ebe6ead8a5399a567119e1d04f934 Mon Sep 17 00:00:00 2001 From: Marro64 Date: Mon, 22 Jun 2026 18:31:16 +0200 Subject: [PATCH] Improving sync --- Assets/Scripts/GameManager.cs | 61 +++++++++++++----- Assets/Scripts/Ghost.cs | 40 +++++++----- Assets/Scripts/PlayerInput.cs | 28 ++++++++ .../Sequences/AttractScreenIntroduction.cs | 2 +- Assets/Scripts/Sequences/StartNewLevel.cs | 1 + .../Scripts/Sequences/TimeSequenceShared.cs | 22 +++---- Assets/Scripts/SoundManager.asset | 64 +++++++++---------- 7 files changed, 142 insertions(+), 76 deletions(-) diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs index e5bd9df..f31b2e5 100644 --- a/Assets/Scripts/GameManager.cs +++ b/Assets/Scripts/GameManager.cs @@ -16,7 +16,6 @@ namespace Marro.PacManUdon [SerializeField] private GameObject intermissionScreen; [SerializeField] private GameObject pressStartButtonScreen; [SerializeField] private PlayerInput playerInput; - [SerializeField] private Animator demo; [SerializeField] private SoundManager soundManager; [SerializeField] private NetworkManager networkManagerSetup; @@ -143,6 +142,7 @@ namespace Marro.PacManUdon bonusFruit.Despawn(); soundManager.Reset(); collisionManager.Reset(); + statusDisplay.Reset(); } private void PrepareForCutscene() @@ -263,7 +263,6 @@ namespace Marro.PacManUdon statusDisplay.SetLevelDisplayVisible(false); statusDisplay.SetPlayer1TextVisible(false); statusDisplay.SetReadyTextVisible(false); - demo.gameObject.SetActive(false); } void SetPelletsActive(bool active) @@ -373,6 +372,27 @@ namespace Marro.PacManUdon soundManager.PlayExtraLifeSound(); } + private void SetupInGameState() + { + gameState = PacManGameState.InGame; + + attractScreen.gameObject.SetActive(false); + + SetPelletsActive(true); + SetMazeVisible(true); + SetGhostsActive(true); + SetPacManActive(true); + + statusDisplay.SetExtraLivesDisplayVisible(true); + statusDisplay.SetLevelDisplayVisible(true); + statusDisplay.SetLabel1UPTextBlinking(true); + + soundManager.SuppressSound(false); + soundManager.StartGhostSound(); + + SetFrozen(false); + } + public void SetFrozen(bool frozen, bool ghostIgnoreIfCaught = false, bool ghostKeepAnimating = false) { // Debug.Log($"{gameObject} Set Frozen: {frozen}"); @@ -389,6 +409,12 @@ namespace Marro.PacManUdon return; } + data.Append(gameState == PacManGameState.InGame, ref index); + + data.AppendAsByte(level, ref index); + data.Append(score, ref index); + data.AppendAsByte(extraLives, ref index); + data.Append(currentlyInTimeSequence, ref index); if (currentlyInTimeSequence) @@ -397,10 +423,6 @@ namespace Marro.PacManUdon data.Append(timeSequenceSecondsPassed, ref index); } - data.AppendAsByte(level, ref index); - data.Append(score, ref index); - data.AppendAsByte(extraLives, ref index); - bonusFruit.CollectSyncedData(data, ref index, eventType); collisionManager.CollectSyncedData(data, ref index, eventType); @@ -425,22 +447,31 @@ namespace Marro.PacManUdon return true; } - var currentlyInTimeSequence = data.ReadBool(ref index); - if (currentlyInTimeSequence) + // If we're currently in-game, we'll need to make sure the state is setup correctly + var remoteCurrentlyInGame = data.ReadBool(ref index); + if (remoteCurrentlyInGame) { - var currentTimeSequence = (PacManTimeSequence)data.ReadByte(ref index); - var timeSequenceSecondsPassed = data.ReadFloat(ref index); - TimeSequenceSyncWithRemote(currentTimeSequence, timeSequenceSecondsPassed); - } - else - { - TimeSequenceTryEndCurrent(); + currentlyInTimeSequence = false; // Kill the current time sequence, otherwise it might interfere + // No need to run it to completion since we're overriding all state + SetupInGameState(); } SetLevel(data.ReadByte(ref index)); SetScore(data.ReadInt(ref index)); SetExtraLives(data.ReadByte(ref index)); + // Sync up with the remote's time sequence + var remoteCurrentlyInTimeSequence = data.ReadBool(ref index); + if (remoteCurrentlyInTimeSequence) + { + var currentTimeSequence = (PacManTimeSequence)data.ReadByte(ref index); + var timeSequenceSecondsPassed = data.ReadFloat(ref index); + TimeSequenceSyncWithRemote(currentTimeSequence, timeSequenceSecondsPassed); + } + + // Note that we don't have any logic for if the remote is not in-game and not in a time sequence. + // Such a state should be impossible. + bonusFruit.WriteSyncedData(data, ref index, eventType); collisionManager.WriteSyncedData(data, ref index, eventType); diff --git a/Assets/Scripts/Ghost.cs b/Assets/Scripts/Ghost.cs index 75629f2..5c40bc8 100644 --- a/Assets/Scripts/Ghost.cs +++ b/Assets/Scripts/Ghost.cs @@ -15,6 +15,15 @@ namespace Marro.PacManUdon Special, } + enum PacManGhostAnimatorState + { + Normal, + Caught, + Scared, + ScaredWhite, + Special + } + public enum PacManGhostState { Normal, @@ -68,6 +77,7 @@ namespace Marro.PacManUdon // State private PacManGhostState ghostState; private bool isScared; + private bool whiteScared; private bool scattering; private PacManGhostFrozenState frozenState; @@ -540,21 +550,20 @@ namespace Marro.PacManUdon SetAnimatorDirection((int)targetDirection); } - if (isScared) // Don't update ghost type while scared as this interrupts the white/blue blinking - { - return; - } - PacManGhostType ghostType = this.ghostType; - if (specialLook) + if (isScared) { - ghostType = PacManGhostType.Special; + ghostType = whiteScared ? PacManGhostType.ScaredWhite : PacManGhostType.Scared; } else if (ghostState == PacManGhostState.Returning || ghostState == PacManGhostState.Entering) { ghostType = PacManGhostType.Caught; } + else if (specialLook) + { + ghostType = PacManGhostType.Special; + } SetAnimatorGhostType((int)ghostType); } @@ -671,13 +680,8 @@ namespace Marro.PacManUdon private void SetScared(bool scared) { isScared = scared; - UpdateAnimator(); + SetWhite(false); UpdateSpeed(); - - if (isScared) - { - SetWhite(false); - } } public void SetScattering(bool scattering, bool reverseDirection = true) @@ -738,10 +742,8 @@ namespace Marro.PacManUdon public void SetWhite(bool white) { - if (!isScared || !gameObject.activeInHierarchy) - return; - - SetAnimatorGhostType(white ? (int)PacManGhostType.ScaredWhite : (int)PacManGhostType.Scared); + whiteScared = white; + UpdateAnimator(); } public void SetElroy(int elroyLevel) @@ -820,6 +822,7 @@ namespace Marro.PacManUdon data.AppendAsByte((int)ghostState, ref index); data.Append(isScared, ref index); + data.Append(whiteScared, ref index); data.Append(scattering, ref index); data.AppendAsByte((int)frozenState, ref index); @@ -847,6 +850,7 @@ namespace Marro.PacManUdon ghostState = (PacManGhostState)data.ReadByte(ref index); isScared = data.ReadBool(ref index); + whiteScared = data.ReadBool(ref index); scattering = data.ReadBool(ref index); frozenState = (PacManGhostFrozenState)data.ReadByte(ref index); @@ -855,6 +859,8 @@ namespace Marro.PacManUdon housePelletCounterActive = data.ReadBool(ref index); housePelletCounterLimit = data.ReadByte(ref index); + UpdateSpeed(); + return base.WriteSyncedData(data, ref index, eventType); } } diff --git a/Assets/Scripts/PlayerInput.cs b/Assets/Scripts/PlayerInput.cs index 1c63d4c..9428c41 100644 --- a/Assets/Scripts/PlayerInput.cs +++ b/Assets/Scripts/PlayerInput.cs @@ -39,6 +39,34 @@ SubscribeToEvent(NetworkEventType.PacManTurn); } + void Update() + { + if (active) + { + if (Input.GetKeyDown(KeyCode.R)) + { + gameManager.ResetButtonPressed(); + } + + if (Input.GetKeyDown(KeyCode.G)) + { + gameManager.networkManager.DoFullSync(); + } + + if (Input.GetKeyDown(KeyCode.C)) + { + gameManager.JumpToTimeSequenceBoardClear(); + } + } + else + { + if (Input.GetKeyDown(KeyCode.T)) + { + gameManager.ResetButtonPressed(); + } + } + } + public void Activate() { Debug.Log($"{gameObject} got activated, {player} was immobilized"); diff --git a/Assets/Scripts/Sequences/AttractScreenIntroduction.cs b/Assets/Scripts/Sequences/AttractScreenIntroduction.cs index ba77f9d..5167095 100644 --- a/Assets/Scripts/Sequences/AttractScreenIntroduction.cs +++ b/Assets/Scripts/Sequences/AttractScreenIntroduction.cs @@ -12,7 +12,7 @@ namespace Marro.PacManUdon PrepareForCutscene(); SetGameState(PacManGameState.AttractMode); - + // Initialize soundManager.SuppressSound(true); attractScreen.gameObject.SetActive(true); diff --git a/Assets/Scripts/Sequences/StartNewLevel.cs b/Assets/Scripts/Sequences/StartNewLevel.cs index 4d65fb4..7211e1d 100644 --- a/Assets/Scripts/Sequences/StartNewLevel.cs +++ b/Assets/Scripts/Sequences/StartNewLevel.cs @@ -12,6 +12,7 @@ namespace Marro.PacManUdon // Reset, show maze and score display SetMazeVisible(true); statusDisplay.SetScoreDisplayVisible(true); + statusDisplay.SetLabel1UPTextBlinking(true); break; case 1: // Increment level, show ready, show pellets, show lives indicators diff --git a/Assets/Scripts/Sequences/TimeSequenceShared.cs b/Assets/Scripts/Sequences/TimeSequenceShared.cs index 76a77ef..92afba6 100644 --- a/Assets/Scripts/Sequences/TimeSequenceShared.cs +++ b/Assets/Scripts/Sequences/TimeSequenceShared.cs @@ -42,7 +42,6 @@ namespace Marro.PacManUdon jumpingToTimeSequence = true; TimeSequenceProgressToTime(100000f); - if (waitingForTimeSequenceFinalize) { @@ -102,22 +101,23 @@ namespace Marro.PacManUdon } } - private void TimeSequenceSyncWithRemote(PacManTimeSequence currentTimeSequence, float timeSequenceSecondsPassed) + private void TimeSequenceSyncWithRemote(PacManTimeSequence remoteCurrentTimeSequence, float timeSequenceSecondsPassedRemote) { - // If the remote is in a time sequence but we're not, or we're in a different time sequence, or if we're behind, - // jump to the remote's time sequence. - if (!currentlyInTimeSequence - || currentTimeSequence != this.currentTimeSequence - || timeSequenceSecondsPassed < this.timeSequenceSecondsPassed) + // If our current time sequence state is incompatible with the remote time sequence, kill it + if (currentlyInTimeSequence && remoteCurrentTimeSequence != currentTimeSequence + || timeSequenceSecondsPassedRemote < timeSequenceSecondsPassed) { - StartTimeSequence(currentTimeSequence); + currentlyInTimeSequence = false; } - // If we're (now) in a time sequence, jump our progress to match the one on the remote - if (currentlyInTimeSequence) + // If we're not/no longer in a time sequence, start the remote's time sequence + if (!currentlyInTimeSequence) { - TimeSequenceProgressToTime(timeSequenceSecondsPassed); + StartTimeSequence(remoteCurrentTimeSequence); } + + // Jump our progress to match the one on the remote + TimeSequenceProgressToTime(timeSequenceSecondsPassedRemote); } #region Events diff --git a/Assets/Scripts/SoundManager.asset b/Assets/Scripts/SoundManager.asset index b5f29dc..a2e7eb3 100644 --- a/Assets/Scripts/SoundManager.asset +++ b/Assets/Scripts/SoundManager.asset @@ -1147,19 +1147,25 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _nextDotSound + Data: alternatePelletSound - Name: $v Entry: 7 Data: 65|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _nextDotSound + Data: alternatePelletSound - Name: k__BackingField - Entry: 9 - Data: 17 + Entry: 7 + Data: 66|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Boolean, mscorlib + - Name: + Entry: 8 + Data: - Name: k__BackingField Entry: 9 - Data: 17 + Data: 66 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -1174,7 +1180,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 66|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 67|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -1195,25 +1201,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _ghostRetreating + Data: ghostRetreating - Name: $v Entry: 7 - Data: 67|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 68|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _ghostRetreating + Data: ghostRetreating - Name: k__BackingField - Entry: 7 - Data: 68|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Boolean, mscorlib - - Name: - Entry: 8 - Data: + Entry: 9 + Data: 66 - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -1249,19 +1249,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _ghostBlue + Data: ghostBlue - Name: $v Entry: 7 Data: 70|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _ghostBlue + Data: ghostBlue - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -1297,13 +1297,13 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _ghostSoundLevel + Data: ghostSoundLevel - Name: $v Entry: 7 Data: 72|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _ghostSoundLevel + Data: ghostSoundLevel - Name: k__BackingField Entry: 7 Data: 73|System.RuntimeType, mscorlib @@ -1351,19 +1351,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _currentlyPlayingSiren + Data: currentlyPlayingSiren - Name: $v Entry: 7 Data: 75|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _currentlyPlayingSiren + Data: currentlyPlayingSiren - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -1399,19 +1399,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: _suppress + Data: suppress - Name: $v Entry: 7 Data: 77|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: _suppress + Data: suppress - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 9 - Data: 68 + Data: 66 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib