diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 19c1830..ff08b20 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -608,6 +608,7 @@ GameObject: - component: {fileID: 453022420} - component: {fileID: 453022422} - component: {fileID: 453022423} + - component: {fileID: 453022424} m_Layer: 0 m_Name: Game m_TagString: Untagged @@ -633,6 +634,7 @@ MonoBehaviour: deathPlanePrefab: {fileID: 6985639713120889316, guid: b25f4148dc4e46617b9f0cb6403de754, type: 3} soundManager: {fileID: 1341134052} rumbleManager: {fileID: 453022423} + beatPulseController: {fileID: 453022424} cameraController: {fileID: 1265730430} npcPrefab: {fileID: 6083523108754401876, guid: 4b3d84858334857368bde30df360ae3e, type: 3} hunterNpcPrefab: {fileID: 4496988857626767934, guid: ab4e193839fef9a2189f27360914c044, type: 3} @@ -693,6 +695,74 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a6eb2e3678564ac1b40c68e722a6469f, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.RumbleManager +--- !u!114 &453022424 +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: e65ed2be995f4ab9b6205cbca1a6ad22, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.BeatPulseController + bpm: 90 + startDelay: 0 + OnBeat: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 453022423} + m_TargetAssemblyTypeName: Infrastructure.Unity.RumbleManager, Assembly-CSharp + m_MethodName: PulseLight + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1265730430} + m_TargetAssemblyTypeName: Infrastructure.Unity.CameraController, Assembly-CSharp + m_MethodName: ShakeLight + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + OnMeasure: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 453022423} + m_TargetAssemblyTypeName: Infrastructure.Unity.RumbleManager, Assembly-CSharp + m_MethodName: PulseHeavy + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1265730430} + m_TargetAssemblyTypeName: Infrastructure.Unity.CameraController, Assembly-CSharp + m_MethodName: ShakeMedium + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 --- !u!1 &832575517 GameObject: m_ObjectHideFlags: 0 @@ -921,7 +991,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 605a8529ba214e75baf6cc7dcd3e9527, type: 3} m_Name: m_EditorClassIdentifier: Assembly-CSharp::Infrastructure.Unity.SoundManager - bgMusicClip: {fileID: 0} + bgMusicClip: {fileID: 8300000, guid: e2affcb35757c83e499eb7d85a45b8f5, type: 3} startClip: {fileID: 0} scoreClip: {fileID: 0} gameOverClip: {fileID: 0} diff --git a/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs b/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs new file mode 100644 index 0000000..cc976ee --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs @@ -0,0 +1,66 @@ +using System; +using UnityEngine; +using UnityEngine.Events; + +namespace Infrastructure.Unity +{ + public class BeatPulseController : MonoBehaviour + { + [Header("Music Settings")] + [Tooltip("Beats Per Minute of your track")] + [SerializeField] private float bpm = 90f; + [Tooltip("Delay in seconds to sync the first beat with the music start")] + [SerializeField] private float startDelay = 0.0f; + + [Header("Events")] + public UnityEvent OnBeat; // Fires every beat (1, 2, 3, 4) + public UnityEvent OnMeasure; // Fires every 4th beat (The Drop) + + private float _beatInterval; + private float _timer; + private int _beatCount; + private bool _isRunning; + + private void Start() + { + if (bpm > 0) _beatInterval = 60f / bpm; + } + + public void BeginTracking() + { + _timer = -startDelay; + _beatCount = 0; + _isRunning = true; + } + + public void StopTracking() + { + _isRunning = false; + } + + private void Update() + { + if (!_isRunning) return; + + _timer += Time.deltaTime; + + if (_timer >= _beatInterval) + { + _timer -= _beatInterval; + Pulse(); + } + } + + private void Pulse() + { + _beatCount++; + + OnBeat?.Invoke(); + + if (_beatCount % 4 == 0) + { + OnMeasure?.Invoke(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs.meta b/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs.meta new file mode 100644 index 0000000..983f540 --- /dev/null +++ b/Assets/Scripts/Infrastructure/Unity/BeatPulseController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e65ed2be995f4ab9b6205cbca1a6ad22 +timeCreated: 1765582012 \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/CameraController.cs b/Assets/Scripts/Infrastructure/Unity/CameraController.cs index 2b46ea3..cbed255 100644 --- a/Assets/Scripts/Infrastructure/Unity/CameraController.cs +++ b/Assets/Scripts/Infrastructure/Unity/CameraController.cs @@ -46,5 +46,9 @@ namespace Infrastructure.Unity _shakeTimer = duration; _shakeMagnitude = magnitude; } + + public void ShakeLight() => Shake(.1f, .1f); + public void ShakeMedium() => Shake(.15f, .3f); + public void ShakeHeavy() => Shake(.1f, .5f); } } \ No newline at end of file diff --git a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs index f319a61..984c4ef 100644 --- a/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs +++ b/Assets/Scripts/Infrastructure/Unity/GameBootstrap.cs @@ -17,6 +17,7 @@ namespace Infrastructure.Unity [SerializeField] private DeathPlaneAdapter deathPlanePrefab; [SerializeField] private SoundManager soundManager; [SerializeField] private RumbleManager rumbleManager; + [SerializeField] private BeatPulseController beatPulseController; [SerializeField] private CameraController cameraController; [SerializeField] private NpcController npcPrefab; [SerializeField] private HunterNpcController hunterNpcPrefab; @@ -181,6 +182,9 @@ namespace Infrastructure.Unity private void HandleGameOver() { _isGameRunning = false; + + if (beatPulseController) beatPulseController.StopTracking(); + if (gameOverUi) gameOverUi.SetActive(true); StartCoroutine(RestartRoutine()); @@ -253,6 +257,8 @@ namespace Infrastructure.Unity { soundManager.PlayGameStart(); soundManager.PlayMusic(); + + if (beatPulseController) beatPulseController.BeginTracking(); } if (_playerInstance) diff --git a/Assets/Scripts/Infrastructure/Unity/TileViewAdapter.cs b/Assets/Scripts/Infrastructure/Unity/TileViewAdapter.cs index 1b497dd..8aa82f0 100644 --- a/Assets/Scripts/Infrastructure/Unity/TileViewAdapter.cs +++ b/Assets/Scripts/Infrastructure/Unity/TileViewAdapter.cs @@ -28,6 +28,7 @@ namespace Infrastructure.Unity private MaterialPropertyBlock _propBlock; private static readonly int ColorProperty = Shader.PropertyToID("_BaseColor"); + private static readonly int EmissionIntensity = Shader.PropertyToID("_EmissionIntensity"); private Action _onReturnToPool; @@ -108,6 +109,12 @@ namespace Infrastructure.Unity _linkedTile?.StepOn(); } + public void PulseEmission(float intensity) + { + StartCoroutine(PulseEmissionRoutine(intensity, 0.2f)); + StartCoroutine(PulseScaleRoutine()); + } + private void SetColor(Color color) { meshRenderer.GetPropertyBlock(_propBlock); @@ -157,5 +164,26 @@ namespace Infrastructure.Unity _linkedTile.OnStateChanged -= OnTileStateChanged; } } + + private IEnumerator PulseScaleRoutine() + { + var original = transform.localScale; + transform.localScale = original * 1.05f; + yield return new WaitForSeconds(0.1f); + transform.localScale = original; + } + + private IEnumerator PulseEmissionRoutine(float intensity, float duration) + { + meshRenderer.GetPropertyBlock(_propBlock); + var originalIntensity = _propBlock.GetFloat(EmissionIntensity); + _propBlock.SetFloat(EmissionIntensity, intensity); + meshRenderer.SetPropertyBlock(_propBlock); + + yield return new WaitForSeconds(duration); + + _propBlock.SetFloat(EmissionIntensity, originalIntensity); + meshRenderer.SetPropertyBlock(_propBlock); + } } } \ No newline at end of file diff --git a/Assets/Sfxs.meta b/Assets/Sfxs.meta new file mode 100644 index 0000000..85e1a17 --- /dev/null +++ b/Assets/Sfxs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c687722413b924cc9815514c01e02524 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sfxs/BackgroundMusic.mp3 b/Assets/Sfxs/BackgroundMusic.mp3 new file mode 100644 index 0000000..cc4dbcc Binary files /dev/null and b/Assets/Sfxs/BackgroundMusic.mp3 differ diff --git a/Assets/Sfxs/BackgroundMusic.mp3.meta b/Assets/Sfxs/BackgroundMusic.mp3.meta new file mode 100644 index 0000000..249b384 --- /dev/null +++ b/Assets/Sfxs/BackgroundMusic.mp3.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: e2affcb35757c83e499eb7d85a45b8f5 +AudioImporter: + externalObjects: {} + serializedVersion: 8 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: