From eb1a1b224a84051b7f36c32314cde34daef44414 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sat, 13 Dec 2025 00:19:09 +0100 Subject: [PATCH] Add RumbleManager for enhanced player feedback and integrate with existing systems --- Assets/Prefabs/HunterNpc.prefab | 2 +- Assets/Prefabs/Npc.prefab | 2 +- Assets/Scenes/SampleScene.unity | 14 +++++++ .../Infrastructure/Unity/GameBootstrap.cs | 6 ++- .../Infrastructure/Unity/LevelGenerator.cs | 26 ++++++++----- .../Infrastructure/Unity/RumbleManager.cs | 37 +++++++++++++++++++ .../Unity/RumbleManager.cs.meta | 3 ++ .../Infrastructure/Unity/TeleporterAdapter.cs | 3 ++ 8 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 Assets/Scripts/Infrastructure/Unity/RumbleManager.cs create mode 100644 Assets/Scripts/Infrastructure/Unity/RumbleManager.cs.meta diff --git a/Assets/Prefabs/HunterNpc.prefab b/Assets/Prefabs/HunterNpc.prefab index 439737e..c0ecefe 100644 --- a/Assets/Prefabs/HunterNpc.prefab +++ b/Assets/Prefabs/HunterNpc.prefab @@ -141,7 +141,7 @@ Rigidbody: m_UseGravity: 1 m_IsKinematic: 0 m_Interpolate: 0 - m_Constraints: 0 + m_Constraints: 112 m_CollisionDetection: 0 --- !u!114 &4496988857626767934 MonoBehaviour: diff --git a/Assets/Prefabs/Npc.prefab b/Assets/Prefabs/Npc.prefab index dbfd2ed..99327df 100644 --- a/Assets/Prefabs/Npc.prefab +++ b/Assets/Prefabs/Npc.prefab @@ -141,7 +141,7 @@ Rigidbody: m_UseGravity: 1 m_IsKinematic: 0 m_Interpolate: 0 - m_Constraints: 0 + m_Constraints: 112 m_CollisionDetection: 0 --- !u!114 &6083523108754401876 MonoBehaviour: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 459f669..19c1830 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -607,6 +607,7 @@ GameObject: - component: {fileID: 453022421} - component: {fileID: 453022420} - component: {fileID: 453022422} + - component: {fileID: 453022423} m_Layer: 0 m_Name: Game m_TagString: Untagged @@ -631,6 +632,7 @@ MonoBehaviour: playerPrefab: {fileID: 2609731564308181199, guid: 6092ad6a2e82606a8a571057922b379c, type: 3} deathPlanePrefab: {fileID: 6985639713120889316, guid: b25f4148dc4e46617b9f0cb6403de754, type: 3} soundManager: {fileID: 1341134052} + rumbleManager: {fileID: 453022423} cameraController: {fileID: 1265730430} npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3} hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3} @@ -679,6 +681,18 @@ MonoBehaviour: floorHeightDistance: 15 decayTime: 0.5 fallingTime: 2 +--- !u!114 &453022423 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 453022419} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a6eb2e3678564ac1b40c68e722a6469f, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.RumbleManager --- !u!1 &832575517 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs index 7df909e..f319a61 100644 --- a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs +++ b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs @@ -16,6 +16,7 @@ namespace Infrastructure.Unity [SerializeField] private PlayerController playerPrefab; [SerializeField] private DeathPlaneAdapter deathPlanePrefab; [SerializeField] private SoundManager soundManager; + [SerializeField] private RumbleManager rumbleManager; [SerializeField] private CameraController cameraController; [SerializeField] private NpcController npcPrefab; [SerializeField] private HunterNpcController hunterNpcPrefab; @@ -65,7 +66,7 @@ namespace Infrastructure.Unity // Set Theme based on High Score ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore); - if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews, cameraController); + if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews, cameraController, rumbleManager); SpawnDeathPlane(); SpawnPlayer(); @@ -275,6 +276,9 @@ namespace Infrastructure.Unity instance.OnCollected += (t) => { + cameraController?.Shake(0.2f, 0.15f); + rumbleManager?.PulseMedium(); + if (t == PowerUpType.TimeSlow) { _gameSession.ActivateTimeSlow(10f); diff --git a/Assets/Scripts/Infrastructure/Unity/LevelGenerator.cs b/Assets/Scripts/Infrastructure/Unity/LevelGenerator.cs index 5faed9f..e857265 100644 --- a/Assets/Scripts/Infrastructure/Unity/LevelGenerator.cs +++ b/Assets/Scripts/Infrastructure/Unity/LevelGenerator.cs @@ -27,19 +27,17 @@ namespace Infrastructure.Unity private TilePool _tilePool; - public void Generate(SoundManager soundManager, List allTiles, Dictionary tileViews, CameraController camera) + public void Generate(SoundManager soundManager, List allTiles, Dictionary tileViews, CameraController camera, RumbleManager rumble) { _tilePool = new TilePool(tilePrefab, transform); - GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews, camera); - - GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera); - - GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera); + GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), soundManager, allTiles, tileViews, camera, rumble); + GenerateFloor(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera, rumble); + GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera, rumble); } private void GenerateFloor(int floorIndex, List coordinates, SoundManager soundManager, - List allTiles, Dictionary tileViews, CameraController camera) + List allTiles, Dictionary tileViews, CameraController camera, RumbleManager rumble) { var yOffset = -(floorIndex * floorHeightDistance); var xOffset = gridSizeX / 2f; @@ -48,7 +46,7 @@ namespace Infrastructure.Unity foreach (var coord in coordinates) { var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset); - CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews, camera); + CreateTile(pos, $"{floorIndex}_{coord.x}_{coord.y}", floorIndex, soundManager, allTiles, tileViews, camera, rumble); } if (floorIndex > 0 && jumpPadPrefab) @@ -80,11 +78,20 @@ namespace Infrastructure.Unity telA.Initialize(telB.transform); telB.Initialize(telA.transform); + + System.Action onTeleport = () => + { + camera?.Shake(0.2f, 0.2f); + rumble?.PulseMedium(); + }; + + telA.OnTeleport += onTeleport; + telB.OnTeleport += onTeleport; } } private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager, - List allTiles, Dictionary tileViews, CameraController camera) + List allTiles, Dictionary tileViews, CameraController camera, RumbleManager rumble) { var go = _tilePool.Get(); go.transform.position = position; @@ -111,6 +118,7 @@ namespace Infrastructure.Unity if (t.Type == TileType.Fragile) { camera?.Shake(0.1f, 0.05f); + rumble?.PulseLight(); } if (tileBreakVfxPrefab) diff --git a/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs new file mode 100644 index 0000000..204073b --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs @@ -0,0 +1,37 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.InputSystem; + +namespace Infrastructure.Unity +{ + public class RumbleManager : MonoBehaviour + { + private Coroutine _rumbleCoroutine; + + public void Pulse(float lowFrequency, float highFrequency, float duration) + { + if (Gamepad.current == null) return; + + if (_rumbleCoroutine != null) StopCoroutine(_rumbleCoroutine); + + _rumbleCoroutine = StartCoroutine(RumbleRoutine(lowFrequency, highFrequency, duration)); + } + + public void PulseLight() => Pulse(0.1f, 0.2f, 0.1f); + public void PulseMedium() => Pulse(0.4f, 0.5f, 0.2f); + public void PulseHeavy() => Pulse(0.8f, 1.0f, 0.3f); + + private IEnumerator RumbleRoutine(float low, float high, float duration) + { + Gamepad.current.SetMotorSpeeds(low, high); + yield return new WaitForSeconds(duration); + Gamepad.current.SetMotorSpeeds(0f, 0f); + } + + private void OnDisable() + { + if (Gamepad.current != null) + Gamepad.current.SetMotorSpeeds(0f, 0f); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs.meta b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs.meta new file mode 100644 index 0000000..140ee2e --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/RumbleManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a6eb2e3678564ac1b40c68e722a6469f +timeCreated: 1765581035 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs b/Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs index 8e3dbea..56280b9 100644 --- a/Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs +++ b/Assets/Scripts/Infrastructure/Unity/TeleporterAdapter.cs @@ -5,6 +5,8 @@ namespace Infrastructure.Unity { public class TeleporterAdapter : MonoBehaviour { + public event Action OnTeleport; + private Transform _targetDestination; private TeleporterAdapter _targetAdapter; private float _cooldownTimer; @@ -45,6 +47,7 @@ namespace Infrastructure.Unity } Lock(1.0f); + OnTeleport?.Invoke(); } }