Adding Post Processing and lights to the tesla tower #9

Merged
matt merged 1 commit from feature/post-processing into main 2026-06-30 13:17:33 -07:00
8 changed files with 241 additions and 106 deletions
Showing only changes of commit 587fc46f1a - Show all commits

View file

@ -105,7 +105,7 @@ Material:
- _AddPrecomputedVelocity: 0 - _AddPrecomputedVelocity: 0
- _AlphaClip: 0 - _AlphaClip: 0
- _AlphaToMask: 0 - _AlphaToMask: 0
- _Blend: 0 - _Blend: 2
- _BlendModePreserveSpecular: 1 - _BlendModePreserveSpecular: 1
- _BumpScale: 1 - _BumpScale: 1
- _ClearCoatMask: 0 - _ClearCoatMask: 0
@ -114,8 +114,8 @@ Material:
- _Cutoff: 0.5 - _Cutoff: 0.5
- _DetailAlbedoMapScale: 1 - _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 10 - _DstBlend: 1
- _DstBlendAlpha: 10 - _DstBlendAlpha: 1
- _EnvironmentReflections: 1 - _EnvironmentReflections: 1
- _GlossMapScale: 0 - _GlossMapScale: 0
- _Glossiness: 0 - _Glossiness: 0

View file

@ -12226,55 +12226,6 @@ Mesh:
- serializedVersion: 1 - serializedVersion: 1
m_IndexStart: 0 m_IndexStart: 0
m_IndexCount: 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 --- !u!1 &839198900
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -28745,7 +28696,6 @@ SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_Roots: m_Roots:
- {fileID: 410087041} - {fileID: 410087041}
- {fileID: 832575519}
- {fileID: 441239881} - {fileID: 441239881}
- {fileID: 167151709} - {fileID: 167151709}
- {fileID: 1507514109} - {fileID: 1507514109}

View file

@ -6,35 +6,92 @@ namespace TD.Combat
{ {
/// <summary> /// <summary>
/// Local-only electrical-arc visual for <see cref="TD.Core.TargetType.AllInRange"/> /// Local-only electrical-arc visual for <see cref="TD.Core.TargetType.AllInRange"/>
/// towers (Tesla Coil). Subscribes to <see cref="TowerCombat.OnAreaFired"/> and draws a /// towers (Tesla Coil). Subscribes to <see cref="TowerCombat.OnAreaFired"/> and draws an
/// jagged line from the tower's emitter point to every enemy hit, flashed for a moment. /// 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.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Pure visualization — runs on every peer from the replicated fire broadcast; nothing /// Pure visualization — runs on every peer from the replicated fire broadcast; nothing
/// here is networked. Arcs are pooled <see cref="LineRenderer"/>s reused across ticks. /// here is networked. Bolts are pooled <see cref="LineRenderer"/>s reused across ticks.
/// The glow (bloom) comes from the material + an HDR color above the bloom threshold; see
/// <see cref="emissionIntensity"/> and the project's post-processing Volume.
/// </remarks> /// </remarks>
[RequireComponent(typeof(TowerCombat))] [RequireComponent(typeof(TowerCombat))]
public class TeslaArcVisual : MonoBehaviour public class TeslaArcVisual : MonoBehaviour
{ {
[Tooltip("Point the arcs originate from — the central top of the coil. " + [Tooltip("Point the bolts originate from — the central top of the coil. " +
"If unset, falls back to one unit above the tower root.")] "If unset, falls back to one unit above the tower root.")]
[SerializeField] private Transform emitter; [SerializeField] private Transform emitter;
[Tooltip("Material for the arc lines. Assign an unlit/additive material for a glow. " + [Tooltip("Material for the bolts. Use an UNLIT ADDITIVE material for a convincing " +
"If unset, a fallback Sprites/Default material is created at runtime.")] "glow (a Lit material won't bloom well on a thin line). If unset, a fallback " +
"additive material is created at runtime.")]
[SerializeField] private Material arcMaterial; [SerializeField] private Material arcMaterial;
[SerializeField] private Color arcColor = new Color(0.6f, 0.85f, 1f, 1f); [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 float arcWidth = 0.06f; [SerializeField] private float arcWidth = 0.06f;
[Tooltip("How long each arc flash stays visible, in seconds.")]
[Tooltip("How long each flash stays visible, in seconds.")]
[SerializeField] private float arcDuration = 0.12f; [SerializeField] private float arcDuration = 0.12f;
[Tooltip("Number of points per arc. More = more jagged detail.")]
[SerializeField] private int segmentsPerArc = 6; [Tooltip("Points per bolt. More = smoother arc and finer crackle. ~12-20 looks good.")]
[Tooltip("Random offset applied to interior arc points for the lightning look.")] [SerializeField] private int segmentsPerArc = 16;
[SerializeField] private float jitter = 0.2f;
[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;
private TowerCombat combat; private TowerCombat combat;
private readonly List<LineRenderer> pool = new List<LineRenderer>(); private readonly List<LineRenderer> pool = new List<LineRenderer>();
private Light flashLight;
private readonly List<Light> impactLightPool = new List<Light>();
// 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 float hideAt = -1f;
private void Awake() => combat = GetComponent<TowerCombat>(); private void Awake() => combat = GetComponent<TowerCombat>();
@ -51,31 +108,120 @@ namespace TD.Combat
private void Update() private void Update()
{ {
if (hideAt >= 0f && Time.time >= hideAt) if (!active) return;
if (Time.time >= hideAt)
{ {
for (int i = 0; i < pool.Count; i++) pool[i].enabled = false; HideAll();
hideAt = -1f; active = false;
return;
} }
// Re-draw every frame with fresh jitter so the bolts crackle while visible.
RedrawBolts();
} }
private void HandleAreaFired(Vector3[] positions) private void HandleAreaFired(Vector3[] positions)
{ {
if (positions == null) return; if (positions == null || positions.Length == 0) 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; Vector3 origin = emitter != null ? emitter.position : transform.position + Vector3.up;
for (int i = 0; i < positions.Length; i++) for (int i = 0; i < activeCount; i++)
{ {
var lr = GetLine(i); var lr = GetLine(i);
DrawArc(lr, origin, positions[i]); DrawBolt(lr, origin, activeTargets[i]);
lr.enabled = true; lr.enabled = true;
} }
// Disable any leftover lines from a previous, larger tick. // Disable any leftover bolts from a previous, larger tick.
for (int i = positions.Length; i < pool.Count; i++) for (int i = activeCount; i < pool.Count; i++)
pool[i].enabled = false; pool[i].enabled = false;
hideAt = Time.time + arcDuration; // 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<Light>();
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<Light>();
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;
} }
private LineRenderer GetLine(int index) private LineRenderer GetLine(int index)
@ -84,33 +230,74 @@ namespace TD.Combat
{ {
var go = new GameObject($"Arc_{pool.Count}"); var go = new GameObject($"Arc_{pool.Count}");
go.transform.SetParent(transform, worldPositionStays: false); go.transform.SetParent(transform, worldPositionStays: false);
var lr = go.AddComponent<LineRenderer>(); var lr = go.AddComponent<LineRenderer>();
lr.useWorldSpace = true; lr.useWorldSpace = true;
lr.widthMultiplier = arcWidth; lr.widthMultiplier = arcWidth;
lr.numCapVertices = 2; lr.numCapVertices = 4;
lr.numCornerVertices = 4;
lr.alignment = LineAlignment.View; // face the camera, like a billboard
lr.textureMode = LineTextureMode.Stretch; lr.textureMode = LineTextureMode.Stretch;
lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
lr.material = arcMaterial != null lr.material = arcMaterial != null ? arcMaterial : CreateFallbackMaterial();
? arcMaterial
: new Material(Shader.Find("Sprites/Default")); // HDR color so Bloom in the post stack picks the bolt up as a glow.
lr.startColor = lr.endColor = arcColor; Color hdr = arcColor * Mathf.Max(1f, emissionIntensity);
hdr.a = 1f;
lr.startColor = lr.endColor = hdr;
lr.enabled = false; lr.enabled = false;
pool.Add(lr); pool.Add(lr);
} }
return pool[index]; return pool[index];
} }
private void DrawArc(LineRenderer lr, Vector3 a, Vector3 b) // 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)
{ {
int n = Mathf.Max(2, segmentsPerArc); int n = Mathf.Max(2, segmentsPerArc);
lr.positionCount = n; 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++) for (int s = 0; s < n; s++)
{ {
float t = s / (float)(n - 1); float t = s / (float)(n - 1);
Vector3 p = Vector3.Lerp(a, b, t); Vector3 p = a + delta * t;
// Jitter interior points only — endpoints stay anchored to the coil and enemy.
// 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.
if (s != 0 && s != n - 1) if (s != 0 && s != n - 1)
p += Random.insideUnitSphere * jitter; {
p += bowDir * (Random.Range(-jitter, jitter) * curve);
p += sideDir * (Random.Range(-jitter, jitter) * curve);
}
lr.SetPosition(s, p); lr.SetPosition(s, p);
} }
} }

View file

@ -473,8 +473,6 @@ namespace TD.Combat
{ {
var multiplier = GetOwnerBuffManager()?.GetMultiplier(BuffStat.Damage) ?? 1f; var multiplier = GetOwnerBuffManager()?.GetMultiplier(BuffStat.Damage) ?? 1f;
float effectiveDamage = p.Damage * multiplier; float effectiveDamage = p.Damage * multiplier;
Debug.Log("multiplier: " + multiplier);
Debug.Log("Effective damage: " + effectiveDamage);
target.TakeDamage(effectiveDamage, p.DamageType, owner); target.TakeDamage(effectiveDamage, p.DamageType, owner);
ApplyStatusEffect(p, target, owner); ApplyStatusEffect(p, target, owner);
} }

View file

@ -37,13 +37,13 @@ MonoBehaviour:
active: 1 active: 1
shadows: shadows:
m_OverrideState: 1 m_OverrideState: 1
m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_Value: {r: 0.5458793, g: 0.6841803, b: 0.8207547, a: 1}
highlights: highlights:
m_OverrideState: 1 m_OverrideState: 1
m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_Value: {r: 0.9811321, g: 0.7474893, b: 0.50445, a: 1}
balance: balance:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: -25
--- !u!114 &-8104416584915340131 --- !u!114 &-8104416584915340131
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 3 m_ObjectHideFlags: 3
@ -161,10 +161,10 @@ MonoBehaviour:
active: 1 active: 1
postExposure: postExposure:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: -0.2
contrast: contrast:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 20
colorFilter: colorFilter:
m_OverrideState: 1 m_OverrideState: 1
m_Value: {r: 1, g: 1, b: 1, a: 1} m_Value: {r: 1, g: 1, b: 1, a: 1}
@ -173,7 +173,7 @@ MonoBehaviour:
m_Value: 0 m_Value: 0
saturation: saturation:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: -25
--- !u!114 &-6288072647309666549 --- !u!114 &-6288072647309666549
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 3 m_ObjectHideFlags: 3
@ -192,7 +192,7 @@ MonoBehaviour:
m_Value: 0 m_Value: 0
intensity: intensity:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 0.3
response: response:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0.8 m_Value: 0.8
@ -214,7 +214,7 @@ MonoBehaviour:
active: 1 active: 1
mode: mode:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 2
neutralHDRRangeReductionMode: neutralHDRRangeReductionMode:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 2 m_Value: 2
@ -363,10 +363,10 @@ MonoBehaviour:
m_Value: 1 m_Value: 1
threshold: threshold:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0.9 m_Value: 0.7
intensity: intensity:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 1
scatter: scatter:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0.7 m_Value: 0.7
@ -410,10 +410,10 @@ MonoBehaviour:
active: 1 active: 1
temperature: temperature:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: -8
tint: tint:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 5
--- !u!114 &-581120513425526550 --- !u!114 &-581120513425526550
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 3 m_ObjectHideFlags: 3
@ -855,7 +855,7 @@ MonoBehaviour:
active: 1 active: 1
intensity: intensity:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 0.1
--- !u!114 &6940869943325143175 --- !u!114 &6940869943325143175
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 3 m_ObjectHideFlags: 3
@ -890,7 +890,7 @@ MonoBehaviour:
m_Value: {x: 0.5, y: 0.5} m_Value: {x: 0.5, y: 0.5}
intensity: intensity:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0 m_Value: 0.35
smoothness: smoothness:
m_OverrideState: 1 m_OverrideState: 1
m_Value: 0.2 m_Value: 0.2

View file

@ -45,7 +45,7 @@ MonoBehaviour:
m_MainLightShadowsSupported: 1 m_MainLightShadowsSupported: 1
m_MainLightShadowmapResolution: 4096 m_MainLightShadowmapResolution: 4096
m_AdditionalLightsRenderingMode: 1 m_AdditionalLightsRenderingMode: 1
m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightsPerObjectLimit: 6
m_AdditionalLightShadowsSupported: 1 m_AdditionalLightShadowsSupported: 1
m_AdditionalLightsShadowmapResolution: 4096 m_AdditionalLightsShadowmapResolution: 4096
m_AdditionalLightsShadowResolutionTierLow: 256 m_AdditionalLightsShadowResolutionTierLow: 256

View file

@ -45,7 +45,7 @@ MonoBehaviour:
m_MainLightShadowsSupported: 1 m_MainLightShadowsSupported: 1
m_MainLightShadowmapResolution: 2048 m_MainLightShadowmapResolution: 2048
m_AdditionalLightsRenderingMode: 1 m_AdditionalLightsRenderingMode: 1
m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightsPerObjectLimit: 4
m_AdditionalLightShadowsSupported: 1 m_AdditionalLightShadowsSupported: 1
m_AdditionalLightsShadowmapResolution: 2048 m_AdditionalLightsShadowmapResolution: 2048
m_AdditionalLightsShadowResolutionTierLow: 256 m_AdditionalLightsShadowResolutionTierLow: 256

View file

@ -45,7 +45,7 @@ MonoBehaviour:
m_MainLightShadowsSupported: 1 m_MainLightShadowsSupported: 1
m_MainLightShadowmapResolution: 8192 m_MainLightShadowmapResolution: 8192
m_AdditionalLightsRenderingMode: 1 m_AdditionalLightsRenderingMode: 1
m_AdditionalLightsPerObjectLimit: 2 m_AdditionalLightsPerObjectLimit: 8
m_AdditionalLightShadowsSupported: 1 m_AdditionalLightShadowsSupported: 1
m_AdditionalLightsShadowmapResolution: 8192 m_AdditionalLightsShadowmapResolution: 8192
m_AdditionalLightsShadowResolutionTierLow: 256 m_AdditionalLightsShadowResolutionTierLow: 256