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/Scenes/Levels/9Player.unity b/Assets/_Project/Scenes/Levels/9Player.unity index 32942ce..76b7f7f 100644 --- a/Assets/_Project/Scenes/Levels/9Player.unity +++ b/Assets/_Project/Scenes/Levels/9Player.unity @@ -12226,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 @@ -28696,6 +28745,7 @@ SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 410087041} + - {fileID: 832575519} - {fileID: 441239881} - {fileID: 167151709} - {fileID: 1507514109} 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/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