diff --git a/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset b/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset index cfcc419..e969989 100644 --- a/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset +++ b/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset @@ -27,7 +27,7 @@ MonoBehaviour: GroundedOnly: 0 Damage: 5 Range: 10 - AttacksPerSecond: 1.5 + AttacksPerSecond: 2 SplashRadius: 0 ChainCount: 0 ChainRange: 0 diff --git a/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab b/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab index cff0c5b..959f827 100644 --- a/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab +++ b/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab @@ -99,6 +99,7 @@ GameObject: - component: {fileID: 805962841523123163} - component: {fileID: 8853488620519990682} - component: {fileID: 4524938955752569428} + - component: {fileID: 42814861218671054} - component: {fileID: -2590971686077483651} m_Layer: 0 m_Name: Tower_TeslaCoil @@ -146,7 +147,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject - GlobalObjectIdHash: 1363936954 + GlobalObjectIdHash: 280718094 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 1 @@ -223,6 +224,103 @@ MonoBehaviour: arcDuration: 0.12 segmentsPerArc: 6 jitter: 0.2 +--- !u!82 &42814861218671054 +AudioSource: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6482414459531823157} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 0} + m_Resource: {fileID: 0} + m_PlayOnAwake: 0 + m_Volume: 0.5 + m_Pitch: 1 + Loop: 0 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 --- !u!114 &-2590971686077483651 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/_Project/Scenes/Levels/9Player.unity b/Assets/_Project/Scenes/Levels/9Player.unity index ad268e9..32942ce 100644 --- a/Assets/_Project/Scenes/Levels/9Player.unity +++ b/Assets/_Project/Scenes/Levels/9Player.unity @@ -2222,63 +2222,6 @@ Transform: m_Children: [] m_Father: {fileID: 1097152085} m_LocalEulerAnglesHint: {x: 0, y: 90, z: 0} ---- !u!1 &176580460 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 176580462} - - component: {fileID: 176580461} - m_Layer: 0 - m_Name: AudioManager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &176580461 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 176580460} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9ec21c01769ef58d1ac26ba89668eeaa, type: 3} - m_Name: - m_EditorClassIdentifier: Assembly-CSharp::TD.Audio.AudioManager - categories: - - category: 0 - maxVoices: 4 - volume: 0.5 - - category: 1 - maxVoices: 4 - volume: 0.5 - - category: 2 - maxVoices: 4 - volume: 0.5 - - category: 3 - maxVoices: 4 - volume: 0.5 ---- !u!4 &176580462 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 176580460} - serializedVersion: 2 - 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: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!43 &203092944 Mesh: m_ObjectHideFlags: 0 @@ -28771,4 +28714,3 @@ SceneRoots: - {fileID: 1097152085} - {fileID: 1889390964} - {fileID: 2139601601} - - {fileID: 176580462} diff --git a/Assets/_Project/Scripts/Audio.meta b/Assets/_Project/Scripts/Audio.meta deleted file mode 100644 index d399f53..0000000 --- a/Assets/_Project/Scripts/Audio.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d11cb1aeddfee3009879738a45665945 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/_Project/Scripts/Audio/AudioCategory.cs b/Assets/_Project/Scripts/Audio/AudioCategory.cs deleted file mode 100644 index ef63198..0000000 --- a/Assets/_Project/Scripts/Audio/AudioCategory.cs +++ /dev/null @@ -1,5 +0,0 @@ -// Assets/_Project/Scripts/Audio/AudioCategory.cs -namespace TD.Audio -{ - public enum AudioCategory { TowerFire, EnemyHitDeath, UI, Music } -} diff --git a/Assets/_Project/Scripts/Audio/AudioCategory.cs.meta b/Assets/_Project/Scripts/Audio/AudioCategory.cs.meta deleted file mode 100644 index 3947300..0000000 --- a/Assets/_Project/Scripts/Audio/AudioCategory.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 2f652b06e3d150798895893892820cc7 \ No newline at end of file diff --git a/Assets/_Project/Scripts/Audio/AudioManager.cs b/Assets/_Project/Scripts/Audio/AudioManager.cs deleted file mode 100644 index 961a820..0000000 --- a/Assets/_Project/Scripts/Audio/AudioManager.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Assets/_Project/Scripts/Audio/AudioManager.cs -using System.Collections.Generic; -using UnityEngine; - -namespace TD.Audio -{ - public class AudioManager : MonoBehaviour - { - [System.Serializable] - public struct CategoryConfig - { - public AudioCategory category; - public int maxVoices; - [Range(0f, 1f)] - public float volume; - } - - public static AudioManager Instance { get; private set; } - - [SerializeField] private CategoryConfig[] categories; - - private Dictionary pools; - private Dictionary indices; - - private void Awake() - { - if (Instance != null) - { - Destroy(gameObject); - return; - } - Instance = this; - InitializePools(); - } - - private void OnDestroy() - { - if (Instance == this) Instance = null; - } - - private void InitializePools() - { - pools = new Dictionary(); - indices = new Dictionary(); - - foreach (var config in categories) - { - var pool = new AudioSource[config.maxVoices]; - for (int i = 0; i < config.maxVoices; i++) - { - var src = gameObject.AddComponent(); - src.playOnAwake = false; - src.volume = config.volume; - pool[i] = src; - } - pools[config.category] = pool; - indices[config.category] = 0; - } - } - - public void Play(AudioClip clip, AudioCategory category, float pitch = 1f) - { - if (clip == null) return; - if (!pools.TryGetValue(category, out var pool)) return; - - int idx = indices[category]; - var src = pool[idx % pool.Length]; - src.pitch = pitch; - src.clip = clip; - src.Play(); - indices[category] = idx + 1; - } - } -} diff --git a/Assets/_Project/Scripts/Audio/AudioManager.cs.meta b/Assets/_Project/Scripts/Audio/AudioManager.cs.meta deleted file mode 100644 index 855be40..0000000 --- a/Assets/_Project/Scripts/Audio/AudioManager.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 9ec21c01769ef58d1ac26ba89668eeaa \ No newline at end of file diff --git a/Assets/_Project/Scripts/Audio/README.md b/Assets/_Project/Scripts/Audio/README.md deleted file mode 100644 index 2f7d81c..0000000 --- a/Assets/_Project/Scripts/Audio/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Audio System - -Centralised voice-limited audio for the game. Lives in `Assets/_Project/Scripts/Audio/`. - -## How it works - -`AudioManager` is a per-scene MonoBehaviour singleton. On `Awake` it pre-allocates a pool of `AudioSource` components (on its own GameObject) for each sound category. Callers request playback via `AudioManager.Instance.Play(clip, category, pitch)` — the manager picks the next source in that category's pool using round-robin, interrupting the oldest sound if all voices are busy. - -## Categories (`AudioCategory` enum) - -| Category | Typical use | -|---|---| -| `TowerFire` | Tower attack sounds | -| `EnemyHitDeath` | Enemy damage and death sounds | -| `UI` | Button clicks, placement confirmation, etc. | -| `Music` | Background music | - -Voice limits and volume per category are configured in the Inspector on the `AudioManager` scene GameObject. - -## Scene setup - -An empty GameObject named `AudioManager` must exist in each gameplay scene with the `AudioManager` component attached. Configure the `Categories` array in the Inspector — one entry per `AudioCategory` value. - -Suggested defaults: -- TowerFire: 4 voices, volume 1.0 -- EnemyHitDeath: 8 voices, volume 1.0 -- UI: 4 voices, volume 1.0 -- Music: 2 voices, volume 0.8 - -## Adding a new sound-emitting component - -1. Get a reference to an `AudioClip` via `[SerializeField]` -2. Call `AudioManager.Instance?.Play(clip, AudioCategory.YourCategory)` at the point the sound should trigger -3. Pitch randomization (if desired) is the caller's responsibility: `Random.Range(minPitch, maxPitch)` passed as the third argument - -See `TeslaTowerFireSound.cs` in `Scripts/Combat/` as a reference implementation. diff --git a/Assets/_Project/Scripts/Audio/README.md.meta b/Assets/_Project/Scripts/Audio/README.md.meta deleted file mode 100644 index 284147a..0000000 --- a/Assets/_Project/Scripts/Audio/README.md.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4acf87ebbb79a6ce482e6e4767d27b41 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/_Project/Scripts/Combat/TeslaTowerFireSound.cs b/Assets/_Project/Scripts/Combat/TeslaTowerFireSound.cs index 9294b85..69de453 100644 --- a/Assets/_Project/Scripts/Combat/TeslaTowerFireSound.cs +++ b/Assets/_Project/Scripts/Combat/TeslaTowerFireSound.cs @@ -1,5 +1,4 @@ // Assets/_Project/Scripts/Combat/TeslaTowerFireSound.cs -using TD.Audio; using UnityEngine; namespace TD.Combat @@ -15,6 +14,7 @@ namespace TD.Combat /// as the Tesla Coil gains more audio (idle hum, charge-up, etc.). /// [RequireComponent(typeof(TowerCombat))] + [RequireComponent(typeof(AudioSource))] public class TeslaTowerFireSound : MonoBehaviour { [Tooltip("Sound played each time the coil discharges.")] @@ -25,10 +25,12 @@ namespace TD.Combat [SerializeField] private float maxPitch = 1.07f; private TowerCombat combat; + private AudioSource audioSource; private void Awake() { - combat = GetComponent(); + combat = GetComponent(); + audioSource = GetComponent(); } private void OnEnable() @@ -43,7 +45,12 @@ namespace TD.Combat private void HandleAreaFired(Vector3[] positions) { - AudioManager.Instance?.Play(fireClip, AudioCategory.TowerFire, Random.Range(minPitch, maxPitch)); + if (fireClip != null) + { + audioSource.pitch = Random.Range(minPitch, maxPitch); + audioSource.clip = fireClip; + audioSource.Play(); + } } } }