diff --git a/Assets/_Project/Art/Materials/M_Electrical_Glow.mat b/Assets/_Project/Art/Materials/M_Electrical_Glow.mat index 558d2db..1dd11fe 100644 --- a/Assets/_Project/Art/Materials/M_Electrical_Glow.mat +++ b/Assets/_Project/Art/Materials/M_Electrical_Glow.mat @@ -105,7 +105,7 @@ Material: - _AddPrecomputedVelocity: 0 - _AlphaClip: 0 - _AlphaToMask: 0 - - _Blend: 2 + - _Blend: 0 - _BlendModePreserveSpecular: 1 - _BumpScale: 1 - _ClearCoatMask: 0 @@ -114,8 +114,8 @@ Material: - _Cutoff: 0.5 - _DetailAlbedoMapScale: 1 - _DetailNormalMapScale: 1 - - _DstBlend: 1 - - _DstBlendAlpha: 1 + - _DstBlend: 10 + - _DstBlendAlpha: 10 - _EnvironmentReflections: 1 - _GlossMapScale: 0 - _Glossiness: 0 diff --git a/Assets/_Project/Definitions/Towers/BasicArrowTower.asset b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset index 3a1c5c4..7709fe3 100644 --- a/Assets/_Project/Definitions/Towers/BasicArrowTower.asset +++ b/Assets/_Project/Definitions/Towers/BasicArrowTower.asset @@ -25,7 +25,7 @@ MonoBehaviour: GroundedOnly: 0 Damage: 10 Range: 20 - AttacksPerSecond: 5 + FireRate: 5 SplashRadius: 0 ChainCount: 0 ChainRange: 0 diff --git a/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset index 7a6ead6..f8b6521 100644 --- a/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset +++ b/Assets/_Project/Definitions/Towers/SiegeCannonTower.asset @@ -27,7 +27,7 @@ MonoBehaviour: GroundedOnly: 1 Damage: 25 Range: 16 - AttacksPerSecond: 0.8 + AttacksPerSecond: 0 SplashRadius: 3 ChainCount: 0 ChainRange: 0 diff --git a/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset b/Assets/_Project/Definitions/Towers/TeslaCoilTower.asset index aa5b2b6..c122a53 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: 0 SplashRadius: 0 ChainCount: 0 ChainRange: 0 diff --git a/Assets/_Project/Definitions/Towers/Wall.asset b/Assets/_Project/Definitions/Towers/Wall.asset index ead40ed..8ee63b7 100644 --- a/Assets/_Project/Definitions/Towers/Wall.asset +++ b/Assets/_Project/Definitions/Towers/Wall.asset @@ -24,7 +24,7 @@ MonoBehaviour: GroundedOnly: 0 Damage: 0 Range: 0 - AttacksPerSecond: 0 + FireRate: 0 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..76b7f7f 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 @@ -12283,6 +12226,55 @@ Mesh: - serializedVersion: 1 m_IndexStart: 0 m_IndexCount: 0 +--- !u!1 &832575517 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 832575519} + - component: {fileID: 832575518} + m_Layer: 0 + m_Name: Global Volume + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &832575518 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IsGlobal: 1 + priority: 0 + blendDistance: 0 + weight: 1 + sharedProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2} +--- !u!4 &832575519 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 832575517} + 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!1 &839198900 GameObject: m_ObjectHideFlags: 0 @@ -28753,6 +28745,7 @@ SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 410087041} + - {fileID: 832575519} - {fileID: 441239881} - {fileID: 167151709} - {fileID: 1507514109} @@ -28771,4 +28764,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/TeslaArcVisual.cs b/Assets/_Project/Scripts/Combat/TeslaArcVisual.cs index c4e7828..20de293 100644 --- a/Assets/_Project/Scripts/Combat/TeslaArcVisual.cs +++ b/Assets/_Project/Scripts/Combat/TeslaArcVisual.cs @@ -6,92 +6,35 @@ namespace TD.Combat { /// /// Local-only electrical-arc visual for - /// towers (Tesla Coil). Subscribes to and draws an - /// arced, jittering bolt from the tower's emitter to every enemy hit, re-randomized each - /// frame so it crackles, then hidden after a short flash. + /// towers (Tesla Coil). Subscribes to and draws a + /// jagged line from the tower's emitter point to every enemy hit, flashed for a moment. /// /// /// Pure visualization — runs on every peer from the replicated fire broadcast; nothing - /// here is networked. Bolts are pooled s reused across ticks. - /// The glow (bloom) comes from the material + an HDR color above the bloom threshold; see - /// and the project's post-processing Volume. + /// here is networked. Arcs are pooled s reused across ticks. /// [RequireComponent(typeof(TowerCombat))] public class TeslaArcVisual : MonoBehaviour { - [Tooltip("Point the bolts originate from — the central top of the coil. " + + [Tooltip("Point the arcs originate from — the central top of the coil. " + "If unset, falls back to one unit above the tower root.")] [SerializeField] private Transform emitter; - [Tooltip("Material for the bolts. Use an UNLIT ADDITIVE material for a convincing " + - "glow (a Lit material won't bloom well on a thin line). If unset, a fallback " + - "additive material is created at runtime.")] + [Tooltip("Material for the arc lines. Assign an unlit/additive material for a glow. " + + "If unset, a fallback Sprites/Default material is created at runtime.")] [SerializeField] private Material arcMaterial; - [Tooltip("Base bolt color. Multiplied by Emission Intensity to push it into HDR so " + - "Bloom picks it up.")] - [ColorUsage(true, true)] - [SerializeField] private Color arcColor = new Color(0.55f, 0.8f, 1f, 1f); - - [Tooltip("HDR multiplier on the color. Must exceed the Bloom threshold (>1) for the " + - "bolt to glow. Raise for a hotter, brighter arc.")] - [SerializeField] private float emissionIntensity = 4f; - + [SerializeField] private Color arcColor = new Color(0.6f, 0.85f, 1f, 1f); [SerializeField] private float arcWidth = 0.06f; - - [Tooltip("How long each flash stays visible, in seconds.")] + [Tooltip("How long each arc flash stays visible, in seconds.")] [SerializeField] private float arcDuration = 0.12f; - - [Tooltip("Points per bolt. More = smoother arc and finer crackle. ~12-20 looks good.")] - [SerializeField] private int segmentsPerArc = 16; - - [Tooltip("Overall arc/bow as a fraction of bolt length (0 = straight line). The bolt " + - "lifts toward the middle for an electrical-arc curve.")] - [SerializeField] private float arcHeight = 0.18f; - - [Tooltip("Random crackle displacement (world units) at the middle of the bolt, " + - "tapering to 0 at both ends so it stays anchored to the coil and enemy.")] - [SerializeField] private float jitter = 0.18f; - - [Header("Light flash")] - [Tooltip("Pulse a real point light at the emitter when firing so the bolts actually " + - "illuminate nearby enemies (emission/bloom alone don't cast light).")] - [SerializeField] private bool castLight = true; - - [Tooltip("Color of the flash light.")] - [SerializeField] private Color lightColor = new Color(0.6f, 0.85f, 1f); - - [Tooltip("Peak intensity of the flash. The light flickers between this and ~70% of " + - "it while firing for an electrical pulse.")] - [SerializeField] private float lightIntensity = 8f; - - [Tooltip("Range of the emitter flash light — covers enemies near the coil.")] - [SerializeField] private float lightRange = 12f; - - [Tooltip("Also flash a small light at each bolt's IMPACT point, so enemies struck at " + - "the far edge of range get lit by the bolt — not just those near the coil.")] - [SerializeField] private bool castImpactLight = true; - - [Tooltip("Peak intensity of each impact light (usually lower than the emitter flash).")] - [SerializeField] private float impactLightIntensity = 4f; - - [Tooltip("Range of each impact light — only needs to cover the struck enemy, so keep it small.")] - [SerializeField] private float impactLightRange = 5f; - - [Tooltip("Performance cap on simultaneous impact lights. URP limits how many lights " + - "affect each object, and many towers add up — targets beyond this cap rely on " + - "the emitter flash. Raise carefully.")] - [SerializeField] private int maxImpactLights = 8; + [Tooltip("Number of points per arc. More = more jagged detail.")] + [SerializeField] private int segmentsPerArc = 6; + [Tooltip("Random offset applied to interior arc points for the lightning look.")] + [SerializeField] private float jitter = 0.2f; private TowerCombat combat; private readonly List pool = new List(); - private Light flashLight; - private readonly List impactLightPool = new List(); - - // Snapshot of the current flash so Update can re-randomize the bolts each frame. - private Vector3[] activeTargets; - private int activeCount; - private bool active; private float hideAt = -1f; private void Awake() => combat = GetComponent(); @@ -108,120 +51,31 @@ namespace TD.Combat private void Update() { - if (!active) return; - - if (Time.time >= hideAt) + if (hideAt >= 0f && Time.time >= hideAt) { - HideAll(); - active = false; - return; + for (int i = 0; i < pool.Count; i++) pool[i].enabled = false; + hideAt = -1f; } - - // Re-draw every frame with fresh jitter so the bolts crackle while visible. - RedrawBolts(); } private void HandleAreaFired(Vector3[] positions) { - if (positions == null || positions.Length == 0) return; + if (positions == null) return; - activeTargets = positions; // RPC hands us a fresh array each call — safe to keep - activeCount = positions.Length; - active = true; - hideAt = Time.time + arcDuration; - - RedrawBolts(); - } - - private void RedrawBolts() - { Vector3 origin = emitter != null ? emitter.position : transform.position + Vector3.up; - for (int i = 0; i < activeCount; i++) + for (int i = 0; i < positions.Length; i++) { var lr = GetLine(i); - DrawBolt(lr, origin, activeTargets[i]); + DrawArc(lr, origin, positions[i]); lr.enabled = true; } - // Disable any leftover bolts from a previous, larger tick. - for (int i = activeCount; i < pool.Count; i++) + // Disable any leftover lines from a previous, larger tick. + for (int i = positions.Length; i < pool.Count; i++) pool[i].enabled = false; - // Pulse the emitter light so the coil/source lights nearby enemies. - if (castLight) - { - var fl = GetFlashLight(); - fl.intensity = lightIntensity * Random.Range(0.7f, 1f); // electrical flicker - fl.enabled = true; - } - - // Pulse a light at each bolt's impact point so far-struck enemies get lit by the - // bolt itself. Capped for performance; extra targets rely on the emitter flash. - if (castImpactLight) - { - int lit = Mathf.Min(activeCount, maxImpactLights); - for (int i = 0; i < lit; i++) - { - var il = GetImpactLight(i); - il.transform.position = activeTargets[i]; - il.intensity = impactLightIntensity * Random.Range(0.7f, 1f); - il.enabled = true; - } - for (int i = lit; i < impactLightPool.Count; i++) - impactLightPool[i].enabled = false; - } - } - - private void HideAll() - { - for (int i = 0; i < pool.Count; i++) - pool[i].enabled = false; - - if (flashLight != null) flashLight.enabled = false; - for (int i = 0; i < impactLightPool.Count; i++) - impactLightPool[i].enabled = false; - } - - // Lazily creates a small world-space point light for a bolt's impact point. - private Light GetImpactLight(int index) - { - while (impactLightPool.Count <= index) - { - var go = new GameObject($"ArcImpactLight_{impactLightPool.Count}"); - go.transform.SetParent(transform, worldPositionStays: true); - - var l = go.AddComponent(); - l.type = LightType.Point; - l.color = lightColor; - l.range = impactLightRange; - l.shadows = LightShadows.None; - l.intensity = 0f; - l.enabled = false; - impactLightPool.Add(l); - } - return impactLightPool[index]; - } - - // Lazily creates the point light at the emitter (parented so it tracks the coil). - private Light GetFlashLight() - { - if (flashLight == null) - { - var go = new GameObject("ArcFlashLight"); - Transform parent = emitter != null ? emitter : transform; - go.transform.SetParent(parent, worldPositionStays: false); - go.transform.localPosition = Vector3.zero; - - flashLight = go.AddComponent(); - flashLight.type = LightType.Point; - flashLight.color = lightColor; - flashLight.range = lightRange; - flashLight.shadows = LightShadows.None; // perf: brief flashes don't need shadows - flashLight.intensity = 0f; - flashLight.enabled = false; - } - return flashLight; + hideAt = Time.time + arcDuration; } private LineRenderer GetLine(int index) @@ -230,74 +84,33 @@ namespace TD.Combat { var go = new GameObject($"Arc_{pool.Count}"); go.transform.SetParent(transform, worldPositionStays: false); - var lr = go.AddComponent(); - lr.useWorldSpace = true; - lr.widthMultiplier = arcWidth; - lr.numCapVertices = 4; - lr.numCornerVertices = 4; - lr.alignment = LineAlignment.View; // face the camera, like a billboard - lr.textureMode = LineTextureMode.Stretch; + lr.useWorldSpace = true; + lr.widthMultiplier = arcWidth; + lr.numCapVertices = 2; + lr.textureMode = LineTextureMode.Stretch; lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; - lr.material = arcMaterial != null ? arcMaterial : CreateFallbackMaterial(); - - // HDR color so Bloom in the post stack picks the bolt up as a glow. - Color hdr = arcColor * Mathf.Max(1f, emissionIntensity); - hdr.a = 1f; - lr.startColor = lr.endColor = hdr; - - lr.enabled = false; + lr.material = arcMaterial != null + ? arcMaterial + : new Material(Shader.Find("Sprites/Default")); + lr.startColor = lr.endColor = arcColor; + lr.enabled = false; pool.Add(lr); } return pool[index]; } - // Additive unlit fallback so bolts still glow if no material is assigned. Prefer - // assigning a real material in the inspector. - private static Material CreateFallbackMaterial() - { - var shader = Shader.Find("Universal Render Pipeline/Particles/Unlit") - ?? Shader.Find("Sprites/Default"); - return new Material(shader); - } - - // Builds an arced, jagged bolt from a to b. A smooth sine bow gives the overall arc; - // tapered random perpendicular offsets give the electrical crackle. Endpoints stay - // exactly on the coil and the enemy. - private void DrawBolt(LineRenderer lr, Vector3 a, Vector3 b) + private void DrawArc(LineRenderer lr, Vector3 a, Vector3 b) { int n = Mathf.Max(2, segmentsPerArc); lr.positionCount = n; - - Vector3 delta = b - a; - float len = delta.magnitude; - Vector3 dir = len > 1e-4f ? delta / len : Vector3.forward; - - // Bow toward world-up, projected perpendicular to the bolt (any perpendicular for - // near-vertical bolts), plus a sideways axis for 3D crackle. - Vector3 bowDir = Vector3.up - dir * Vector3.Dot(Vector3.up, dir); - if (bowDir.sqrMagnitude < 1e-4f) bowDir = Vector3.Cross(dir, Vector3.right); - bowDir.Normalize(); - Vector3 sideDir = Vector3.Cross(dir, bowDir); - - float bow = arcHeight * len; - for (int s = 0; s < n; s++) { float t = s / (float)(n - 1); - Vector3 p = a + delta * t; - - // Smooth arc — sine peaks at the middle, zero at both ends. - float curve = Mathf.Sin(t * Mathf.PI); - p += bowDir * (bow * curve); - - // Crackle on interior points, tapered to nothing at the ends. + Vector3 p = Vector3.Lerp(a, b, t); + // Jitter interior points only — endpoints stay anchored to the coil and enemy. if (s != 0 && s != n - 1) - { - p += bowDir * (Random.Range(-jitter, jitter) * curve); - p += sideDir * (Random.Range(-jitter, jitter) * curve); - } - + p += Random.insideUnitSphere * jitter; lr.SetPosition(s, p); } } 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(); + } } } } diff --git a/Assets/_Project/Scripts/Combat/TowerCombat.cs b/Assets/_Project/Scripts/Combat/TowerCombat.cs index 9c9ac7c..657d5f8 100644 --- a/Assets/_Project/Scripts/Combat/TowerCombat.cs +++ b/Assets/_Project/Scripts/Combat/TowerCombat.cs @@ -473,6 +473,8 @@ namespace TD.Combat { var multiplier = GetOwnerBuffManager()?.GetMultiplier(BuffStat.Damage) ?? 1f; float effectiveDamage = p.Damage * multiplier; + Debug.Log("multiplier: " + multiplier); + Debug.Log("Effective damage: " + effectiveDamage); target.TakeDamage(effectiveDamage, p.DamageType, owner); ApplyStatusEffect(p, target, owner); } diff --git a/Assets/_Project/Settings/DefaultVolumeProfile.asset b/Assets/_Project/Settings/DefaultVolumeProfile.asset index 1c6d468..66d98de 100644 --- a/Assets/_Project/Settings/DefaultVolumeProfile.asset +++ b/Assets/_Project/Settings/DefaultVolumeProfile.asset @@ -37,13 +37,13 @@ MonoBehaviour: active: 1 shadows: m_OverrideState: 1 - m_Value: {r: 0.5458793, g: 0.6841803, b: 0.8207547, a: 1} + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} highlights: m_OverrideState: 1 - m_Value: {r: 0.9811321, g: 0.7474893, b: 0.50445, a: 1} + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} balance: m_OverrideState: 1 - m_Value: -25 + m_Value: 0 --- !u!114 &-8104416584915340131 MonoBehaviour: m_ObjectHideFlags: 3 @@ -161,10 +161,10 @@ MonoBehaviour: active: 1 postExposure: m_OverrideState: 1 - m_Value: -0.2 + m_Value: 0 contrast: m_OverrideState: 1 - m_Value: 20 + m_Value: 0 colorFilter: m_OverrideState: 1 m_Value: {r: 1, g: 1, b: 1, a: 1} @@ -173,7 +173,7 @@ MonoBehaviour: m_Value: 0 saturation: m_OverrideState: 1 - m_Value: -25 + m_Value: 0 --- !u!114 &-6288072647309666549 MonoBehaviour: m_ObjectHideFlags: 3 @@ -192,7 +192,7 @@ MonoBehaviour: m_Value: 0 intensity: m_OverrideState: 1 - m_Value: 0.3 + m_Value: 0 response: m_OverrideState: 1 m_Value: 0.8 @@ -214,7 +214,7 @@ MonoBehaviour: active: 1 mode: m_OverrideState: 1 - m_Value: 2 + m_Value: 0 neutralHDRRangeReductionMode: m_OverrideState: 1 m_Value: 2 @@ -363,10 +363,10 @@ MonoBehaviour: m_Value: 1 threshold: m_OverrideState: 1 - m_Value: 0.7 + m_Value: 0.9 intensity: m_OverrideState: 1 - m_Value: 1 + m_Value: 0 scatter: m_OverrideState: 1 m_Value: 0.7 @@ -410,10 +410,10 @@ MonoBehaviour: active: 1 temperature: m_OverrideState: 1 - m_Value: -8 + m_Value: 0 tint: m_OverrideState: 1 - m_Value: 5 + m_Value: 0 --- !u!114 &-581120513425526550 MonoBehaviour: m_ObjectHideFlags: 3 @@ -855,7 +855,7 @@ MonoBehaviour: active: 1 intensity: m_OverrideState: 1 - m_Value: 0.1 + m_Value: 0 --- !u!114 &6940869943325143175 MonoBehaviour: m_ObjectHideFlags: 3 @@ -890,7 +890,7 @@ MonoBehaviour: m_Value: {x: 0.5, y: 0.5} intensity: m_OverrideState: 1 - m_Value: 0.35 + m_Value: 0 smoothness: m_OverrideState: 1 m_Value: 0.2 diff --git a/Assets/_Project/Settings/Render Settings/URP-High.asset b/Assets/_Project/Settings/Render Settings/URP-High.asset index 330830a..074ee15 100644 --- a/Assets/_Project/Settings/Render Settings/URP-High.asset +++ b/Assets/_Project/Settings/Render Settings/URP-High.asset @@ -45,7 +45,7 @@ MonoBehaviour: m_MainLightShadowsSupported: 1 m_MainLightShadowmapResolution: 4096 m_AdditionalLightsRenderingMode: 1 - m_AdditionalLightsPerObjectLimit: 6 + m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightShadowsSupported: 1 m_AdditionalLightsShadowmapResolution: 4096 m_AdditionalLightsShadowResolutionTierLow: 256 diff --git a/Assets/_Project/Settings/Render Settings/URP-Medium.asset b/Assets/_Project/Settings/Render Settings/URP-Medium.asset index c5c5444..3b9f2ab 100644 --- a/Assets/_Project/Settings/Render Settings/URP-Medium.asset +++ b/Assets/_Project/Settings/Render Settings/URP-Medium.asset @@ -45,7 +45,7 @@ MonoBehaviour: m_MainLightShadowsSupported: 1 m_MainLightShadowmapResolution: 2048 m_AdditionalLightsRenderingMode: 1 - m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightShadowsSupported: 1 m_AdditionalLightsShadowmapResolution: 2048 m_AdditionalLightsShadowResolutionTierLow: 256 diff --git a/Assets/_Project/Settings/Render Settings/URP-Ultra.asset b/Assets/_Project/Settings/Render Settings/URP-Ultra.asset index 46ffed0..9564d20 100644 --- a/Assets/_Project/Settings/Render Settings/URP-Ultra.asset +++ b/Assets/_Project/Settings/Render Settings/URP-Ultra.asset @@ -45,7 +45,7 @@ MonoBehaviour: m_MainLightShadowsSupported: 1 m_MainLightShadowmapResolution: 8192 m_AdditionalLightsRenderingMode: 1 - m_AdditionalLightsPerObjectLimit: 8 + m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightShadowsSupported: 1 m_AdditionalLightsShadowmapResolution: 8192 m_AdditionalLightsShadowResolutionTierLow: 256 diff --git a/Assets/_Recovery.meta b/Assets/_Recovery.meta deleted file mode 100644 index 701aa9b..0000000 --- a/Assets/_Recovery.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4da4faa336600407eba8a8b842ddebe1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json index 6269d02..5343bc8 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -4,7 +4,7 @@ "com.unity.cinemachine": "3.1.6", "com.unity.collab-proxy": "2.12.4", "com.unity.entities.graphics": "6.4.0", - "com.unity.ide.rider": "3.0.40", + "com.unity.ide.rider": "3.0.39", "com.unity.ide.visualstudio": "2.0.27", "com.unity.inputsystem": "1.19.0", "com.unity.multiplayer.center": "1.0.1", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index a89bbf9..e619138 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -86,7 +86,7 @@ "dependencies": {} }, "com.unity.ide.rider": { - "version": "3.0.40", + "version": "3.0.39", "depth": 0, "source": "registry", "dependencies": { diff --git a/ProjectSettings/Packages/com.unity.probuilder/Settings.json b/ProjectSettings/Packages/com.unity.probuilder/Settings.json index f70e4ce..c46a6fa 100644 --- a/ProjectSettings/Packages/com.unity.probuilder/Settings.json +++ b/ProjectSettings/Packages/com.unity.probuilder/Settings.json @@ -155,6 +155,11 @@ "type": "UnityEngine.ProBuilder.RectSelectMode, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "key": "editor.dragSelectRectMode", "value": "{\"m_Value\":0}" + }, + { + "type": "UnityEditor.ProBuilder.Actions.ExportAssetOptions, Unity.ProBuilder.Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", + "key": "export.assetOptions", + "value": "{\"m_Value\":{\"makePrefab\":false,\"replaceOriginal\":false}}" } ] }