MiniGames/Assets/Scripts/ChaseOn/ChaseLaserBeam.cs

260 lines
7.8 KiB
C#
Raw Permalink Normal View History

2025-09-11 18:46:20 +05:00
using System.Collections;
using UnityEngine;
2025-08-19 16:59:43 +05:00
[RequireComponent(typeof(LineRenderer))]
public class ChaseLaserBeam : MonoBehaviour
{
[Header("Laser Setup")]
public Transform laserOrigin;
public float maxDistance = 20f;
public LayerMask collisionMask;
public Color laserColor = Color.red;
public float laserWidth = 0.05f;
[Header("Visuals")]
public float scrollSpeed = 1f;
public float emissionStrength = 5f;
[Header("Performance")]
public float updateRate = 0.02f;
2025-09-11 18:46:20 +05:00
[Header("Pulse (On/Off)")]
public bool pulsing = true;
public bool startOn = true;
2025-09-22 17:26:19 +05:00
public float onDuration = 1.5f;
public float offDuration = 1.5f;
public float fadeIn = 0.15f;
public float fadeOut = 0.15f;
2025-09-11 18:46:20 +05:00
public float startDelay = 0f;
2025-09-22 17:26:19 +05:00
public float randomStartOffset = 0f;
2025-09-11 18:46:20 +05:00
[Header("Lethality")]
[Range(0f, 1f)] public float lethalThreshold = 0.9f;
2025-08-19 16:59:43 +05:00
private LineRenderer line;
private Vector3 laserStart, laserEnd;
2025-09-11 18:46:20 +05:00
private Material matInstance;
2025-09-22 17:26:19 +05:00
private float currentIntensity = 0f;
private bool isActiveVisual = false;
private bool isEnabled = false;
2025-09-11 18:46:20 +05:00
private Coroutine pulseCo;
2025-08-19 16:59:43 +05:00
void Awake()
{
line = GetComponent<LineRenderer>();
SetupLaserRenderer();
}
void OnEnable()
{
2025-09-11 18:46:20 +05:00
isEnabled = true;
2025-08-19 16:59:43 +05:00
line.enabled = true;
InvokeRepeating(nameof(UpdateLaser), 0f, updateRate);
2025-09-11 18:46:20 +05:00
2025-09-22 17:26:19 +05:00
if (pulsing) pulseCo = StartCoroutine(PulseRoutine());
2025-09-11 18:46:20 +05:00
else
{
currentIntensity = 1f;
isActiveVisual = true;
ApplyIntensity(currentIntensity);
}
2025-08-19 16:59:43 +05:00
}
void OnDisable()
{
2025-09-11 18:46:20 +05:00
isEnabled = false;
2025-08-19 16:59:43 +05:00
CancelInvoke(nameof(UpdateLaser));
2025-09-11 18:46:20 +05:00
if (pulseCo != null) StopCoroutine(pulseCo);
if (line != null) line.enabled = false;
2025-08-19 16:59:43 +05:00
}
void UpdateLaser()
{
2025-09-11 18:46:20 +05:00
if (!isActiveVisual || currentIntensity <= 0.001f)
{
if (line.enabled) line.enabled = false;
return;
}
2025-08-19 16:59:43 +05:00
laserStart = laserOrigin ? laserOrigin.position : transform.position;
Vector3 direction = transform.forward;
if (Physics.Raycast(laserStart, direction, out RaycastHit hit, maxDistance, collisionMask))
{
laserEnd = hit.point;
2025-09-22 17:26:19 +05:00
if (/*currentIntensity >= lethalThreshold && */hit.collider.CompareTag("Player"))
2025-08-19 16:59:43 +05:00
{
2025-09-22 17:26:19 +05:00
// Use Shared_DieZibu for laser kill
var die = hit.collider.GetComponent<Shared_DieZibu>() ?? hit.collider.GetComponentInParent<Shared_DieZibu>();
if (die != null)
{
// optional: stop the runners local movement flags if present
var runner = die.GetComponent<ChasePlayerController>();
if (runner != null)
{
runner.StartCoroutine(runner.PlayStateAndGameOver(runner.fallingStateName, runner.fallingShortHash));
}
die.KillByLaser();
}
else
2025-08-19 16:59:43 +05:00
{
2025-09-22 17:26:19 +05:00
// Fallback: if no Shared_DieZibu found, keep old behavior (optional)
var runner = hit.collider.GetComponent<ChasePlayerController>() ?? hit.collider.GetComponentInParent<ChasePlayerController>();
if (runner != null /*&& !runner.waitingForGameOver*/)
{
runner.moveSpeed = 0;
runner.waitingForGameOver = true;
runner.StartCoroutine(runner.PlayStateAndGameOver(runner.fallingStateName, runner.fallingShortHash));
}
2025-08-19 16:59:43 +05:00
}
}
}
else
{
laserEnd = laserStart + direction * maxDistance;
}
2025-09-11 18:46:20 +05:00
if (!line.enabled) line.enabled = true;
2025-08-19 16:59:43 +05:00
line.SetPosition(0, laserStart);
line.SetPosition(1, laserEnd);
}
void SetupLaserRenderer()
{
line.useWorldSpace = true;
line.positionCount = 2;
line.loop = false;
line.widthMultiplier = laserWidth;
line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
line.receiveShadows = false;
Shader laserShader = Shader.Find("Custom/EmissiveLaser");
if (laserShader != null)
{
2025-09-11 18:46:20 +05:00
matInstance = new Material(laserShader);
matInstance.SetColor("_Color", laserColor);
matInstance.SetFloat("_Emission", 0f);
matInstance.SetFloat("_ScrollSpeed", scrollSpeed);
line.material = matInstance;
2025-08-19 16:59:43 +05:00
}
else
{
2025-09-11 18:46:20 +05:00
matInstance = new Material(Shader.Find("Sprites/Default"));
2025-09-22 17:26:19 +05:00
matInstance.color = laserColor * 0f;
2025-09-11 18:46:20 +05:00
line.material = matInstance;
2025-08-19 16:59:43 +05:00
}
line.startColor = laserColor;
line.endColor = laserColor;
}
2025-09-11 18:46:20 +05:00
IEnumerator PulseRoutine()
{
float jitter = (randomStartOffset > 0f) ? Random.Range(-randomStartOffset, randomStartOffset) : 0f;
if (startDelay + jitter > 0f) yield return new WaitForSeconds(startDelay + jitter);
bool stateOn = startOn;
while (isEnabled)
{
if (stateOn)
{
if (fadeIn > 0f) yield return FadeIntensity(1f, fadeIn);
else { currentIntensity = 1f; ApplyIntensity(currentIntensity); }
2025-09-22 17:26:19 +05:00
isActiveVisual = true;
2025-09-11 18:46:20 +05:00
if (onDuration > 0f) yield return new WaitForSeconds(onDuration);
}
else
{
if (fadeOut > 0f) yield return FadeIntensity(0f, fadeOut);
else { currentIntensity = 0f; ApplyIntensity(currentIntensity); }
2025-09-22 17:26:19 +05:00
isActiveVisual = false;
2025-09-11 18:46:20 +05:00
if (offDuration > 0f) yield return new WaitForSeconds(offDuration);
}
stateOn = !stateOn;
}
}
IEnumerator FadeIntensity(float target, float time)
{
float start = currentIntensity;
float t = 0f;
isActiveVisual = (target > 0f) || (start > 0f);
while (t < 1f)
{
t += Time.deltaTime / Mathf.Max(0.0001f, time);
currentIntensity = Mathf.Lerp(start, target, t);
ApplyIntensity(currentIntensity);
yield return null;
}
currentIntensity = target;
ApplyIntensity(currentIntensity);
if (currentIntensity <= 0.001f && line.enabled) line.enabled = false;
}
void ApplyIntensity(float normalized)
{
line.widthMultiplier = Mathf.Max(0.0001f, laserWidth * Mathf.Lerp(0.35f, 1f, normalized));
if (matInstance != null)
{
if (matInstance.HasProperty("_Emission"))
{
matInstance.SetFloat("_Emission", emissionStrength * normalized);
}
else
{
Color c = laserColor;
c.a = Mathf.Clamp01(normalized);
matInstance.color = c;
}
}
}
public void SetPulsing(bool enabled)
{
pulsing = enabled;
if (!isEnabled) return;
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
2025-09-22 17:26:19 +05:00
if (pulsing) pulseCo = StartCoroutine(PulseRoutine());
2025-09-11 18:46:20 +05:00
else
{
currentIntensity = 1f;
ApplyIntensity(currentIntensity);
isActiveVisual = true;
}
}
public void ForceOff()
{
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
pulsing = false;
currentIntensity = 0f;
ApplyIntensity(0f);
isActiveVisual = false;
if (line) line.enabled = false;
}
public void ForceOn()
{
if (pulseCo != null) { StopCoroutine(pulseCo); pulseCo = null; }
pulsing = false;
currentIntensity = 1f;
ApplyIntensity(1f);
isActiveVisual = true;
if (line && !line.enabled) line.enabled = true;
}
2025-08-19 16:59:43 +05:00
}