Add RumbleManager for enhanced player feedback and integrate with existing systems

This commit is contained in:
2025-12-13 00:19:09 +01:00
parent 6c15935b02
commit eb1a1b224a
8 changed files with 81 additions and 12 deletions

View File

@@ -141,7 +141,7 @@ Rigidbody:
m_UseGravity: 1 m_UseGravity: 1
m_IsKinematic: 0 m_IsKinematic: 0
m_Interpolate: 0 m_Interpolate: 0
m_Constraints: 0 m_Constraints: 112
m_CollisionDetection: 0 m_CollisionDetection: 0
--- !u!114 &4496988857626767934 --- !u!114 &4496988857626767934
MonoBehaviour: MonoBehaviour:

View File

@@ -141,7 +141,7 @@ Rigidbody:
m_UseGravity: 1 m_UseGravity: 1
m_IsKinematic: 0 m_IsKinematic: 0
m_Interpolate: 0 m_Interpolate: 0
m_Constraints: 0 m_Constraints: 112
m_CollisionDetection: 0 m_CollisionDetection: 0
--- !u!114 &6083523108754401876 --- !u!114 &6083523108754401876
MonoBehaviour: MonoBehaviour:

View File

@@ -607,6 +607,7 @@ GameObject:
- component: {fileID: 453022421} - component: {fileID: 453022421}
- component: {fileID: 453022420} - component: {fileID: 453022420}
- component: {fileID: 453022422} - component: {fileID: 453022422}
- component: {fileID: 453022423}
m_Layer: 0 m_Layer: 0
m_Name: Game m_Name: Game
m_TagString: Untagged m_TagString: Untagged
@@ -631,6 +632,7 @@ MonoBehaviour:
playerPrefab: {fileID: 2609731564308181199, guid: 6092ad6a2e82606a8a571057922b379c, type: 3} playerPrefab: {fileID: 2609731564308181199, guid: 6092ad6a2e82606a8a571057922b379c, type: 3}
deathPlanePrefab: {fileID: 6985639713120889316, guid: b25f4148dc4e46617b9f0cb6403de754, type: 3} deathPlanePrefab: {fileID: 6985639713120889316, guid: b25f4148dc4e46617b9f0cb6403de754, type: 3}
soundManager: {fileID: 1341134052} soundManager: {fileID: 1341134052}
rumbleManager: {fileID: 453022423}
cameraController: {fileID: 1265730430} cameraController: {fileID: 1265730430}
npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3} npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3}
hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3} hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3}
@@ -679,6 +681,18 @@ MonoBehaviour:
floorHeightDistance: 15 floorHeightDistance: 15
decayTime: 0.5 decayTime: 0.5
fallingTime: 2 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 --- !u!1 &832575517
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@@ -16,6 +16,7 @@ namespace Infrastructure.Unity
[SerializeField] private PlayerController playerPrefab; [SerializeField] private PlayerController playerPrefab;
[SerializeField] private DeathPlaneAdapter deathPlanePrefab; [SerializeField] private DeathPlaneAdapter deathPlanePrefab;
[SerializeField] private SoundManager soundManager; [SerializeField] private SoundManager soundManager;
[SerializeField] private RumbleManager rumbleManager;
[SerializeField] private CameraController cameraController; [SerializeField] private CameraController cameraController;
[SerializeField] private NpcController npcPrefab; [SerializeField] private NpcController npcPrefab;
[SerializeField] private HunterNpcController hunterNpcPrefab; [SerializeField] private HunterNpcController hunterNpcPrefab;
@@ -65,7 +66,7 @@ namespace Infrastructure.Unity
// Set Theme based on High Score // Set Theme based on High Score
ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore); ThemeManager.CurrentTheme = ThemeManager.GetTheme(_gameSession.HighScore);
if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews, cameraController); if (levelGenerator) levelGenerator.Generate(soundManager, _allTiles, _tileViews, cameraController, rumbleManager);
SpawnDeathPlane(); SpawnDeathPlane();
SpawnPlayer(); SpawnPlayer();
@@ -275,6 +276,9 @@ namespace Infrastructure.Unity
instance.OnCollected += (t) => instance.OnCollected += (t) =>
{ {
cameraController?.Shake(0.2f, 0.15f);
rumbleManager?.PulseMedium();
if (t == PowerUpType.TimeSlow) if (t == PowerUpType.TimeSlow)
{ {
_gameSession.ActivateTimeSlow(10f); _gameSession.ActivateTimeSlow(10f);

View File

@@ -27,19 +27,17 @@ namespace Infrastructure.Unity
private TilePool _tilePool; private TilePool _tilePool;
public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera) public void Generate(SoundManager soundManager, List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble)
{ {
_tilePool = new TilePool(tilePrefab, transform); _tilePool = new TilePool(tilePrefab, transform);
GenerateFloor(0, MapPatterns.GenerateSquare(gridSizeX, gridSizeY), 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(1, MapPatterns.GenerateDonut(gridSizeX, Mathf.FloorToInt(gridSizeX / 3f)), soundManager, allTiles, tileViews, camera); GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera, rumble);
GenerateFloor(2, MapPatterns.GenerateCircle(gridSizeX), soundManager, allTiles, tileViews, camera);
} }
private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager, private void GenerateFloor(int floorIndex, List<Vector2Int> coordinates, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera) List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble)
{ {
var yOffset = -(floorIndex * floorHeightDistance); var yOffset = -(floorIndex * floorHeightDistance);
var xOffset = gridSizeX / 2f; var xOffset = gridSizeX / 2f;
@@ -48,7 +46,7 @@ namespace Infrastructure.Unity
foreach (var coord in coordinates) foreach (var coord in coordinates)
{ {
var pos = new Vector3(coord.x - xOffset, yOffset, coord.y - zOffset); 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) if (floorIndex > 0 && jumpPadPrefab)
@@ -80,11 +78,20 @@ namespace Infrastructure.Unity
telA.Initialize(telB.transform); telA.Initialize(telB.transform);
telB.Initialize(telA.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, private void CreateTile(Vector3 position, string id, int floorIndex, SoundManager soundManager,
List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera) List<Tile> allTiles, Dictionary<string, TileViewAdapter> tileViews, CameraController camera, RumbleManager rumble)
{ {
var go = _tilePool.Get(); var go = _tilePool.Get();
go.transform.position = position; go.transform.position = position;
@@ -111,6 +118,7 @@ namespace Infrastructure.Unity
if (t.Type == TileType.Fragile) if (t.Type == TileType.Fragile)
{ {
camera?.Shake(0.1f, 0.05f); camera?.Shake(0.1f, 0.05f);
rumble?.PulseLight();
} }
if (tileBreakVfxPrefab) if (tileBreakVfxPrefab)

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a6eb2e3678564ac1b40c68e722a6469f
timeCreated: 1765581035

View File

@@ -5,6 +5,8 @@ namespace Infrastructure.Unity
{ {
public class TeleporterAdapter : MonoBehaviour public class TeleporterAdapter : MonoBehaviour
{ {
public event Action OnTeleport;
private Transform _targetDestination; private Transform _targetDestination;
private TeleporterAdapter _targetAdapter; private TeleporterAdapter _targetAdapter;
private float _cooldownTimer; private float _cooldownTimer;
@@ -45,6 +47,7 @@ namespace Infrastructure.Unity
} }
Lock(1.0f); Lock(1.0f);
OnTeleport?.Invoke();
} }
} }