From c1d0af9a39ac61c80a47046b20bc31c6b91df136 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sat, 13 Dec 2025 16:13:22 +0100 Subject: [PATCH] Implement pause functionality with UI and input bindings --- Assets/InputSystem_Actions.cs | 50 ++++ Assets/InputSystem_Actions.inputactions | 31 +++ Assets/Prefabs/Player.prefab | 6 +- Assets/Scenes/SampleScene.unity | 217 +++++++++++++++++- .../Infrastructure/Unity/GameBootstrap.cs | 29 +++ .../Infrastructure/Unity/RumbleManager.cs | 11 + .../Infrastructure/Unity/SoundManager.cs | 14 ++ 7 files changed, 354 insertions(+), 4 deletions(-) diff --git a/Assets/InputSystem_Actions.cs b/Assets/InputSystem_Actions.cs index bb9275c..44d831b 100644 --- a/Assets/InputSystem_Actions.cs +++ b/Assets/InputSystem_Actions.cs @@ -181,6 +181,15 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable ""processors"": """", ""interactions"": """", ""initialStateCheck"": false + }, + { + ""name"": ""Pause"", + ""type"": ""Button"", + ""id"": ""0d2f71b9-572d-45ca-8ce3-c150b120d654"", + ""expectedControlType"": """", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false } ], ""bindings"": [ @@ -590,6 +599,28 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable ""action"": ""StartGame"", ""isComposite"": false, ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""f0dd9d3e-03b2-4d73-9a5b-3c59a85c49ee"", + ""path"": ""/escape"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Pause"", + ""isComposite"": false, + ""isPartOfComposite"": false + }, + { + ""name"": """", + ""id"": ""ad5638d0-68fe-4a6c-9cd4-ca6679aa0360"", + ""path"": ""/start"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Pause"", + ""isComposite"": false, + ""isPartOfComposite"": false } ] }, @@ -1185,6 +1216,7 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable m_Player_Next = m_Player.FindAction("Next", throwIfNotFound: true); m_Player_Sprint = m_Player.FindAction("Sprint", throwIfNotFound: true); m_Player_StartGame = m_Player.FindAction("StartGame", throwIfNotFound: true); + m_Player_Pause = m_Player.FindAction("Pause", throwIfNotFound: true); // UI m_UI = asset.FindActionMap("UI", throwIfNotFound: true); m_UI_Navigate = m_UI.FindAction("Navigate", throwIfNotFound: true); @@ -1288,6 +1320,7 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable private readonly InputAction m_Player_Next; private readonly InputAction m_Player_Sprint; private readonly InputAction m_Player_StartGame; + private readonly InputAction m_Player_Pause; /// /// Provides access to input actions defined in input action map "Player". /// @@ -1340,6 +1373,10 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable /// public InputAction @StartGame => m_Wrapper.m_Player_StartGame; /// + /// Provides access to the underlying input action "Player/Pause". + /// + public InputAction @Pause => m_Wrapper.m_Player_Pause; + /// /// Provides access to the underlying input action map instance. /// public InputActionMap Get() { return m_Wrapper.m_Player; } @@ -1395,6 +1432,9 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable @StartGame.started += instance.OnStartGame; @StartGame.performed += instance.OnStartGame; @StartGame.canceled += instance.OnStartGame; + @Pause.started += instance.OnPause; + @Pause.performed += instance.OnPause; + @Pause.canceled += instance.OnPause; } /// @@ -1436,6 +1476,9 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable @StartGame.started -= instance.OnStartGame; @StartGame.performed -= instance.OnStartGame; @StartGame.canceled -= instance.OnStartGame; + @Pause.started -= instance.OnPause; + @Pause.performed -= instance.OnPause; + @Pause.canceled -= instance.OnPause; } /// @@ -1806,6 +1849,13 @@ public partial class @InputSystem_Actions: IInputActionCollection2, IDisposable /// /// void OnStartGame(InputAction.CallbackContext context); + /// + /// Method invoked when associated input action "Pause" is either , or . + /// + /// + /// + /// + void OnPause(InputAction.CallbackContext context); } /// /// Interface to implement callback methods for all input action callbacks associated with input actions defined by "UI" which allows adding and removing callbacks. diff --git a/Assets/InputSystem_Actions.inputactions b/Assets/InputSystem_Actions.inputactions index 805a218..7945010 100644 --- a/Assets/InputSystem_Actions.inputactions +++ b/Assets/InputSystem_Actions.inputactions @@ -95,6 +95,15 @@ "processors": "", "interactions": "", "initialStateCheck": false + }, + { + "name": "Pause", + "type": "Button", + "id": "0d2f71b9-572d-45ca-8ce3-c150b120d654", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false } ], "bindings": [ @@ -504,6 +513,28 @@ "action": "StartGame", "isComposite": false, "isPartOfComposite": false + }, + { + "name": "", + "id": "f0dd9d3e-03b2-4d73-9a5b-3c59a85c49ee", + "path": "/escape", + "interactions": "", + "processors": "", + "groups": "", + "action": "Pause", + "isComposite": false, + "isPartOfComposite": false + }, + { + "name": "", + "id": "ad5638d0-68fe-4a6c-9cd4-ca6679aa0360", + "path": "/start", + "interactions": "", + "processors": "", + "groups": "", + "action": "Pause", + "isComposite": false, + "isPartOfComposite": false } ] }, diff --git a/Assets/Prefabs/Player.prefab b/Assets/Prefabs/Player.prefab index 8202226..22e253f 100644 --- a/Assets/Prefabs/Player.prefab +++ b/Assets/Prefabs/Player.prefab @@ -281,8 +281,8 @@ TrailRenderer: m_RotationOrder: 4 colorGradient: serializedVersion: 2 - key0: {r: 1, g: 1, b: 1, a: 1} - key1: {r: 1, g: 1, b: 1, a: 1} + key0: {r: 0, g: 1, b: 0.9607843, a: 1} + key1: {r: 1, g: 1, b: 1, a: 0} key2: {r: 0, g: 0, b: 0, a: 0} key3: {r: 0, g: 0, b: 0, a: 0} key4: {r: 0, g: 0, b: 0, a: 0} @@ -306,7 +306,7 @@ TrailRenderer: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 + m_ColorSpace: 0 m_NumColorKeys: 2 m_NumAlphaKeys: 2 numCornerVertices: 0 diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 63a1e31..2d5a764 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -643,6 +643,7 @@ MonoBehaviour: scoreText: {fileID: 412275999} highScoreText: {fileID: 1626199842} gameOverUi: {fileID: 87831902} + pauseUi: {fileID: 1019087904} startScreenUi: {fileID: 1763855010} restartTime: 3 powerUpPrefab: {fileID: 7381336953128067686, guid: 8b540be4548e610709c2f7eccf8bf9c6, type: 3} @@ -885,7 +886,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: You have fallen. + m_text: LOSER m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} @@ -965,6 +966,82 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 907291871} m_CullTransparentMesh: 1 +--- !u!1 &1019087904 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1019087905} + - component: {fileID: 1019087907} + - component: {fileID: 1019087906} + m_Layer: 5 + m_Name: Pause + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1019087905 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1019087904} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1956141778} + m_Father: {fileID: 1580934007} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1019087906 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1019087904} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 0.14150941, g: 0.14150941, b: 0.14150941, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1019087907 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1019087904} + m_CullTransparentMesh: 1 --- !u!114 &1265730430 stripped MonoBehaviour: m_CorrespondingSourceObject: {fileID: 5807397709334561572, guid: 9870f813a82bf15d5b6ac59102c82546, type: 3} @@ -1400,6 +1477,7 @@ RectTransform: m_Children: - {fileID: 1656084056} - {fileID: 87831903} + - {fileID: 1019087905} - {fileID: 1763855011} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -1685,6 +1763,143 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1763855010} m_CullTransparentMesh: 1 +--- !u!1 &1956141777 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1956141778} + - component: {fileID: 1956141780} + - component: {fileID: 1956141779} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1956141778 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956141777} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1019087905} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 600, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1956141779 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956141777} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: PAUSE + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 1 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1956141780 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1956141777} + m_CullTransparentMesh: 1 --- !u!1001 &4539605737078215898 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs index 7533a23..817899c 100644 --- a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs +++ b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs @@ -27,6 +27,7 @@ namespace Infrastructure.Unity [SerializeField] private TMP_Text scoreText; [SerializeField] private TMP_Text highScoreText; [SerializeField] private GameObject gameOverUi; + [SerializeField] private GameObject pauseUi; [SerializeField] private GameObject startScreenUi; [Header("Settings")] @@ -46,6 +47,7 @@ namespace Infrastructure.Unity private int _currentPlayerFloorIndex; private int _currentDisplayedScore; private float _inputBlockTimer; + private bool _isPaused; private void OnEnable() { @@ -105,6 +107,13 @@ namespace Infrastructure.Unity _inputBlockTimer -= Time.deltaTime; return; } + + if (_actions.Player.Pause.triggered && _isGameRunning) + { + TogglePause(); + } + + if (_isPaused) return; if (!_isGameRunning) { @@ -149,6 +158,26 @@ namespace Infrastructure.Unity } } + private void TogglePause() + { + _isPaused = !_isPaused; + + if (_isPaused) + { + Time.timeScale = 0f; + if (soundManager) soundManager.SetPaused(true); + if (pauseUi) pauseUi.SetActive(true); + if (rumbleManager) rumbleManager.SetPaused(true); + } + else + { + Time.timeScale = 1f; + if (soundManager) soundManager.SetPaused(false); + if (pauseUi) pauseUi.SetActive(false); + if (rumbleManager) rumbleManager.SetPaused(false); + } + } + private void SpawnVisualOrb(string tileId) { if (_currentOrbInstance) Destroy(_currentOrbInstance); diff --git a/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs index 204073b..9bc5e8b 100644 --- a/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs +++ b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs @@ -33,5 +33,16 @@ namespace Infrastructure.Unity if (Gamepad.current != null) Gamepad.current.SetMotorSpeeds(0f, 0f); } + + public void SetPaused(bool isPaused) + { + if (Gamepad.current != null) + { + if (isPaused) + Gamepad.current.PauseHaptics(); + else + Gamepad.current.ResumeHaptics(); + } + } } } \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/SoundManager.cs b/Assets/Scripts/Infrastructure/Unity/SoundManager.cs index 734812a..cd39e79 100644 --- a/Assets/Scripts/Infrastructure/Unity/SoundManager.cs +++ b/Assets/Scripts/Infrastructure/Unity/SoundManager.cs @@ -66,5 +66,19 @@ namespace Infrastructure.Unity sfxSource.PlayOneShot(clip); } + + public void SetPaused(bool isPaused) + { + if (isPaused) + { + musicSource.Pause(); + } + else + { + musicSource.UnPause(); + } + + AudioListener.pause = isPaused; + } } } \ No newline at end of file